How to Iterate Activerecord Attributes, Including Attr_Accessor Methods

How to iterate ActiveRecord Attributes, including attr_accessor methods

You can't really solve this. You can approximate a hack, but it's not something that will ever work nicely.

model.attribute_names should get you all the ActiveRecord ones, but the attr_accessor fields are not fields. They are just ordinary ruby methods, and the only way to get them is with model.instance_methods.

Idea 1

You could do model.attribute_names + model.instance_methods, but then you'd have to filter out all your other normal ruby methods initialize, save, etc which would be impractical.

To help filter the instance_methods you could match them up against model.instance_variables (you'd have to account for the @ sign in the instance variables manually), but the problem with this is that instance variables don't actually exist at all until they are first assigned.

Idea 2

In your environment.rb, before anything else ever gets loaded, define your own self.attr_accessor in ActiveRecord::Base. This could then wrap the underlying attr_accessor but also save the attribute names to a private list. Then you'd be able to pull out of this list later on. However I'd advise against this... monkey-patching core language facilities like attr_accessor is guaranteed to bring you a lot of pain.

Idea 3

Define your own custom_attr_accessor in ActiveRecord::Base, which does the same thing as Idea 2, and use it in your code where you want to be able to retrieve the attribute names. This would be safe as you won't be clobbering the built-in attr_accessor method any more, but you'll have to change all your code to use custom_attr_accessor where neccessary

I guess in summary, what are you trying to do that needs to know about all the attr_accessor fields? Try look at your problem from a different angle if you can.

How do you output all attributes including attr_accessor attributes?

I don't believe it what you're trying to do is easily possible to do.

See this question:

How to iterate ActiveRecord Attributes, including attr_accessor methods

Looping over attributes of object of a Non-Active-Record-Model

This is the best way I found

item=self.instance_values.symbolize_keys
item.each do |k,v|
...
..
end

There is a code to show it's usage here (look at the update in the question itself) - Grouping via an element in hash

Accessing attr_accessor attributes with variable

you can use

 week.send("#{dayname}=", schedule.day == dayname_index ? "Open" : "Closed")

Or you can work with it like instance_variables

week.instance_variable_set("@#{dayname}", schedule.day == dayname_index ? "Open" : "Closed")

how to access attr_accessor in rails model using `attribute_names` method

First of all if you don't know difference b/w attr_acessabe and attr_accessor look at

How to iterate ActiveRecord Attributes, including attr_accessor methods

you can add attr_accessor if you don't an attribute to save in database then add that att_accessor to attr_accessable :)

attr_accessor :color
attr_accessible :color

now

User.accessible_attributes # => ["color"], but beware that you have lost all other attribute you need to add those too if you want to enable mass assignment. 

attr_accessible :color,:first_name,:blah,:blah...

Loop through all public attributes in a model

You probably have more allowed attributes than disallowed, so I would create an array of protected attribute names and ignore those when looping through the attributes.

protected_attributes = %w(password salt confirmation_token)

user.attributes.each do |name, value|
unless protected_attributes.include?(name)
something(name, value)
end
end

How to get calculated value in hash (attr_accessor) within ActiveRecord query in rails 4?

I would simply define a method that returns the record as a hash. It uses the attributes method from ActiveRecord and manually adds the calculated attribute to the hash:

class Task < ActiveRecord::Base
attr_reader :overall_rating

def overall_rating
# returns calculated value, the following is a simple example of a calculation
id + 100
end

def to_h
attributes.merge("overall_rating" => overall_rating)
end
end

Also note that I changed attr_accessor to attr_reader as you probably don't want to have a setter defined for the calculated value.

Example:

t = Task.find(5)
t.to_h
# => { "id" => 5, "overall_rating" => 105 }

Rails - attr_accessor :- read the attribute value instead of the function overriding it

attr_accessor defines a instance variable and a method to access it (read/write).

So the easy way is to write:

def open_ledger_account
create_ledger_account!(opening_balance: @opening_balance)
end

The read_attribute would only work if opening_balance was an attribute in the database on Customer.

ruby on rail - problem with attr_accessor in model

attr_accessor is a class level method. You are trying to use it on an instance level.

Try cattr_accessor instead. Although you dont need an attr_accessor orcattr_accessor to access attributes of anActiveRecord::Base model that are defined in the schema.

====> EDIT <==== Corrected Answer Below

Disregard the advice above. It's not accurate. Im leaving it for reference. The reason you are getting the undefined method: name error is because you have set an attr_accessor on a model that already has a getter set dynamically via ActiveRecord::Base.

Setting attr_accessor on an attribute of an ActiveRecord::Base models DB column causes some sort of conflict. When you remove the attr_accessor method and instead add whats supposed to be its exact equivalent...

def name
name
end

and then try to call that you get an infinitely recursive looping of your call because the .name getter method we defined above is calling itself and not accessing the ActiveRecord getter method that actually pulls data from your DB.

Im guessing that somehow active_record model classes will just throw you an undefined method error rather than make the recursive call that ends in a stack level too deep error.

However since you arent getting a stack too deep error my next guess is that the attr_accessor you defined overrides the dynamically created ActiveRecord::Base getter while rails is still attempting to access the overridden method ( which dosnt exist anymore ). Possibly resulting in the undefined method 'name' error.

But...

When you add your own getter method this way... then it works...

def name
super
end

this is because with super your class is just inheriting the behavior of its dynamically defined ActiveRecord::Base getter method. You can test this by adding...

def name
super
'Foo'
end

And when you call @model.name you'll see that Foo is returned. Remove the 'Foo' from the method and what you have being returned is a super call to the dynamically created ActiveRecord::Base getter method.

Im open to edits and input on this answer. This is my logical conclusion from testing in my console and doing some reading.

When to use attr_accessor

Also, to answer your question further about when to use attr_accessor...

You would use this when you want to create and store information that is business-logic as well as model related, and only lasts for the duration of the request/instance life cycle.

For example raw passwords ( although I cringe at anyone manipulating raw passwords )

or something like...

@stock.current_price

where @stock is a ActiveRecord::Base object but .current_price is calculated or retrieved from an API upon instantiation of the @stock object because it doesn't make sense to persist and retrieve from the DB an ever changing value such as the price of a stock at any given point in time.



Related Topics



Leave a reply



Submit