Rails对象散列

我有以下创build的对象

@post = Post.create(:name => 'test', :post_number => 20, :active => true) 

一旦保存了,我希望能够将对象返回到散列,例如通过执行如下操作:

 @object.to_hash 

这在轨道内是如何实现的?

如果您只查找属性,则可以通过以下方法获取它们:

 @post.attributes 

在Rails的最新版本(不能确定哪一个),你可以使用as_json方法:

 @post = Post.first hash = @post.as_json puts hash.pretty_inspect 

会输出:

 { :name => "test", :post_number => 20, :active => true } 

为了进一步,您可以重写该方法,以便自定义您的属性出现的方式,通过做这样的事情:

 class Post < ActiveRecord::Base def as_json(*args) { :name => "My name is '#{self.name}'", :post_number => "Post ##{self.post_number}", } end end 

然后,与上面相同的实例,将输出:

 { :name => "My name is 'test'", :post_number => "Post #20" } 

这当然意味着你必须明确指定哪些属性必须出现。

希望这可以帮助。

编辑:

你也可以检查Hashifiablegem。

 @object.as_json 

as_json根据模型关系可以非常灵活地configuration复杂对象

模特活动属于商店,并有一个列表

模型列表有许多list_tasks ,每个list_tasks都有很多注释

我们可以得到一个简单的结合所有这些数据的json。

 @campaign.as_json( { except: [:created_at, :updated_at], include: { shop: { except: [:created_at, :updated_at, :customer_id], include: {customer: {except: [:created_at, :updated_at]}}}, list: { except: [:created_at, :updated_at, :observation_id], include: { list_tasks: { except: [:created_at, :updated_at], include: {comments: {except: [:created_at, :updated_at]}} } } }, }, methods: :tags }) 

注意方法::标签可以帮助你附加任何与他人没有关系的附加对象。 您只需要在模型广告系列中定义一个名称标签的方法。 这个方法应该返回你需要的任何东西(比如Tags.all)

as_json的官方文档

这里有一些很棒的build议。

我认为值得注意的是,你可以把一个ActiveRecord模型当作一个哈希来处理:

 @customer = Customer.new( name: "John Jacob" ) @customer.name # => "John Jacob" @customer[:name] # => "John Jacob" @customer['name'] # => "John Jacob" 

因此,不要生成属性的散列,而可以将对象本身用作散列。

您可以使用其中一个获得作为散列返回的模型对象的属性

 @post.attributes 

要么

 @post.as_json 

as_json允许您包含关联及其属性,并指定要包含/排除哪些属性(请参阅文档 )。 但是,如果您只需要基础对象的属性,那么在我的应用程序中使用ruby 2.2.3和rails 4.2.2进行基准testing就会发现, attributes所需的时间as_json

 >> p = Problem.last Problem Load (0.5ms) SELECT "problems".* FROM "problems" ORDER BY "problems"."id" DESC LIMIT 1 => #<Problem id: 137, enabled: true, created_at: "2016-02-19 11:20:28", updated_at: "2016-02-26 07:47:34"> >> >> p.attributes => {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00} >> >> p.as_json => {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00} >> >> n = 1000000 >> Benchmark.bmbm do |x| ?> x.report("attributes") { n.times { p.attributes } } ?> x.report("as_json") { n.times { p.as_json } } >> end Rehearsal ---------------------------------------------- attributes 6.910000 0.020000 6.930000 ( 7.078699) as_json 14.810000 0.160000 14.970000 ( 15.253316) ------------------------------------ total: 21.900000sec user system total real attributes 6.820000 0.010000 6.830000 ( 7.004783) as_json 14.990000 0.050000 15.040000 ( 15.352894) 

你肯定可以使用属性来返回所有的属性,但是你可以添加一个实例方法到Post,称之为“to_hash”,并让它返回你想要的数据。 就像是

 def to_hash { name: self.name, active: true } end 

不知道这是你需要什么,但在ruby控制台中试试这个:

 h = Hash.new h["name"] = "test" h["post_number"] = 20 h["active"] = true h 

显然它会返回你在控制台中的散列。 如果你想从一个方法中返回一个哈希值,而不是“h”,可以尝试使用“return h.inspect”,类似于:

 def wordcount(str) h = Hash.new() str.split.each do |key| if h[key] == nil h[key] = 1 else h[key] = h[key] + 1 end end return h.inspect end 

哈希[post.attributes.map {| A | [a,post [a]]}]

Swanand的回答非常好。

如果使用的是FactoryGirl,则可以使用其build方法生成不带密钥id的属性哈希。 例如

 build(:post).attributes 

老问题,但大量引用…我认为大多数人使用其他方法,但实际上有一个to_hash方法,它必须设置正确。 一般来说,采摘是一个更好的答案后,铁轨4 …回答这主要是因为我不得不search一堆find这个线程或任何有用的假设其他人正在碰到同样的问题…

注意:不是向每个人推荐这个,而是边缘情况!


从轨道上的rubyapi … http://api.rubyonrails.org/classes/ActiveRecord/Result.html

 This class encapsulates a result returned from calling #exec_query on any database connection adapter. For example: result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts') result # => #<ActiveRecord::Result:0xdeadbeef> ... # Get an array of hashes representing the result (column => value): result.to_hash # => [{"id" => 1, "title" => "title_1", "body" => "body_1"}, {"id" => 2, "title" => "title_2", "body" => "body_2"}, ... ] ...