2013-05-15 9 views
7

Jeśli mam następujące modele w Railsach, w jaki sposób będę reprezentował to w Ember/Ember Data?Model polimorficzny typu rails w danych 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 

Referencje znalazłem są the relevant ember-data pull request, the ember-data tests for polymorphic relationships i this related question ale trudno wypracować kanoniczny przykład od nich.

Odpowiedz

11

Używam teraz dwóch różnych sposobów pracy z "polimorficznymi" modelami szyn. Zaktualizowałem poniższy kod, aby pokazać oba zastosowania.

Attachment model: Jest to "polimorficzny" po stronie szyny, ale zawsze jest "osadzony" po stronie Embera. Powodem tego jest to, że obecnie muszę tylko zapisywać/aktualizować załączniki wraz z ich powiązanym modelem.

Comment model: Jest polimorficzny zarówno po stronie Railsów, jak i po stronie Ember.

Dołączyłem również kod modelu Post, ponieważ może on zawierać wiele załączników i wiele komentarzy. Kod


szyn: Kod

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() 

Niestety mój kod Rails stała się mało zanieczyszczone ember transmisji danych specyficznych dziwactw, ponieważ próbuje odeślij wszystkie atrybuty zdefiniowane w modelach. (Uwaga: Jest open proposal na tylko do odczytu atrybutów, które rozwiązałoby problem zanieczyszczenia params)

Jeśli ktoś zna lepszy sposób podejść do żadnej z powyższych proszę dać mi znać!

UWAGA: Jestem trochę zaniepokojony tym, że o modele rozciągają się od App.Commentable uniemożliwi mi o wielu polimorficznych załączników na modelu, może trzeba szukać innego sposobu obchodzenia tego.

+0

Dziękujemy za opublikowanie rozwiązania. Próbuję użyć twojego kodu jako przewodnika do realizacji mojego. Chcę wyjaśnić, czy jest to dokładny sposób zdefiniowania modelu załącznika w danych embers. Pytam, ponieważ linki do polimorficznych przykładów danych z ember-danych w twoim pytaniu definiowały model przywiązania w następujący sposób: ** App.Attachment = DS.Model.extend ({attachable: DS.belongsTo ('AppAAckachable', {polimorficzny: true })}) **, a następnie ** App.Attachable = DS.Model.extend ({attachments: DS.hasMany ('App.Attachment')}) **. Także od czasu, gdy rails oczekuje z powrotem ** attachable_type ** jako pole, jak to robisz z bieżącym kodem. – brg

+0

Teraz, tak. Myślę, że moje obecne użycie "załączników" jest bardzo ograniczone, działa, ale nie w pełni skonfigurowane. W weekend wykorzystam polimorfizm i zaktualizuję kod, aby się do niego dopasować.Zasadniczo omijam problem 'attachable_type', zawsze traktując załączniki jako osadzone po stronie klienta, pozwalając stronie serwera zarządzać tym, czego potrzebuje. –

+0

Dziękuję Kevinowi za wyjaśnienie. Sprawdzę w ciągu weekendu zaktualizowany kod dla właściwego polimorfizmu. Miłego dnia. – brg

3

Część komentarza do odpowiedzi Kevina Ansfielda (nie korzystała z części Post) działa od wersji Ember 1.3.0-beta/Ember Data 1.0.0-beta.4 z wyjątkiem serializatora szyn, który powinien być teraz:

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 
Powiązane problemy