1

The short version (dummy code):

So I have one ActiveRecord (rails model) class:

class User < ActiveRecord::Base
    attr_accessor :somevar
end

When I do

@u=User.find(1)
@u.somevar = 1

I get

undefined method `somevar=' for #<Class:0x007fa8cd0016a8>

I do not have a column in the database called somevar
I have restarted rails server after adding attr_accessor (just in case)
Still getting the bloody error.
Have googled alot!

Where can the error be? Any thoughts?

I appriciate all answers! Thank you!


The long version (with the actual code)

I use Devise to manage my users. Also I'm trying to add a default condition, to filter the results, on some of the models. This is based on 'company_id' which is in the User model. I tried to use the session variable in default_scope and found this. It basically says that it is bad practice to use session vars to default conditions, and I could use Devise and add some modifications.

This resulted in my User model to be

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  attr_accessor :current_company

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  belongs_to :company
end

And my ApplicationController

class ApplicationController < ActionController::Base
  around_filter :scope_current_user  

  def scope_current_user
        User.current_company = current_user.company_id
    yield
    ensure
        #avoids issues when an exception is raised, to clear the current_id
        User.current_company = nil       
  end
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead. 
  protect_from_forgery with: :exception

end

Then it raises, from the ApplicationController

undefined method `current_company=' for #<Class:0x007fa8cd0016a8>

The same happens if I define the methods manually:

def current_company
    @current_company
end
def current_company=(new_val)
    @current_company = new_val
end
Community
  • 1
  • 1

1 Answers1

1

This is not correct:

User.current_company = current_user.company_id

The attr_accessor :current_company line adds an attribute to User instances, not the User class. You could use the current_company accessor as:

current_user.current_company = # whatever

The thing you are missing from this url is that it actually uses cattr_accessible and not attr_accessor. So your model should instaed be:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  cattr_accessible :current_company

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  belongs_to :company
end

This should work.

UPDATE BASED ON LAST EDIT:

Even when you define the methods manually, you fall in the same mistake: you are defining instance methods and trying to call them as class methods. You should define them as class methods, which is done by adding self. before the names of the methods, like so:

def self.current_company
    @@current_company
end
def self.current_company=(new_val)
    @@current_company = new_val
end

Please tell me if this doesn't work.

Community
  • 1
  • 1
Tamer Shlash
  • 9,314
  • 5
  • 44
  • 82
  • Do'h. Of course. Still when I use `cattr_accessible` I get `undefined method cattr_accessible` :( – Andreas Storvik Strauman Jun 03 '14 at 00:49
  • So the literal you added last does work. However, the cattr_accessible raises an exception. Have any idea why? Thank you anyway! – Andreas Storvik Strauman Jun 03 '14 at 00:51
  • 1
    @AndreasStorvikStrauman try `cattr_accessor` instead. Still, you better stick with the manually defined methods as the [link](http://stackoverflow.com/questions/24005515/rails-3-caches-page-works-in-development-and-not-in-production) says it's the thread-safe one. – Tamer Shlash Jun 03 '14 at 00:53