7

Rails に次のモデルがある場合、これを Ember/Ember Data でどのように表現しますか?

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

私が見つけた参考文献は、関連する ember-data pull requestember-data tests for polymorphic relationship、およびthis related questionですが、それらから標準的な例を導き出すことは困難です。

4

2 に答える 2

11

私は現在、Rails スタイルの「ポリモーフィック」モデルを操作する 2 つの異なる方法を使用しています。以下のコードを更新して、両方の使用法を示します。

Attachmentmodel : これは Rails 側では「ポリモーフィック」ですが、Ember 側では常に「埋め込み」です。この理由は、現在、関連付けられているモデルと共に添付ファイルを保存/更新するだけでよいためです。

Commentmodel : これは、Rails 側と Ember 側の両方でポリモーフィックです。

Postモデルには複数の添付ファイルと複数のコメントを含めることができるため、モデルのコードも含めました。


レールコード:

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

残り火コード:

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 データ固有の奇妙な点で少し汚染されています。(: params 汚染の問題を解決する読み取り専用属性の公開提案があります)

上記のいずれかにアプローチするためのより良い方法を誰かが知っている場合は、私に知らせてください!

注意:モデルを拡張すると、モデルに複数のポリモーフィックな添付ファイルを作成できなくなるのではないかと少し心配していApp.Commentableます。それを処理する別の方法を探す必要があるかもしれません。

于 2013-05-15T12:31:32.733 に答える
3

Kevin Ansfield の回答のコメント部分 (Post 部分は使用しませんでした) は、Ember 1.3.0-beta / Ember Data 1.0.0-beta.4 の時点で機能しますが、レール シリアライザーは次のようになります。

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
于 2013-11-21T03:52:03.767 に答える