2011-07-31 25 views
48

Giả sử tôi có một ứng dụng xử lý danh sách TODO. Danh sách đã hoàn thành và các mục chưa hoàn thành. Bây giờ tôi muốn thêm hai thuộc tính ảo vào đối tượng danh sách; số lượng các hạng mục đã hoàn thành và chưa hoàn thành trong danh sách. Tôi cũng cần những thứ này được hiển thị trong đầu ra json.Thêm thuộc tính ảo vào đầu ra json

Tôi có hai phương pháp trong mô hình của tôi mà fetches chưa hoàn thành/thành hạng mục:

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

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

Vì vậy, làm thế nào tôi có thể lấy số liệu của hai phương pháp này trong đầu ra json của tôi?

Tôi đang sử dụng Rails 3.1

+0

tôi đã không cố gắng này: có lẽ tất cả các bạn phải làm là thêm attr_reader: finished_items? – mkro

Trả lời

95

Các serialization các đối tượng trong Rails có hai bước sau:

  • Thứ nhất, as_json được gọi để chuyển đổi các đối tượng đến một Hash đơn giản.
  • Sau đó, to_json được gọi trên giá trị trả về as_json để nhận chuỗi JSON cuối cùng.

Bạn thường muốn để lại to_json một mình vì vậy tất cả bạn cần làm là thêm your own as_json implementation loại như thế này:

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 

Bạn cũng có thể làm điều đó như thế này:

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

nếu bạn muốn sử dụng các tên khác nhau cho các giá trị được phương pháp hỗ trợ.

Nếu bạn quan tâm đến XML và JSON, hãy xem serializable_hash.

+3

Tôi gặp lỗi này ở đầu: phương thức chưa xác định 'hợp nhất 'cho nil: NilClass Vì vậy, tôi đã thay thế' options.merge' bằng '(options || {}). Merge'. – Turadg

+0

@Turadg: Người đầu tiên nên làm việc do mặc định 'options = {}' trừ khi ai đó đang chuyển một 'nil' rõ ràng vào một nơi nào đó, tôi sẽ vá trong hoang tưởng thêm chỉ để được an toàn. Xin lỗi, bình luận của bạn đã bị mất trong sự hỗn loạn hàng ngày vì vậy tôi là một chút muộn nhận lại cho bạn. –

13

Một cách khác để làm điều này là thêm video này vào mô hình của bạn:

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

Điều này cũng sẽ tự động làm việc cho xml serialization. Tuy nhiên, hãy lưu ý rằng, bạn có thể muốn sử dụng các chuỗi cho các phím, vì phương pháp này không thể xử lý các biểu tượng khi phân loại các khóa trong đường ray 3. Nhưng nó không được sắp xếp trong đường ray 4, vì vậy không còn vấn đề gì nữa .

22

Với Rails 4, bạn có thể làm như sau -

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

Hope this helps ai đó là trên phiên bản mới hơn/mới nhất

+0

thx, đây là một phím tắt thực sự thú vị, đặc biệt là cho các phản hồi với javascript kết hợp với BSON ObjectIds. – RunsnbunsN

0

Tôi chỉ nghĩ rằng tôi muốn cung cấp câu trả lời này cho bất cứ ai như bản thân mình , người đã cố gắng để tích hợp này thành một hiện as_json khối:

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

Chỉ tack .merge({}) vào cuối của bạn super()

2

chỉ cần đóng tất cả các dữ liệu của bạn thành một băm, như

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

0

này sẽ làm, mà không cần phải làm một số overridings xấu xí. Nếu bạn có một mô hình List ví dụ, bạn có thể đặt điều này trong điều khiển của bạn:

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

Như Aswin liệt kê ở trên, :methods sẽ cho phép bạn quay trở lại phương pháp/chức năng một mô hình cụ thể như là một thuộc tính json, trong trường hợp bạn có phức tạp assosiations này sẽ làm các trick vì nó sẽ thêm chức năng cho mô hình hiện tại/assossiations: D nó sẽ làm việc như một say mê nếu bạn không muốn xác định lại as_json

Kiểm tra mã này, và xin vui lòng thông báo như thế nào tôi đang sử dụng :methods cũng như :include [Truy vấn N + thậm chí không phải là một tùy chọn;)]

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

overwritting as_json chức năng sẽ cách khó khăn hơn trong kịch bản này (đặc biệt bởi vì bạn phải thêm :include assossiations bằng tay:/ def as_json(options = { }) end

Các vấn đề liên quan