【问题标题】:Update attribute in associated model in Rails when parent is updated更新父级时更新Rails中关联模型中的属性
【发布时间】:2020-11-25 01:30:15
【问题描述】:

我有两个模型用户和分配。每当更新用户时,我都想更新分配中的 url 属性。

我该怎么做?

class User
  has_many :assignments
  ...
end

class Assignment
   belongs_to :user

   before_save :set_url

   def set_sandbox_url
        language = 'www'
        project = 'example'
        base_url = "https://#{language}.#{project}.org/"
        sandbox_url = "#{base_url}/User:#{user.username}/#{article_title}"
   end

【问题讨论】:

  • 您的before_save 应该在User 中,您可以使用它来更新相关的分配。但是,用户有很多任务,所以我不知道您要更新哪些。
  • 感谢您回来!作业中的 url 使用用户名,因此我需要更新与用户相关的每个作业。
  • 你确定你应该这样存储 URL 吗?应该动态计算而不是存储在数据库中。这不是 WordPress :D

标签: ruby-on-rails ruby database


【解决方案1】:

我同意 Tamer Shlash 的观点,将这个 URL 存储在数据库中并没有真正的好处,因为它可以在您每次需要时轻松生成。

但除此之外,我想回答你的问题。由于各种原因,您重新生成 URL 的回调不起作用。首先,您想在用户更改时更新 URL,因此用户需要定义一个回调。二是命名不正确。当前编写的回调将尝试运行set_url 方法,但该方法实际上称为set_sandbox_url。第三,sandbox_url = 只会将新 URL 分配给局部变量 sandbox_url,但不会更新实例变量 @sandbox_url

我会这样做:

# in app/models/user.rb
after_save :update_assignment_url

private
def update_assignment_url
  assignments.each(&:update_url) if username_previously_changed?
end

# in app/models/assignments.rb
def update_url
  language = 'www'
  project = 'example'
  base_url = "https://#{language}.#{project}.org/"
  sandbox_url = "#{base_url}/User:#{user.username}/#{article_title}"

  update!(sandbox_url: sandbox_url)
end

注意:因为您通过简单地连接字符串来构建 URL,所以我建议确保这些字符串(尤其是用户提供的值,例如 username 和 article_title)仅包含 URL 中有效的字符(例如,使用 String#parameterize )。

您可能还想了解Dirty Attributes,它提供了使用的username_previously_changed? 方法。

【讨论】:

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