开发者

How do I return an array of attributes defined via a Rails model method, as well as the attributes in the database table?

开发者 https://www.devze.com 2023-01-24 02:14 出处:网络
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.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消