Rails nested_form with has_many,而不在子表

时间:2016-02-16 15:37:42

标签: ruby-on-rails ruby-on-rails-4 activerecord rails-activerecord

我正在使用

class Mother < ActiveRecord::Base
  has_many :boys
  accepts_nested_attributes_for :boys, reject_if: :all_blank, allow_destroy: true
end

class Boy < ActiveRecord::Base
  belongs_to :mother

  attr_accessor :mother_id
end

因为我无法修改Boys表的列。

现在我在Rails中创建嵌套表单,但是当我去保存母亲和男孩时,它说:

ActiveModel::MissingAttributeError - can't write unknown attribute `mother_id`:

这是正常的,因为专栏mother_id并不存在。但是,我不需要保存母亲模型,只需要我使用宝石茧的形式的许多男孩,然后立即删除母亲的一个我不再需要的模型。

如何绕过男孩表中mother_id列的不存在而只保存男孩行而不引用&#34;假&#34;母亲?

在Rails中是否有办法创建一个表单,我可以在其中使用类似Cocoon的机制,但使用相同的模型实例而不是子模型,没有&#34; accepts_nested_attributes_for&#34;要清楚吗?

1 个答案:

答案 0 :(得分:0)

在您的情况下完全没有Mother模型,也不需要使用cocoon,因为您不需要保存父模型。我要做的是创建一个仅用于创建Boy的表单,如果你希望它看起来是“嵌套”的形式,那么你可以对其进行Ajax化以使其具有嵌套的外观。

删除Mother模型,您不需要它,然后为Boy

添加一组基本路线

的routes.rb

resources :boys

boys_controller.rb

def create
        respond_to do |format|
            @boy = Boy.new boy_params
            @boy.save
            format.js
        end
end

_form.rb

#just make sure you have remote: true and check that you are always creating a new Boy
<%= form_for Boy.new, builder: yourBuilder, remote: true do |f| %>
.....
<% end %>

在您的视图中的某些位置添加了一个div,您可以在其中显示您的男孩,并在以后每次创建新的时候添加它们:

        <div id="boys">
            #Whatever collection you can get for show the current created boys I do not know, let's say current_user
            <% current_user.boys.each do |boy| %>
                <%= render boy %>
            <% end %>
        </div>

接下来只需添加create操作的脚本:

男孩/ create.js.erb

#If @boy is still not persisted it means it has errors, display errors
<% if @boy.new_record? %>
    $('#boy_form').append("<span class=\"error\"><%= j @boy.errors.full_messages.join(', ').html_safe %></span>");
    setTimeout(function() {
      $('#new_group_goal .error').remove();
    }, 8000);
<% else %>
   #Else we prepend the @boy in the div #boys and that's it, you form is beautifully ajaxified.
    $('#boys').prepend("<%= j render(@boy) %>");
    setTimeout(function() {
      $('# .error').remove();
    }, 2000);
<% end %>

这样你就可以使用Ajax创建Boy的单一形式,你可以动态地添加男孩,它看起来像一个嵌套的表单,而不是让你有1个提交动作你执行提交以创建所有男孩们,你将为每个男孩执行1次提交动作,并在表单下方动态显示,这种方式更加灵活,除此之外还有更好的表现。如果你理解我的观点,请告诉我。