2013-05-15 38 views
7

Nếu tôi có các mô hình sau trong Rails, tôi sẽ trình bày mô hình này trong Dữ liệu Ember/Ember như thế nào?Mô hình đa hình theo phong cách đường ray trong dữ liệu ember

class Attachment < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :attachable, polymorphic: true 
end 

class Profile < ActiveRecord::Base 
    belongs_to :user 
    has_one :photo, class_name: 'Attachment', as: :attachable 
end 

class Post < ActiveRecord::Base 
    belongs_to :user 
    has_many :attachments, as: :attachable 
end 

Tài liệu tham khảo tôi đã tìm thấy là the relevant ember-data pull request, the ember-data tests for polymorphic relationships, và this related question nhưng thật khó để tìm ra một ví dụ kinh điển từ họ.

Trả lời

11

Tôi hiện đang sử dụng hai cách khác nhau để làm việc với các kiểu đa hình "đường ray". Tôi đã cập nhật mã bên dưới để hiển thị cả hai cách sử dụng.

Attachment mô hình: Đây là "đa hình" ở bên Rails nhưng luôn được "nhúng" ở phía Ember. Lý do cho điều này là tôi hiện chỉ cần lưu/cập nhật các tệp đính kèm cùng với mô hình được liên kết của chúng.

Comment mô hình: Đây là đa hình ở cả bên Rails và bên Ember.

Tôi cũng đã bao gồm mã cho mô hình Post vì nó có thể có nhiều tệp đính kèm và nhiều nhận xét. đang


Rails: đang

class Attachment < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :attachable, polymorphic: true 
end 

class Comment < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :commentable, polymorphic: true 
end 

class Post < ActiveRecord::Base 
    belongs_to :user 
    has_many :attachments, as: :attachable 
    has_many :comments, as: :commentable 
end 

class ApplicationSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
end 

class AttachmentSerializer < ApplicationSerializer 
    attributes :id, :url, :errors 
    has_many :comments 
end 

class CommentSerializer < ApplicationSerializer 
    attributes :id, :body, :created_at, :commentable_id, :commentable_type 
    has_one :user 
end 

class PostSerializer < ApplicationSerializer 
    attributes :id, :title, :body, :posted_at, :errors 
    has_one :user 
    has_many :attachments, embed: :objects, include: true 
    has_many :comments 
end 

class Api::V1::PostsController < Api::V1::BaseController 
    before_filter :auth_only!, only: :create 

    def create 
    # clean/capture ember-data supplied arguments 
    params[:post].delete(:user_id) 
    attachments_params = params[:post].delete(:attachments) 

    @post = current_user.posts.new(params[:post]) 
    process_attachments(attachments_params) 

    if @post.save 
     render json: @post, status: 201 
    else 
     warden.custom_failure! 
     render json: @post, status: 422 
    end 
    end 

    protected 

    def process_attachments(attachments_params) 
     return unless attachments_params.present? 

     attachments_params.each do |attachment_params| 
     # ignore ember-data's additional keys 
     attachment_params.delete(:created_at) 
     attachment_params.delete(:user_id) 

     attachment = @post.attachments.new(attachment_params) 
     attachment.user = current_user 
     end 
    end 
end 

Ember:

DS.RESTAdapter.configure 'App.Post', 
    alias: 'Post' 

DS.RESTAdapter.map 'App.Post', 
    attachments: { embedded: 'always' } 

App.Store = DS.Store.extend 
    adapter: DS.RESTAdapter.create 
    namespace: 'api/v1' 

App.Comment = App.Model.extend 
    user: DS.belongsTo('App.User') 
    commentable: DS.belongsTo('App.Commentable', { polymorphic: true }) 
    body:  DS.attr('string') 
    createdAt: DS.attr('date') 

App.Commentable = App.Model.extend 
    comments: DS.hasMany('App.Comment') 

App.Attachment = App.Commentable.extend 
    user: DS.belongsTo('App.User') 
    url: DS.attr('string') 

