Rails:仅在特定控制器操作中禁用JSON中的root?

时间:2011-08-30 23:01:13

标签: ruby-on-rails ruby-on-rails-3 json activerecord

我知道如何全局禁用根元素,la Rails 3.1 include_root_in_json或使用ActiveRecord::Base.include_root_in_json = false,但我只想为少数JSON请求(不是全局)执行此操作。

到目前为止,我一直在这样做:

@donuts = Donut.where(:jelly => true)
@coffees = Coffee.all
@breakfast_sandwiches = Sandwich.where(:breakfast => true)

dunkin_donuts_order = {}
dunkin_donuts_order[:donuts] = @donuts
dunkin_donuts_order[:libations] = @coffees
dunkin_donuts_order[:non_donut_food] = @breakfast_sandwiches

Donut.include_root_in_json = false
Coffee.include_root_in_json = false

render :json => dunkin_donuts_order

Donut.include_root_in_json = true
Coffee.include_root_in_json = true

大约有5个案例我必须这样做,有时会有多个型号,而且根本不觉得干净。我曾尝试将其放在around_filter中,但例外情况正在打破流量,而且这也变得毛茸茸。

必须有更好的方法!

2 个答案:

答案 0 :(得分:2)

不幸的是,答案是肯定的,不是。

是的,你上面所做的事情可以说是更好。不,Rails不会让你在每个动作的基础上添加root。 JSON渲染并没有考虑到这种灵活性。

话虽如此,这就是我要做的事情:

  1. include_root_in_json设置为false以获取具有root权限的模型,具体取决于操作(例如上面的DonutCoffee)。
  2. 覆盖as_json以提高灵活性。这是一个例子:

    # in model.rb
    def as_json(options = nil)
        hash = serializable_hash(options)
        if options && options[:root]
            hash = { options[:root] => hash }
        else
            hash = hash
        end
    end
    

    此示例将使您可以选择传递根,但默认为无根。你也可以用另一种方式写它。

  3. 由于您覆盖了as_json,因此您必须适当地修改渲染调用。因此,对于Donut,您需要render :json => @donut.to_json
  4. 希望这有帮助!

答案 1 :(得分:1)

您可以为每个模型实例设置include_root_in_json,它不会影响该类(有关此行为的说明,请参阅rails api中的class_attribute)。因此,您可以在类级别设置合理的默认值,然后在相关控制器中的每个实例上设置不同的值。

示例:

@donuts = Donut.where(:jelly => true).each {|d| d.include_root_in_json = false }

为方便起见,您可以创建一个实用程序方法,该方法接受一组模型实例并在所有模型实例上设置值。