【问题标题】:Single Table inheritance with CRUD and forms in Rails在 Rails 中使用 CRUD 和表单进行单表继承
【发布时间】:2012-07-19 16:29:30
【问题描述】:

我对 Rails 中的 STI 有点困惑。

我的情况: 我有一个 Contact 模型,它有 descriptiondata 字符串字段,用于存储一些联系人,如电话、传真、电子邮件等。

现在,当我有一些特定的联系人类型(例如电子邮件地址的电话号码)时,我想以不同的方式验证数据格式,并且我想在输出时进行一些不同的格式化。

我决定使用 STI,因为所有模型都有相同的数据,只是行为不同。我对表单和 CRUD 操作有一些疑问,因为我不想违反 Rails 约定。

  1. 如何在表格中制作模型类型的下拉列表?我应该硬编码还是有更自动化的方法?

  2. 如何创建记录?我应该使用switch 语句并根据收到的类型创建相应实例的新模型吗?

  3. 如果我要更改模型类型,我应该如何更新它?将对象转换为新类?还是创建一个新对象并销毁之前的对象?

非常感谢您的帮助!

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 forms crud sti


    【解决方案1】:
    1. 是的,应该做一个硬核,因为您的 STI 模型没有默认存储。
    2. 一般来说,是的。但是有了 Rails,你可以使用 camelize.constantize 从字符串中获取类。另一种方法是使用父模型,并手动设置type 字段。与STI 一样,所有记录都在同一个表中,然后都属于父类。
    3. 如果您想更新,只需更新type 字段。然后您可以重新查询以强制 Rails 获取不同类型的新对象。

    【讨论】:

    • 感谢您的回复。但是如果我只设置一个类型字段,验证是否适用于特定模型?
    • @Uko 是的,如果你这样做了@model = type.camelize.contantize.new(params[:model])
    • 哇,真是太好了。还有一件事。我应该如何处理更新?我应该做类似@model.becomes(type.camelize.contantize) 然后@model.update_attributes(params[:model]) 的事情吗?
    【解决方案2】:

    您可以创建这样的模型:

    Type < ActiveRecord::Base
      has_many :contacts
    end
    

    您可以使用此命令rails g model Type name:string,在您的联系人中添加type_id 列并迁移数据库。

    像这样结束更改联系人的模型:

    Contact < ActiveRecord::Base
      belongs_to :type
    end
    

    现在,在您的表单中,您可以使用这个:

    select("type", "type_id", Type.all.collect {|t| [ t.name, t.id ] }, { :include_blank => true })
    

    它应该可以解决您的问题。

    现在你可以这样做了:

    @emails = Type.find_by_name('email').contacts
    

    或者使用范围。

    【讨论】:

    • 感谢您的回答,我考虑过这个选项,但我认为 STI 是更好的设计策略,因为我拥有完全相同的数据,只需要不同的验证和格式化等。因此,如果我使用 STI 验证,将根据模型本身来完成,并且在您的解决方案中,我需要使用一些带有 switch 语句的预验证回调
    猜你喜欢
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多