2014-06-12 49 views
0

我試圖找到所有具有expiry_date和訂閱標記爲過期的訂閱......每個訂閱者都會摘取其用戶標識,然後將該用戶的角色更新爲取消。我已經提出了以下內容,但它並不真正起作用。Rails如何找到並更新另一個模型中的列?

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) 
+1

pluck返回一個數組。嘗試user = subscription.pluck(:user_id).first – Mandeep

回答

2

你應該設置合適的ActiveRecord associations來使這種事情變得微不足道。

另請參閱scopes。它們非常有用。

有了正確的協會和範圍,你應該能夠做這樣的事情:

users = Subscription.expired.users 

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

或者使用巧妙的update_all方法拉胡爾·辛格與建議協會和範圍。

2

勇氣(: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") 
0

根據this Rails documentation。我認爲你可能會使用錯誤的方式,因爲它指出:

使用pluck作爲選擇一個或多個屬性的快捷方式,不加載大量記錄只是爲了獲取所需的屬性。

同樣在this Rails page它指出:

不同於選擇,拔毛直接轉換數據庫結果放入一個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訂閱。

相關問題