【问题标题】:Ruby on Rails: Iterate model values from another model before_create / before_saveRuby on Rails:从另一个模型 before_create / before_save 迭代模型值
【发布时间】:2026-02-18 17:35:02
【问题描述】:

我有一个 RoR 应用程序,可以让人们匿名发帖,因为他们会将他们的电子邮件地址放在一个字段中。

模型是这样的。

后模型。

post.rb
  belongs_to :user # optional: true --> this is for rails 5

用户模型

user.rb
  has_many :posts

我的帖子模型有这些列:title、body、user_email:string、user_id:integer

我的用户模型来自 devise gem。

在我的应用中,我允许用户在不登录或不注册的情况下发帖。这意味着他们可以创建帖子,并且 user_id 列将是空白的(因为他们需要输入他们的电子邮件)。

但是,我想要实现的是,如果他们注册了我的应用,则与他们注册的用户关联的所有帖子都应将 user_id 列更改为其对应的 user.id。所以在我的 user.rb 模型中,我添加了这段代码。

# user.rb
before_save :associate_post_to_user

def associate_post_to_user
  Post.all.each do |post|
    if post.user_email == self.email
      post.user_id = self.id
    end
  end
end

但是,每当他们创建帐户时,post 中 user_id 的值都不会改变。我如何实现这一目标?我正在使用设计宝石顺便说一句。提前致谢!

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 devise ruby-on-rails-5


    【解决方案1】:

    您的代码中有两个问题:

    1. post.user_id = self.id

    2. 之后没有post.save
    3. 使用Post.all,SQL会查询所有Post记录,会有性能问题。

    也许你可以这样改变它:

        def associate_post_to_user
           Post.where(user_email: self.email).update_all(user_id: self.id)
        end
    

    【讨论】:

    • 谢谢!这真的很有帮助。我不知道有一个叫 update_all 的助手。 BTW,你是怎么认识这些帮手的?是否有专门的书可以教授所有这些内容?
    • 经常阅读rails api,对你有更多帮助。参考apidock.com/rails/v4.0.2/ActiveRecord/Relation/update_all
    【解决方案2】:

    由于before_save 钩子是为您的User 模型定义的,您需要明确地save 您的Post 实例。

    # user.rb
    before_save :associate_post_to_user
    
    def associate_post_to_user
      Post.all.each do |post|
        if post.user_email == self.email
          post.user_id = self.id
          post.save
        end
      end
    end
    

    【讨论】:

    • 谢谢!我虽然这样做 post.save 将是多余的,因为模型当前尚未保存(这就是 before_save 的原因)。现在我知道这不是谢谢!
    最近更新 更多