The simple way to loop over all attributes of an object when using Active Record is
order_item_object.attributes.each do |key,value|
....
end
But this doesn't work, when we are not using Active Record. How can I iterate over all the attributes of an object then?
For eg -: I have a model in Rails which does not use active record. The object from model order_item can be used in the controller like order_item_object.product_id, order_item_object.quantity, order_item_object.quoted_price. But when I try to order_item_object.attributes.each do |k,v|
...., I get undefined method "attributes" for #<Order:0x00000005aa81b0>
How should I go about this?
try this:
class Parent
def self.attr_accessor(*vars)
@attributes ||= []
@attributes.concat vars
super(*vars)
end
def self.attributes
@attributes
end
def attributes
self.class.attributes
end
end
class ChildClass < Parent
attr_accessor :id, :title, :body
end
p ChildClass.new.attributes.inspect #=> [:id, :title, :body]
attr_accessor
is simply a macro that creates some methods to set an instance variable. SO perhaps what you want is the instance_variables
method, which returns an array of instance variables that you can iterate through
class Foo
attr_accessor :bar
attr_accessor :baz
end
foo = Foo.new
foo.bar = 123
foo.baz
foo.instance_variables.each do |ivar_name|
ivar_value = foo.instance_variable_get ivar_name
# do something with ivar_name and ivar_value
end
But I wouldn't really recommend this. ActiveRecord keeps model data separate for a reason. Your instance may have lots of uses for instance variables. For instance, perhaps you want to track if the record is saved yet or not. This may be kept in @saved
variable, which reflects the state of the instance but not the data of the model.
Perhaps you want to keep a hash of attributes instead?
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
If you want the string representations of your instance variables, you can do:
self.instance_values.keys.each do |k|
..
end
That should loop over all the keys (instance variable names as strings) that are defined for your class.
The attributes you are referencing is an instance variable on ActiveRecord models which returns a hash of the models db attributes.
A non-ActiveRecord model won't have the attributes method you are calling unless you defined it explicitly. All objects have a method called instance_variables which you can use to get a list of attribute names and then reflectively find the attribute values.
A not very elegant way of doing it:
class Test
attr_accessor :firstname,:lastname
def initialize(fn,ln); @firstname = fn; @lastname = ln; end
end
o = Test.new("Fernando", "Mendez")
o.instance_variables.each {|e| p o.send e.to_s.sub("@","").to_sym}
output:
"Fernando"
"Mendez"
If you want to keep a track of the key-value pair:
r = o.instance_variables.map {|e| Hash[e,(o.send e.to_s.sub("@","").to_sym)]}
#[{:@firstname=>"Fernando"}, {:@lastname=>"Mendez"}]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.