Skip has_many:通过模型创建无变化

时间:2016-07-13 14:45:03

标签: ruby forms ruby-on-rails-5 rails-models

这可能是完全解决这个问题的错误方法,而且我对替代方案非常开放。

我有以下模型,Users可以有多个Positions

class User < ApplicationRecord
  has_many :user_positions
  has_many :positions, through: :user_positions

  accepts_nested_attributes_for :user_positions,
    reject_if: :all_blank
end

class UserPosition < ApplicationRecord
  belongs_to :user
  belongs_to :position
end

class Position < ApplicationRecord
end

在我的编辑用户表单中,我想允许更新User的当前位置。我是通过以下方式做到的:

<%= form_for @user do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>

  <%= f.fields_for :user_positions, @user.user_positions.order(created_at: :desc).first do |ff| %>
    <%= ff.hidden_field :user_id, value: @user.id %>
    <%= ff.collection_select :position_id, Position.all, :id, :label %>
  <% end %>

  <%= f.submit "Update User" %>
<% end %>

我遇到的问题是,每次提交表单时都会创建一个UserPosition的新实例,即使所选的Position没有更改。当position_id的值发生变化时,我真的只关心“促销”或“降级”,这会导致连接表中出现一堆重复的条目。

我不想添加自定义验证器来禁止创建,因为我仍然希望表单能够以不变的位置提交。例如,我只想更改User的名称。

有关如何处理此用例的任何建议吗?

1 个答案:

答案 0 :(得分:0)

事实证明,您实际上可以使用任何方法作为Symbol accepts_nested_attributes_for选项的reject_if参数。

我按如下方式更新了我的User模型,现在行为正是我想要的:

class User < ApplicationRecord
  has_many :user_positions
  has_many :positions, through: :user_positions

  accepts_nested_attributes_for :user_positions,
    reject_if: :same_as_previous_position

  def same_as_previous_position(attributes)
    if self.user_positions.empty?
      return false
    end

    Position.find(attributes[:position_id]) == self.user_positions.order(created_at: :desc).first.position
  end
end