Ember JS中的Rails STI和多态性

时间:2014-11-23 21:08:24

标签: ruby-on-rails ember.js polymorphism ember-data sti

我的设置:

Rails 4.1 with active-model-serializer gem
Ember 1.9.0
Ember-Data 1.0.0 beta with ActiveModelAdapter used as ApplicationAdapter

我有一个名为Jobs的STI表,它有许多子类型。每个Job都有很多LineItems。我在Rails中使用ActiveModelSerializers以Ember-Data理解的方式序列化我的JSON数据。我的模型在Rails中以这种方式设置:

class Job < ActiveRecord::Base
  has_many :line_items
  ...
end
class DisposalJob < Job
  ...
end
class SupplyJob < Job
  ...
end
class LineItem < ActiveRecord::Base
  belongs_to :job, polymorphic: true
  ...
end

这样在Ember:

App.Job = DS.Model.extend
  line_items: DS.hasMany "line_item"
  ...

App.DisposalJob = App.Job.extend
  ...

App.SupplyJob = App.Job.extend
  ...

App.LineItem = DS.Model.extend
  job: DS.belongsTo "job",
    polymorphic: true

我在Rails中的序列化程序设置如下:

class BaseSerializer < ActiveModel::Serializer
  ActiveModel::Serializer.setup do |config|
    config.embed = :ids
    config.embed_in_root = true
  end
end

class JobSerializer < BaseSerializer
  ...
  has_many :line_items
end

class DisposalJobSerializer < JobSerializer
  ...
end

class SupplyJobSerializer < JobSerializer
  ...
end

class LineItemSerializer < BaseSerializer
  belongs_to :job, polymorphic: true
end

我的问题是当我尝试将line_item保存到作业子类时(我不直接使用Job类),Ember拒绝看到DisposalJob是一种类型的作业并抛出它预期的错误a&#34;工作&#34;记录保存到该关系,而不是&#34; DisposalJob&#34;或者&#34; SupplyJob&#34;,尽管这些都是Job的子类。我是一个Ember新手,所以任何帮助都会非常感激。

编辑:这是我在Ember中尝试将DisposalJob保存到LineItem上的Job关系时遇到的错误:

 Uncaught Error: Assertion Failed: You can only add a 'job' record to this relationship
编辑:我尝试过重构,以便line_item同时接受job_id和job_type,而不仅仅是job_id。 Ember仍然告诉我它期待着一份&#34;工作&#34;在这种关系中记录。我试图通过在ember端消除&#34; belongsTo来避开问题,并且让line_item包括job_id:DS.attr&#34; number&#34;和job_type:DS.attr&#34; string&#34;。这允许我保存记录,但是如果没有belongsTo关联,当Ember显示他们所附加的作业时,将找不到行项目。

1 个答案:

答案 0 :(得分:1)

如果启用了MODEL_FACTORY_INJECTIONS,则无法使用子类,因为基于原型的继承检查失败Issue #5573Issue #2342以及Issue #2316

我发现在模型层使用Ember.Data进行STI,实际上Ember.Model由于以下原因而无法实现:

  1. 就商店而言,每个模型子类都是一个单独的集合。
  2. 您不能查询商店以获取包含所有(或仅一些)子类的聚合结果集。理论上你可以通过查询每个所需子类的商店并使用Ember.computed.union()/ Ember.computed.uniq()合并结果来解决这个问题,但它不会有效。
  3. Ember无法使用具有属性的mixin动态扩展对象实例,这是通过基于模型数据中的type属性扩展模型实例来处理STI的另一种方式。
  4. 所以你要留下的就是在服务器上的数据库中处理类似于你所做的事情,它支持数据模型中的所有可能性。这意味着只需定义所有可能的关系和属性。

    在验证和其他业务规则方面,控制器可以提供您需要的外观。 Ember方式是控制器装饰模型,你当然可以创建不同类别的控制器来装饰你喜欢的模型。