【问题标题】:Rails: passing params hash to modelRails:将参数哈希传递给模型
【发布时间】:2014-03-13 06:36:42
【问题描述】:

我有一个用户对用户的消息传递系统。我正在尝试将一组用户 ID 传递给 ConversationUser(连接表)模型,然后该模型将从每个 user.id 中创建多个 conversation_usersConversationUser 中的两个字段是 conversation_iduser_id。我能够初始化单个对话用户,因为新的 conversation_id 正在传递给模型,但由于某种原因,用户 ID 的哈希没有进入我的模型。我收到了Validation failed: User can't be blank

我的对话/捕获 user_ids 的新视图:

<%= check_box_tag "conversation_user[recipient][]", user.id %> <%= user.name %><br />

我知道这是有效的,因为我收到的部分参数是:

"conversation_user"=>{"recipient"=>["9", "10"]}

我的 Rails 4 控制器和强大参数的要点:

class ConversationsController < ApplicationController
  def new
    @user = User.find(params[:user_id])
    @conversation = @user.conversation_users.build
    @conversation.build_conversation.messages.build
  end

  def create
    @conv = Conversation.create!
    @conversation = @conv.conversation_users.create!(conversation_user_params)
  end

  def conversation_user_params
    params.require(:conversation_user).permit(recipient: [])
  end

我的 ConversationUser 模型的要点:

class ConversationUser < ActiveRecord::Base
  attr_accessor :recipient

  before_create :acquire_conversation

  validates :user_id, :conversation_id, presence: true 

  def acquire_conversation
    unless recipient.blank?
      recipient.each do |u|
        ConversationUser.create(user_id: u, conversation: conversation)
      end
    end
  end
end

我认为问题出在我控制器的conversation_user_params 中。但它也可能在模型的before_create 方法中。我已经尝试解决这个问题一天了,进行了大量调试但没有成功。如果有人可以提供帮助,我提前感谢您。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord strong-parameters actioncontroller


    【解决方案1】:

    问题出在模型上。在创建ConversationUser 之前调用before_create 回调。让我们将这个创建的ConversationUser 命名为CURRENT。因此,在创建 CURRENT ConversationUser 之前,您遍历收件人 ID 并为每个收件人创建一个 ConversationUser。您在此处创建的 ConversationUsers 不是 CURRENT ConversationUserCURRENT ConversationUser 在回调执行后保存(在您创建其他ConversationUsers 后)。但在这种情况下,CURRENT ConversationUser 不知道它属于哪个User,因为您将user_id 参数传递给您在before_create 回调中创建的ConversationUsers,但您没有将其传递给CURRENT ConversationUser 创建时(执行原始create! 方法时)。

    要解决此问题,您可以覆盖原始 create! 方法或根本不使用它来通过收件人 ID 创建 ConversationUsers。将新方法添加到您的 Conversation 模型(例如 create_conversation_users):

    解决方案

    在控制器中:

    def create
      @conv = Conversation.create!
      @conversation = @conv.create_conversation_users!(conversation_user_params[:recipient])
    end
    

    在模型中:

    class Conversation
      def create_conversation_users!(recipient_ids)
        return if recipient_ids.blank?
    
        recipient_ids.each do |recipient_id|
          conversation_users.create!(user_id: recipient_id, conversation: self)
        end
      end
    end
    

    您还应该更新ConversationUser 模型:

    class ConversationUser < ActiveRecord::Base
      validates :user_id, :conversation_id, presence: true 
    end
    

    【讨论】:

    • 我明白了我的错误。非常感谢你。这很好用。
    【解决方案2】:

    错误在ConversationUser 中。 before_create 回调在数据库中创建记录之前运行但是在运行验证之后。要解决您的问题,您可以做一些事情。其中一个由 Chumakoff 回答。这是您可以使用的另一个选项。

    ConversationUser里面的代码全部去掉,把conversation_user_params改成

    def conversation_user_params
      params[:conversation_user][recipient].map do |recipient|
        { user_id: recipient }
      end
    end
    

    发生的情况是您将{ user_id: 1 } 的数组传递给create!,这与调用多个create!({ user_id: 1 }) 相同。

    【讨论】:

    • 嗯。有趣的。从来没有想过在参数中使用 do 块。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-18
    • 2013-09-04
    • 1970-01-01
    • 2018-04-11
    相关资源
    最近更新 更多