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"}, ... ] ...