Search code examples
ruby-on-railsactiverecordauthlogic

Using a named scope


I"m trying to use a named scope to set my users carrier but keep getting this error

undefined method `target' for #<ActiveRecord::Relation:0x5ee3e40>

app/models/user.rb:19:in `set_carrier'
app/controllers/users_controller.rb:49:in `block in create' app/controllers/users_controller.rb:48:in `create'

<div class= "field">
  <%= f.label :carrier %><br>
  <%= f.collection_select(:carrier_name, Carrier.find(:all) ,:name, :name) %>
</div>

user.rb

class User < ActiveRecord::Base

  acts_as_authentic
  after_create :set_sub
  after_create :set_universal
  after_create :set_carrier

  def set_sub
    #self.roles << "subscriber"
    self.roles_mask = 4
  end

  def set_universal
      self.channels << Channel.find(1)
  end

  def set_carrier
    @carrier = Carrier.with_name(self.carrier_name)
    self.carrier<< @carrier
  end

  ROLES = %w[admin  moderator subscriber]

  #Each user can subscribe to many channels
  has_and_belongs_to_many :channels

  #Each user who is a moderator can moderate many channels
  #has_many :channel_mods
  has_and_belongs_to_many :modifies , :class_name => "Channel"

  #Each user can receive many messages
  has_and_belongs_to_many :messages

  #Each user belongs to a carrier
  belongs_to :carrier

  #Filter users by role(s)
  named_scope :with_role, lambda { |role| {:conditions => "roles_mask & #{2**ROLES.index(role.to_s)} > 0 "} }

  def roles  
    ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }  
  end

  def roles=(roles)  
    self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum  
  end

  def role_symbols
  roles.map do |role|
    role.underscore.to_sym  # NOT role.name.underscore.to_sym (role is a string)
    end
  end


end

carrier.rb

class Carrier < ActiveRecord::Base
  has_many :users

  named_scope :with_name, lambda {|name| {:conditions => {:name => name}}}


end

user controller

class UsersController < ApplicationController

   filter_resource_access

  # GET /users
  # GET /users.xml
  def index
    @users = User.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @users }
    end
  end

  # GET /users/1
  # GET /users/1.xml
  def show
    #@user = User.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @user }
    end
  end

  # GET /users/new
  # GET /users/new.xml
  def new
    #@user = User.new
    @carriers = Carrier.find(:all)

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @user }
    end
  end

  # GET /users/1/edit
  def edit
    #@user = User.find(params[:id])
  end

  def create
    #@user = User.new(params[:user])
    #@user.channels << Channel.find(1)

    respond_to do |format|
      if @user.save
        format.html { redirect_to(:channels, :notice => 'Registration successfully.') }
        format.xml { render :xml => @user, :status => :created, :location => @user }
      else
        format.html { render :action => "new" }
        format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
      end
    end
  end

  def profile
    @user = User.find(params[:id])
  end



  # PUT /users/1
  # PUT /users/1.xml
  def update
  #@user = current_user

    respond_to do |format|
      if @user.update_attributes(params[:user])
        format.html { redirect_to(@user, :notice => 'User was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.xml
  def destroy
    @user = User.find(params[:id])
    @user.destroy
    respond_to do |format|
      format.html { redirect_to(users_url) }
      format.xml  { head :ok }
    end
  end

  def delete
    @user = User.find(params[:user_id])
    @user.destroy
    redirect_to :users
  end

end

Solution

  • You might be using an array instead of a singular item. belongs_to relationships are either nil or a model.

    You may have intended to do a direct assignment:

    def set_carrier
      self.carrier = Carrier.with_name(self.carrier_name).first
    end
    

    The << operator is used to append items to arrays, but carrier is not an array. This may trip up something deeper in Rails.