3

I have a has_many relationship of models Role and Access through model Permission.

I have a situation that no two roles should have identical accesses. So, I created a custom validation which basically results in an error message when current role(being created) is assigned the same accesses as previously existing roles using,

errors.add(:Role, "already exists with selected permissions") if Role.all.map(&:access_ids).include?(self.access_ids)

This all works fine. Now I need to fetch the role which has identical accesses as current role. So, how do I do that ? I tried with

Role.includes(:accesses).where(:accesses => {:id => [1,2]}).count

but this returns all roles whose access ids have either 1 or 2 (say [1, 2, 3, 4], [1], [2]) . What I need is to get the role whose access ids are exactly 1 and 2.

It would be nice if i could replace '=>' with '==' in above query :) But that obviously does not work.

prasvin
  • 3,009
  • 23
  • 28

1 Answers1

0

Don't know the query to this one but you can get the role through ruby doing this

Role.all.to_a.find{|r| r.access_ids == self.access_ids}

As a response to your comment below that this fires too many queries, use this method which will only fire 2 queries..

 Role.includes(:permissions).find{|r| r.permissions.map(&:access_id) == self.access_ids}

You can also use this for your validation,

Role.includes(:permissions).any?{|r| r.permissions.map(&:access_id) == self.access_ids}

You suggested Role.includes(:accesses) fires three queries whereas Role.includes(:permissions) only fires two

Dipil
  • 2,628
  • 1
  • 20
  • 25
  • hmm..it works but somehow seems that having a loop results in a lot of query statements. Theres a typo too, it should be r.access_ids. I was advised to avoid such loop during database query. Anyway, thanks – prasvin Nov 18 '11 at 08:53
  • You are using a similar loop above to check for the validation you showed above, that is why i suggested using this technique. If you can come up with a better solution for the validation above, you can use the same query to get the role below. – Dipil Nov 18 '11 at 09:02