【问题标题】:Skip has_many :through Model Creation on No Change跳过 has_many :通过无变化的模型创建
【发布时间】:2016-11-16 05:34:50
【问题描述】:

这可能是完全解决这个问题的错误方法,我对替代方案持开放态度。

我有以下模型,其中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 的名称时。

关于如何处理这个用例的任何建议?

【问题讨论】:

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


    【解决方案1】:

    事实证明,您实际上可以使用任何方法作为 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多