如果我在Rails中有以下模型,我将如何在Ember / 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
我发现的参考文献是the relevant ember-data pull request,the ember-data tests for polymorphic relationships和this related question,但很难从它们中找出一个典型的例子.
解决方法
我现在使用两种不同的方式使用rails风格的“多态”模型.我已更新下面的代码以显示两种用途.
附件模型:这是Rails端的“多态”,但总是“嵌入”在Ember端.原因是我目前只需要保存/更新附件及其相关模型.
评论模型:这在Rails方面和Ember方面都是多态的.
我还为Post模型添加了代码,因为它可以有多个附件和多个注释.
Rails代码:
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,: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
灰烬代码:
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()
不幸的是,我的Rails代码变得有点污染了特定于ember数据的怪异,因为它试图发送回模型上定义的所有属性. (注意:有一个open proposal的只读属性可以解决params污染问题)
如果有人知道更好的方法来接近上述任何一种,请告诉我!
注意:我有点担心从App.Commentable扩展模型会阻止我在模型上有多个多态附件,我可能需要寻找一种不同的处理方式.