4

如何在 Rails 中使用多表继承为对象构建嵌套表单?我正在尝试使用与另一组具有多表继承功能的模型具有 has_many 关系的模型创建嵌套表单来创建对象。我使用formtasticcocoon作为嵌套表单,并使用act_as_relation gem 来实现多表继承。

我有以下型号:

class Product < ActiveRecord::Base
 acts_as_superclass
 belongs_to :store
end

class Book < ActiveRecord::Base
     acts_as :product, :as => :producible
end

class Pen < ActiveRecord::Base
     acts_as :product, :as => :producible acts_as :product, :as => :producible
end

class Store < ActiveRecord::Base
    has_many :products
    accepts_nested_attributes_for :products, :allow_destroy => true, :reject_if => :all_blank
end'

对于此示例,该书与其他产品相比的唯一唯一属性是作者字段。实际上,我对 book 有许多独特的属性,这就是为什么我选择多表继承而不是更常见的单表继承的原因。

我正在尝试创建一个嵌套表单,允许您使用产品创建一个新商店。这是我的表格:

<%= semantic_form_for @store do |f| %>
  <%= f.inputs do %>
    <%= f.input :name %>

    <h3>Books/h3>
    <div id='books'>
    <%= f.semantic_fields_for :books do |book| %>
      <%= render 'book_fields', :f => book %>
    <% end %>
          <div class='links'>
      <%= link_to_add_association 'add book', f, :books %>
      </div>

  <% end %>
<%= f.actions :submit %>
<% end %>

而 book_fields 部分:

<div class='nested-fields'>
  <%= f.inputs do %>
    <%= f.input :author %>
    <%= link_to_remove_association "remove book", f %>
  <% end %>
</div>

我收到此错误:

undefined method `new_record?' for nil:NilClass

在阅读了关于act_as_relation的 github 页面上的问题后,我想到了让 store 和 books 之间的关系更加明确:

class Product < ActiveRecord::Base
 acts_as_superclass
 belongs_to :store
 has_one :book
 accepts_nested_attributes_for :book, :allow_destroy => true, :reject_if => :all_blank
end

class Book < ActiveRecord::Base
     belongs_to :store
     acts_as :product, :as => :producible
end

class Store < ActiveRecord::Base
        has_many :products
        has_many :books, :through => :products
        accepts_nested_attributes_for :products, :allow_destroy => true, :reject_if => :all_blank
        accepts_nested_attributes_for :books, :allow_destroy => true, :reject_if => :all_blank
    end

现在,我得到一个静默错误。我可以使用表单创建新的商店,并且 cocoon 允许我添加新的书籍字段,但是当我提交时,商店被创建但不是子书。当我通过“/books/new”路线时,我可以毫无问题地创建一个跨越(产品和书籍表)的新书籍记录。

这个问题有解决方法吗?其余的代码可以在这里找到。

4

2 回答 2

2

也许你可以:

  • stores_controller#new根据您的操作手动建立书籍关系

    @store.books.build

  • 手动存储您stores_controller#create操作的关系

    @store.books ... (对如何实现它不是很有信心)

随时通知我们。

于 2013-12-02T13:32:55.360 回答
1

您可能要考虑创建自己的表单对象。这是一个 RailsCast 专业视频,但这里是 ASCIIcast 中的一些示例:

def new
  @signup_form = SignupForm.new(current_user)
end

此注册表单可以包含与您的其他对象的关系,就像您在原始控制器代码中一样:

class SignupForm
    # Rails 4: include ActiveModel::Model
  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  validates_presence_of :username
  validates_uniqueness_of :username
  validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/
  validates_length_of :password, minimum: 6

  def persisted?
    false
  end

    def subscribed
    subscribed_at
  end

  def subscribed=(checkbox)
    subscribed_at = Time.zone.now if checkbox == "1"
  end

  def generate_token
    begin
      self.token = SecureRandom.hex
    end while User.exists?(token: token)
  end
end

这是 RailsCast 的链接。获得专业会员资格可能值得您花时间。我很幸运通过 www.codeschool.com 成为会员,完成课程后您可以获得“奖品”:

RailsCast: http: //railscasts.com/episodes/416-form-objects

于 2013-12-02T19:34:04.897 回答