开发者

How to cope with non-persisted and persisted associated objects in Rails at the same time?

I will try to explain this very simple. So, I skipped any code which is not necessary to illustrate the problem.

Let's assume a model:

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

I skipped the code for User and some other models because they are not relevant to illustrate...

We instantiate the code:

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

Line 4. will raise a ModelUserNotAllowedError because the required grant build in line 3 is not persisted at this time, but finder methods only work on persisted data. From a logical point of view, the error shouldn't be raised because the user is suffiecent granted.

I am using self.user_grants.build because the Model may not be persisted when calling grant_user.

So, what are the options to get this working:

1.) Implement code that only uses association.create instead of association.build to ensure f开发者_StackOverflowinder methods are "up-to-date". This also requires to save parents first.

2.) Implement code that checks both persisted data by using finder methods and non-persisted data by looping through the assication, e.g. given the above example, one may do to check non-persisted data:

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

However, proposal number 2 seems to be a bad idea. So, let's forget it...

Are there any other options? e.g. Is there a way to get finder methods to check non-persisted data as well? Hope to get some new insights...


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