2011-07-13 29 views
1

我會盡力解釋這很簡單。所以,我跳過了不需要說明問題的任何代碼。如何在Rails中同時處理非持久化和持久化的關聯對象?

讓我們假設一個模型:

class Model < ActiveRecord::Base 

    # Join class storing grants for users, e.g. 'admin', 'default' 
    has_many :user_grants 

    # Grant a user a certain grant 
    def grant_user(user, grant) 
    self.user_grants.build(:user => user, :grant => grant) 
    end 

    # Some action is done by a user, but ensure user has required grants 
    def action(user, action_type) 
    unless user_grants.find_by_user_id_and_grant(user, GrantEnum::ADMIN) 
     raise ModelUserNotAllowedError.new 
    end 
    ...action code... 
    end 

我跳過了用戶和代碼一些其他的模型,因爲他們不相關的說明...

我們實例代碼:

1: @model = Model.new 
    2: @user = User.new 
    3: @model.grant_user(@user, GrantEnum::ADMIN) 
    4: @model.action(@user, ActionEnum::SOMETHING) 

第4行將引發ModelUserNotAllowedError,因爲第3行中所需的授權構建不會在此時保留,但finder方法僅對持久數據有效。從邏輯的角度來看,錯誤不應該提出,因爲用戶已被授予永久權限。

我正在使用self.user_grants.build,因爲在調用grant_user時,模型可能不會持久。

那麼,什麼是得到這個工作的選項:

1)實施僅使用association.create,而不是association.build,以確保取景器的方法是「先進的日期代碼」。這也需要首先拯救父母。 2)通過使用循環遍歷整理例如使用查找方法和非持久數據來實現檢查兩個持久數據的代碼。根據上面的例子,可以檢查非持續數據:

user_grants.each do |user_grant| 
    if user_grant.grant.eql?(GrantEnum::ADMIN) 
     return true 
    end 
    end 

然而,提案2號似乎是一個壞主意。所以,讓我們忘了它...

還有其他的選擇嗎?例如有沒有辦法讓finder方法檢查非持久數據?希望得到一些新的見解...

回答

0
unless user_grants.select {|user_grant| user == user && grant == GrantEnum::ADMIN}.present? 
     raise ModelUserNotAllowedError.new 
end