Ruby-on-rails 将虚拟属性添加到 json 输出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6892044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:41:17  来源:igfitidea点击:

Add virtual attribute to json output

ruby-on-railsjson

提问by Linus

Let's say I have an app that handles a TODO list. The list has finished and unfinished items. Now I want to add two virtual attributes to the list object; the count of finished and unfinished items in the list. I also need these to be displayed in the json output.

假设我有一个处理待办事项列表的应用程序。清单有已完成和未完成的项目。现在我想向列表对象添加两个虚拟属性;列表中已完成和未完成项目的数量。我还需要将这些显示在 json 输出中。

I have two methods in my model which fetches the unfinished/finished items:

我的模型中有两种方法可以获取未完成/已完成的项目:

def unfinished_items 
  self.items.where("status = ?", false) 
end 

def finished_items 
  self.items.where("status = ?", true) 
end

So, how can I get the count of these two methods in my json output?

那么,如何在我的 json 输出中获取这两种方法的数量?

I'm using Rails 3.1

我正在使用 Rails 3.1

回答by mu is too short

The serialization of objects in Rails has two steps:

Rails 中对象的序列化有两个步骤:

  • First, as_jsonis called to convert the object to a simplified Hash.
  • Then, to_jsonis called on the as_jsonreturn value to get the final JSON string.
  • 首先,as_json调用将对象转换为简化的 Hash。
  • 然后,to_jsonas_json返回值上调用以获取最终的 JSON 字符串。

You generally want to leave to_jsonalone so all you need to do is add your own as_jsonimplementationsort of like this:

您通常希望自己离开to_json,因此您需要做的就是添加自己的as_json实现,如下所示:

def as_json(options = { })
  # just in case someone says as_json(nil) and bypasses
  # our default...
  super((options || { }).merge({
    :methods => [:finished_items, :unfinished_items]
  }))
end

You could also do it like this:

你也可以这样做:

def as_json(options = { })
  h = super(options)
  h[:finished]   = finished_items
  h[:unfinished] = unfinished_items
  h
end

if you wanted to use different names for the method-backed values.

如果您想为方法支持的值使用不同的名称。

If you care about XML and JSON, have a look at serializable_hash.

如果您关心 XML 和 JSON,请查看serializable_hash.

回答by Aswin Ramakrishnan

With Rails 4, you can do the following -

使用 Rails 4,您可以执行以下操作 -

render json: @my_object.to_json(:methods => [:finished_items, :unfinished_items])

Hope this helps somebody who is on the later / latest version

希望这对使用更高/最新版本的人有所帮助

回答by randomor

Another way to do this is add this to your model:

另一种方法是将其添加到您的模型中:

def attributes
  super.merge({'unfinished' => unfinished_items, 'finished' => finished_items})
end

This would also automatically work for xml serialization. http://api.rubyonrails.org/classes/ActiveModel/Serialization.htmlBe aware though, you might want use strings for the keys, since the method can not deal with symbols when sorting the keys in rails 3. But it is not sorted in rails 4, so there shouldn't be a problem anymore.

这也将自动适用于 xml 序列化。 http://api.rubyonrails.org/classes/ActiveModel/Serialization.html但请注意,您可能希望使用字符串作为键,因为在 Rails 3 中对键进行排序时,该方法无法处理符号。但事实并非如此在 rails 4 中排序,所以应该不会再有问题了。

回答by jmeinlschmidt

just close all of your data into one hash, like

只需将所有数据关闭到一个哈希中,例如

render json: {items: items, finished: finished, unfinished: unfinished}

render json: {items: items, finished: finished, unfinished: unfinished}

回答by sidney

This will do, without having to do some ugly overridings. If you got a model Listfor example, you can put this in your controller:

这样就可以了,而不必做一些丑陋的覆盖。List例如,如果你有一个模型,你可以把它放在你的控制器中:

  render json: list.attributes.merge({
                                       finished_items: list.finished_items,
                                       unfinished_items: list.unfinished_items
                                     })

回答by d1jhoni1b

As Aswinlisted above, :methodswill enable you to return a specific model's method/function as a json attribute, in case you have complex assosiations this will do the trick since it will add functions to the existing model/assossiations :D it will work like a charm if you dont want to redefine as_json

正如上面列出的Aswin:methods将使您能够将特定模型的方法/函数作为 json 属性返回,如果您有复杂的关联,这将起作用,因为它将向现有模型/关联添加函数:D 它会像一个如果你不想重新定义魅力as_json

Check this code, and please notice how i'm using :methodsas well as :include[N+Query is not even an option ;)]

检查此代码,请注意我的使用:methods方式以及:include[N+Query 甚至不是一个选项;)]

render json: @YOUR_MODEL.to_json(:methods => [:method_1, :method_2], :include => [:company, :surveys, :customer => {:include => [:user]}])

render json: @YOUR_MODEL.to_json(:methods => [:method_1, :method_2], :include => [:company, :surveys, :customer => {:include => [:user]}])

Overwritting as_jsonfunction will be way harder in this scenario (specially because you have to add the :includeassossiations manually :/ def as_json(options = { }) end

as_json在这种情况下,覆盖功能将更加困难(特别是因为您必须:include手动添加关联:/ def as_json(options = { }) end

回答by Abram

I just thought I'd provide this answer for anyone like myself, who was trying to integrate this into an existing as_jsonblock:

我只是想我会为像我这样试图将其集成到现有as_json块中的任何人提供这个答案:

  def as_json(options={})
    super(:only => [:id, :longitude, :latitude],
          :include => {
            :users => {:only => [:id]}
          }
    ).merge({:premium => premium?})

Just tack .merge({})on to the end of your super()

只要.merge({})坚持到你的尽头super()