Rails如何在另一个模型中查找和更新列?

时间:2014-06-12 17:47:34

标签: ruby-on-rails

我正在尝试查找所有已将expiry_date和订阅标记为已过期的订阅...每个订阅者都将获取其用户ID,然后将该用户的角色更新为已取消。我想出了以下内容,但它并没有真正发挥作用。

sub = Subscription.where(:subscription_plan => 'cancelled', :expiry_date => Time.now.beginning_of_day).each do |subscription|
    user = subscription.pluck(:user_id)
    user.role = 'cancelled'
    user.save!
end

如果我只是进行以下测试,那么它只适用于一个用户

Subscription.where(:subscription_plan => 'cancelled', :expiry_date => Time.now.beginning_of_day).pluck(:user_id)

3 个答案:

答案 0 :(得分:2)

pluck(:user_id)只返回用户ID数组,  你可以这样做

user_ids = Subscription.where(:subscription_plan => 'cancelled', :expiry_date => Time.now.beginning_of_day).pluck(:user_id)

User.where("id IN (?)",user_ids).update_all(role:"canceled")

答案 1 :(得分:2)

你应该设置适当的ActiveRecord associations来使这种事情变得微不足道。

另外,请查看scopes。它们非常有用。

通过适当的关联和范围,您应该能够做到这样的事情:

users = Subscription.expired.users

users.each do |user|
  user.role = 'cancelled'
  user.save!
end

或者使用Rahul Singh建议的聪明的update_all方法与关联和范围。

答案 2 :(得分:0)

根据this Rails documentation。我认为你可能正在以错误的方式使用pluck,因为它声明:

  

使用pluck作为快捷方式选择一个或多个属性而不加载一堆记录只是为了获取所需的属性。

同样在this Rails page上声明:

  

与select不同,pluck直接将数据库结果转换为Ruby数组,而不构造ActiveRecord对象。对于大型或经常运行的查询,这可能意味着更好的性能。但是,任何模型方法覆盖都将不可用。

重要的是要注意它所说的“不构建ActiveRecord对象”。您正在使用pluck,就好像它正在返回一个ActiveRecord对象一样,这也不是它所做的。

让我们通过您的代码来展示我的意思:

sub = Subscription.where(:subscription_plan => 'cancelled', :expiry_date => Time.now.beginning_of_day).each do |subscription|
    user = subscription.pluck(:user_id) #user now equals an array of integers (ids not objects)
    user.role = 'cancelled'  #array does not have a "role method"
    user.save!  #again, this is an array, not an active record object
end

假设您设置了正确的关联,您可以执行以下操作:

Subscription.where(:subscription_plan => 'cancelled', :expiry_date => Time.now.beginning_of_day).each do |subscription|
    subscription.user.role = 'cancelled'
    subscription.user.save! 
end

当然,我正在对你的协会做出一些分析。我假设订阅belongs_to用户和该用户has_onehas_many订阅。