Reputation: 331
I'm trying to locate all subscriptions that have the expiry_date and subscription marked to expired... those each one would pluck its user id and then update that user's role to cancelled. I've come up with the following, but its not truly working.
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
If I just do the following for testing, it works but only for one user
Subscription.where(:subscription_plan => 'cancelled', :expiry_date => Time.now.beginning_of_day).pluck(:user_id)
Upvotes: 0
Views: 64
Reputation: 3298
According to this Rails documentation. I think you may be using pluck in the wrong way, as it states:
Use pluck as a shortcut to select one or more attributes without loading a bunch of records just to grab the attributes you want.
Also on this Rails page it states:
Unlike select, pluck directly converts a database result into a Ruby Array, without constructing ActiveRecord objects. This can mean better performance for a large or often-running query. However, any model method overrides will not be available.
It is important to note where it says, "without constructing ActiveRecord objects." You are using pluck
as if it were returning an ActiveRecord object, which again, isn't what it does.
Let's go through your code to show what I mean:
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
Assuming that you have the proper associations set up you could do something like:
Subscription.where(:subscription_plan => 'cancelled', :expiry_date => Time.now.beginning_of_day).each do |subscription|
subscription.user.role = 'cancelled'
subscription.user.save!
end
Of course, I am making some assumtions about your associations. I am assuming that subscription belongs_to
user and that user either has_one
or has_many
subscriptions.
Upvotes: 0
Reputation: 833
You should set up the appropriate ActiveRecord associations to make this sort of thing trivial.
Also, look into scopes. They are quite useful.
With the proper associations and scopes, you should be able to do something like this:
users = Subscription.expired.users
users.each do |user|
user.role = 'cancelled'
user.save!
end
Or use the clever update_all
method that Rahul Singh suggested with associations and scopes.
Upvotes: 2
Reputation: 3427
pluck(:user_id) only returns array of user ids , you can do it as
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")
Upvotes: 2