Ich verwende jetzt zwei verschiedene Arten der Arbeit mit "polymorphen" Modellen im Rails-Stil. Ich habe den folgenden Code aktualisiert, um beide Verwendungsmöglichkeiten anzuzeigen.
Attachment
Modell: Dies ist "polymorph" auf der Rails-Seite, ist aber immer auf der Ember-Seite "eingebettet". Der Grund dafür ist, dass ich momentan nur Anhänge zusammen mit dem zugehörigen Modell speichern/aktualisieren muss.
Comment
Modell: Dies ist sowohl auf der Rails-Seite als auch auf der Ember-Seite polymorph.
Ich habe auch Code für das Post
Modell hinzugefügt, da es mehrere Anhänge und mehrere Kommentare haben kann.
Rails-Code:
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 Code:
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()
Leider hat mein Rails-Code ein wenig verschmutzt mit glut-spezifischen Daten Merkwürdigkeiten geworden, da es versucht, Senden Sie alle Attribute zurück, die in den Modellen definiert sind. (Hinweis: Es gibt eine open proposal für Nur-Lese-Attribute, die das params Verschmutzung Problem lösen würden)
Wenn jemand einen besseren Weg kennt eine der oben genannten Ansatz lass es mich wissen!
NB: ich ein wenig besorgt bin, dass mit Modellen von App.Commentable
verlängern wird mich hindern mehrere polymorphe Anhänge auf einem Modell, das, ich kann für einen anderen Weg suchen müssen, dass der Umgang mit.
Vielen Dank für Ihre Lösung. Ich versuche, deinen Code als Leitfaden zu verwenden, um meine zu implementieren. Ich möchte klarstellen, ob dies genau die Art und Weise ist, wie Sie das Attachment-Modell in Ember-Daten definiert haben. Ich frage, weil die Links zu ember-Daten polymorphe Beispiele in Ihrer Frage das Attachment-Modell wie folgt definiert: ** App.Attachment = DS.Model.extend ({anfügbar: DS.belongsTo ('App.Attachable', {polymorph: true })}) ** und dann ** App.Attachable = DS.Model.extend ({Anhänge: DS.hasMany ('App.Attachment')}) **. Da rails ** ** attachable_type ** als Feld erwartet, wie bekommt man das mit dem aktuellen Code? – brg
Gerade jetzt, ja. Ich denke, weil meine derzeitige Verwendung von "Attachments" sehr begrenzt ist, funktioniert es, ist aber nicht vollständig eingerichtet. Ich werde den Polymorphismus über das Wochenende richtig nutzen und den Code hier entsprechend aktualisieren.Ich umgehe das 'attachable_type'-Problem grundsätzlich, indem ich Anhänge immer so behandle, wie sie auf der Clientseite eingebettet sind, und die Server-Seite verwalten lassen, was sie benötigt. –
Danke Kevin für die Klärung. Ich werde über das Wochenende nach dem aktualisierten Code für korrekten Polymorphismus zurückschauen. Ich wünsche ihnen einen wunderbaren Tag. – brg