App.Post = App.Commentable.extend 
    user: DS.belongsTo('App.User') 
    attachments: DS.hasMany('App.Attachment') 

    title: DS.attr('string') 
    body: DS.attr('string') 
    postedAt: DS.attr('date') 

App.PostFormOverlayController = App.OverlayController.extend 
    # 'files' attribute is set by a widget that wraps the filepicker.io JS 
    updateAttachments: (-> 
    attachments = @get('attachments') 
    attachments.clear() 
    @get('files').forEach (file) => 
     attachment = App.Attachment.createRecord({fpFile: file}) 
     attachments.addObject(attachment) 
).observes('files') 

App.CommentNewController = App.ObjectController.extend 
    # this should be instantiated with it's model set to the commentable 
    # item. eg. `{{render 'comment/new' content}}` 

    save: -> 
    transaction = @get('store').transaction() 
    comment = transaction.createRecord App.Comment, 
     body: @get('body') 
     commentable: @get('model') 

    comment.one 'didCreate', @, -> 
     @set('body', null) 

    transaction.commit() 

Thật không may đang Rails của tôi đã trở thành một ít bị ô nhiễm với ember dữ liệu oddities cụ thể như nó cố gắng gửi lại tất cả các thuộc tính được xác định trên các mô hình. (Lưu ý : Có một open proposal cho read-only thuộc tính đó sẽ giải quyết vấn đề ô nhiễm params)

Nếu có ai biết một cách tốt hơn để tiếp cận bất kỳ ở trên xin vui lòng cho tôi biết!

NB: Tôi lo ngại rằng việc có mô hình mở rộng từ App.Commentable sẽ ngăn không cho tôi có nhiều tệp đính kèm đa hình trên mô hình, tôi có thể cần tìm cách xử lý khác.

+0

Cảm ơn bạn đã đăng giải pháp của mình. Tôi đang cố gắng sử dụng mã của bạn làm hướng dẫn để triển khai mỏ của tôi. Tôi muốn làm rõ nếu đó là cách chính xác bạn đã xác định mô hình đính kèm trong dữ liệu ember. Tôi hỏi vì các liên kết đến các ví dụ đa hình dữ liệu ember trong câu hỏi của bạn đã xác định mô hình đính kèm như sau: ** App.Attachment = DS.Model.extend ({attachable: DS.belongsTo ('App.Attachable', {polymorphic: true })}) ** và sau đó ** App.Attachable = DS.Model.extend ({tệp đính kèm: DS.hasMany ('App.Attachment')}) **. Ngoài ra kể từ khi đường ray mong đợi trở lại ** attachable_type ** như là một lĩnh vực như thế nào để bạn nhận được rằng với mã hiện tại. – brg

+0

Ngay bây giờ, có. Tôi nghĩ bởi vì việc sử dụng hiện tại của tôi "tập tin đính kèm" là rất hạn chế nó làm việc nhưng không hoàn toàn thiết lập. Tôi sẽ sử dụng đúng tính đa hình vào cuối tuần và sẽ cập nhật mã ở đây để khớp.Tôi về cơ bản là sidestepping vấn đề 'attachable_type' bằng cách luôn xử lý các tệp đính kèm như được nhúng ở phía máy khách, cho phép phía máy chủ quản lý những gì nó cần. –

+0

Cảm ơn Kevin đã làm rõ. Tôi sẽ kiểm tra lại vào cuối tuần để biết mã cập nhật cho tính đa hình phù hợp. Có một ngày tuyệt vời. – brg

3

Phần bình luận của câu trả lời của Kevin Ansfield (không sử dụng phần Post) hoạt động như của Ember 1.3.0-beta/Ember Data 1.0.0-beta.4 ngoại trừ serializer đường ray, bây giờ sẽ là:

class CommentSerializer < ActiveModel::Serializer 
    attributes :id, :body, :created_at, :commentable_id, :commentable_type 
    has_one :user 

    def attributes 
    data = super 
    data[:commentable] = {id: data[:commentable_id], type: data[:commentable_type]} 
    data.delete(:commentable_type) 
    data.delete(:commentable_id) 
    data 
    end 
Các vấn đề liên quan