I have a Rails model called Person which has database table columns for first_name and last_name. I've also defined a full_name method to return the combined first_name and last_name of the instance.
Is there a way to return an array, hash, or object which has first_name, last_name, as well as full_name?
Here's the code I have:
#person.rb
class Person < ActiveRecord::Base
validates_presence_of :first_name, :last_name
def full_name
self.first_name + " " + self.last_name
end
end
Here's what I've tried in the Rails console:
ruby-1.8.7-p302 > person = Person.new({:first_name=>"Bruce", :last_name=>"Wayne"})
=> #<Person id: nil, first_name: "Bruce", :last_name: "Wayne", created_at: nil, updated_at: nil>
ruby-1.8.7-p302 > person.save!
=> true
ruby-1.8.7-p302 > Person.last
=> #<Person id: 1, first_name: "Bruce", :last_name: "Wayne", created_at: "2010-11-09 22:53:14", updated_at: "2010-11-09 22:53:14">
Is it possible to get something returned like this instead:
ruby-1.8.7-p302 > Person.last
=> #<Person id: 1, first_name: "Bruce", :last_name: "Wayne", :full_name: "Bruce Wayne", created_at: "2010-11-09 22:53:14", updated_at: "2010-11-09 22:53:14">
Or can it only return values from the database?
Eventually, I'd like t开发者_StackOverflowo be able to call Person.all
to return an array of hashes which also includes full_name.
Thanks in advanced!
The first_name
and last_name
are DB attributes which are printed in the inspect method.
If you want to access the full_name
call full_name
on the user object.
User.last.full_name
So if you want a hash of users with full_name
as key:
@users = {}
User.all.each{|u| @users[u.full_name] = u}
Edit 1
The User.last
call returns an User
object. What gets printed in the console depends upon how the inspect method on the object is implemented. In case of ActiveRecord, database attributes are printed.
If you need the full name, you need to call the full_name
method on the returned User object.
I am still not clear what you are trying to do.
Edit 2
u = User.last
[u.full_name, u.age, u.phone] # array
{:full_name => u.full_name, :age => u.age, :phone => u.phone } #hash
Edit 3
If you want to get a JSON format out of an object do the following
u.to_json(:methods => [:full_name])
Refer to the to_json
documentation for more details.
Edit 4
The to_json method has include
and exclude
options for you to select the attributes you need. The to_json method gives you total control over data selection. Refer to the documentation link above for more details.
u.to_json(:methods => [:full_name], :include => [:first_name, :last_name])
If you need to include additional attributes, add them to the :include
array in the above example.
Edit 5
To use this along with respond_with do the following:
respond_with(@users, :methods => [:full_name],
:include => [:first_name, :last_name])
After banging my head, it looks like a way to get an array of all DB attributes plus the full_name attribute is to do:
person = Person.last.attributes
person["full_name"] = Person.last.full_name
In console this will return something like:
=> {"first_name" => "Bruce", "created_at" => Tue Nov 09 22:53:14 UTC 2010, "updated_at" => Tue Nov 09 22:53:14 UTC 2010", "id" => 58, "last_name" => "Wayne", "full_name" => "Bruce Wayne"}
You could do this for a single Person in one line with:
Person.first.instance_eval { attributes.merge("full_name" => full_name)}
Regarding your desire to Person.all and return hashes, why would you want this behavior? By default it returns an array of Person instances, and I wouldn't recommend overriding a default rails method to return a different type than you would normally expect. If you want this behavior, I would add a class method on Person, something like Person.all_hashes, that returns an array of hashes for each result.
精彩评论