开发者

Can a 3-way relationship be modeled this way in Rails?

开发者 https://www.devze.com 2023-01-20 23:57 出处:网络
A User can have many roles, but only one role per Brand. Class User < AR::Base has_and_belongs_to_many :roles, :join_table => \"use开发者_JAVA技巧r_brand_roles\"

A User can have many roles, but only one role per Brand.

Class User < AR::Base
    has_and_belongs_to_many :roles, :join_table => "use开发者_JAVA技巧r_brand_roles"
    has_and_belongs_to_many :brands, :join_table => "user_brand_roles"
end

The problem with this setup is, how do I check the brand and the role at the same time?

Or would I better off with a BrandRole model where different roles can be set up for each Brand, and then be able to assign a user to a BrandRole?

Class User < AR::Base has_many :user_brand_roles has_many :brand_roles, :through => :user_brand_roles end

Class BrandRole < AR::Base belongs_to :brand belongs_to :role end

Class UserBrandRole < AR::Base belongs_to :brand_role belongs_to :user end

This way I could do a find on the brand for the user:

br = current_user.brand_roles.where(:brand_id => @brand.id).includes(:brand_role)
if br.blank? or br.role != ADMIN
  # reject access, redirect
end

This is a new application and I'm trying to learn from past mistakes and stick to the Rails Way. Am I making any bad assumptions or design decisions here?


Assuming Roles,Brands are reference tables. You can have a single association table Responsibilities with columns user_id, role_id, brand_id. Then you can define

Class User < AR::Base
 has_many : responsibilities
 has_many :roles, :through => responsibilities
 has_many :brands,:through => responsibilities
end
Class Responsibility < AR::Base
 belongs_to :user
 has_one :role
 has_one :brand
end

The you can define

Class User < AR::Base
  def has_access?(brand)
     responsibility = responsibilities.where(:brand => brand)
     responsibility and responsibility.role == ADMIN
  end
end

[Not sure if Responsibility is the term used in your domain, but use a domain term instead of calling it as user_brand_role]


This is a conceptual thing. If BrandRole is an entity for your application, then your approach should work. If BrandRole is not an entity by itself in your app, then maybe you can create a UserBrandRole model:

class User < AR::Base
  has_many :user_brand_roles
end

class Brand < AR::Base
  has_many :user_brand_roles
end

class Role < AR::Base
  has_many :user_brand_roles
end

class UserBrandRole < AR::Base
  belongs_to :user
  belongs_to :brand
  belongs_to :role
  validates_uniqueness_of :role_id, :scope => [:user_id, :brand_id]
end
0

精彩评论

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