2012-01-20 31 views
10

Có vẻ như khi trả về một đối tượng có chứa thuộc tính "type" là JSON từ một ứng dụng Rails 3.1, thuộc tính "type" không được bao gồm. Giả sử tôi có những điều sau đây:Bao gồm thuộc tính "type" trong json respond_with Rails 3.1

Mô hình có bảng STI tương ứng. Mô hình Mèo, Chó và Cá thừa hưởng Động vật.

Khi trở về một động vật qua JSON, tôi muốn bao gồm các "loại" cột, nhưng điều này không xảy ra:

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

sản lượng:

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}" 

Nó có vẻ như đây là một vấn đề với 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}" 

Có ai biết lý do đằng sau hành vi này và cách ghi đè hành vi này không?

Trả lời

6

Ghi đè phương thức as_json. Nó được sử dụng bởi to_json để tạo ra đầu ra. Bạn có thể làm một cái gì đó như:

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

Tuyệt vời, cảm ơn - điều này có vẻ như lừa! – cyrusd

+5

Điều này có vẻ giống như một thỏa hiệp tốt đẹp để giảm dự phòng: def as_json (tùy chọn = {}) {type: type} .merge super end – cyrusd

+0

Bạn được chào đón. Tôi thích ghi đè as_json vì tôi biết cách tôi thực sự chuyển đổi các đối tượng của mình thành JSON và tôi chỉ chuyển đổi những gì tôi thực sự cần chuyển đổi. – lucapette

0

Đối với tôi, trong Rails 2.3.12, phần trên không có tác dụng.

tôi có thể (trong Model của tôi tất nhiên) làm một cái gì đó như thế này:

class Registration < ActiveRecord::Base 

    def as_json(options={}) 
    super(options.merge(:include => [:type])) 
    end 

end 

Nhưng điều đó gây to_json để ném ra một lỗi như thế này:

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

Tôi đã làm việc xung quanh này với điều này, mà là đấm phương pháp này vào đối tượng tôi muốn xuất khẩu

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 

Vì vậy, trên ứng dụng của tôi, tôi đã đưa nó vào một 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 

Và bây giờ trong lớp mô hình của tôi (es), tôi thêm:

include RailsStiModel 
0

Đây là giải pháp của tôi mà có thể giữ cho các tính năng ban đầu của 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 
14

Đây là những gì tôi đã làm. Nó chỉ thêm số thiếu type vào tập hợp kết quả

def as_json(options={}) 
    super(options.merge({:methods => :type})) 
    end 
Các vấn đề liên quan