【问题标题】:Including "type" attribute in json respond_with Rails 3.1在 json respond_with Rails 3.1 中包含“type”属性
【发布时间】:2012-01-20 18:03:23
【问题描述】:

似乎当从 Rails 3.1 应用程序返回包含“类型”属性作为 JSON 的对象时,“类型”属性不包括在内。假设我有以下内容:

具有相应 STI 表 Animal 的模型。 继承 Animal 的 Cat、Dog 和 Fish 模型。

当通过 JSON 返回 Animal 时,我希望包含“type”列,但这不会发生:

jQuery.ajax("http://localhost:3001/animals/1", {dataType: "json"});

产量:

responseText: "{"can_swim":false,"created_at":"2012-01-20T17:55:16Z","id":1,"name":"Fluffy","updated_at":"2012-01-20T17:55:16Z","weight":9.0}"

看来这是to_json的问题:

bash-3.2$ rails runner 'p Animal.first.to_yaml'
"--- !ruby/object:Cat\nattributes:\n  id: 1\n  type: Cat\n  weight: 9.0\n  name: Fluffy\n  can_swim: false\n  created_at: 2012-01-20 17:55:16.090646000 Z\n  updated_at: 2012-01-20 17:55:16.090646000 Z\n"

bash-3.2$ rails runner 'p Animal.first.to_json'
"{\"can_swim\":false,\"created_at\":\"2012-01-20T17:55:16Z\",\"id\":1,\"name\":\"Fluffy\",\"updated_at\":\"2012-01-20T17:55:16Z\",\"weight\":9.0}"

有谁知道这种行为背后的原因,以及如何覆盖它?

【问题讨论】:

    标签: ruby-on-rails json respond-with


    【解决方案1】:

    这就是我所做的。它只是将缺少的type 添加到结果集中

      def as_json(options={})
        super(options.merge({:methods => :type}))
      end
    

    【讨论】:

      【解决方案2】:

      覆盖as_json 方法。 to_json 使用它来生成输出。您可以执行以下操作:

      def as_json options={}
       {
         id: id,
         can_swim: can_swim,
         type: type
       }
      end
      

      【讨论】:

      • 这似乎是减少冗余的一个不错的折衷方案:def as_json(options = {}) { type: type }.merge super end
      • 不客气。我喜欢覆盖 as_json,因为我知道我实际上是如何将我的对象转换为 JSON 的,而且我只转换我真正需要转换的内容。
      【解决方案3】:

      对我来说,在 Rails 2.3.12 中,上述方法不起作用。

      我可以(当然在我的模型中)做这样的事情:

      class Registration < ActiveRecord::Base
      
        def as_json(options={})
          super(options.merge(:include => [:type]))
        end
      
      end
      

      但这会导致 to_json 抛出如下错误:

      NoMethodError: undefined method `serializable_hash' for "Registration":String
      

      我已经解决了这个问题,将这个方法打到我要导出的对象上

      class Registration < ActiveRecord::Base
      
        def as_json(options={})
          super(options.merge(:include => [:type]))
        end
      
        def type
          r  = self.attributes["type"]
          def r.serializable_hash(arg)
            self
          end
          r
        end
      end
      

      所以在我的应用程序中,我将它放入了一个 mixin:

      module RailsStiModel
        # The following two methods add the "type" parameter to the to_json output.
        # see also:
        # http://stackoverflow.com/questions/8945846/including-type-attribute-in-json-respond-with-rails-3-1/15293715#15293715
        def as_json(options={})
          super(options.merge(:include => [:type]))
        end
      
        def type
          r  = self.attributes["type"]
          def r.serializable_hash(arg)
            self
          end
          r
        end
      end
      

      现在在我的模型类中,我添加:

      include RailsStiModel
      

      【讨论】:

        【解决方案4】:

        这是我的解决方案,可以保留 as_json 的原始功能。

        def as_json(options={})
          options = options.try(:clone) || {}
          options[:methods] = Array(options[:methods]).map { |n| n.to_sym }
          options[:methods] |= [:type]
        
          super(options)
        end
        

        【讨论】:

          猜你喜欢
          • 2011-07-22
          • 1970-01-01
          • 2014-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-20
          • 1970-01-01
          相关资源
          最近更新 更多