一个模型上有多个habtm关系

时间:2012-10-22 02:29:54

标签: ruby-on-rails join mapping has-and-belongs-to-many

我正在努力找出解决问题的最佳方法。我有一个页面表和一个user_types表。我试图在页面上指定多个用户类型。他们将作为许可组。但是,我需要做两次。一次用于读取权限,一次用于编辑权限。这是一个例子:

主页有3种可以阅读的用户类型 - admin,super admin,public 它有2种用户类型可以编辑它 - admin,super admin

我有一个user_types表: 管理 超级管理员 上市 等

我创建了两个映射表(一个用于读取,一个用于编辑): pages_user_read_types pages_user_edit_types

他们都有page_id和user_type_id

有没有更好的方法来实现这一目标?如果这是最好的方法,我需要帮助找出模型的关系。我有一个关系

  has_and_belongs_to_many :user_types, :join_table => :pages_user_read_types

如何为单独的字段指定两个关系?

由于

2 个答案:

答案 0 :(得分:1)

至少,您可能想要添加Permission模型。如果它比你描述的更复杂,我还建议使用CanCan

class Permission < ActiveRecord::Base
  #table is id, page_id, user_type_id, and permission_type (string).
  belongs_to :page
  belongs_to :user_type
end

在您的控制器中,您可以构建如下过滤器链:

class PagesController < ApplicationController
  before_filter :load_page
  before_filter :authorize_view!, only: [ :show ]
  before_filter :authorize_edit!, only: [ :edit ]

  def show
  end

  def edit
  end

  private
    def load_page
      @page = Page.find(params[:id])
    end

    def authorize_view!
      if !@page.permissions.where(user_type_id: current_user.user_type_id, permission_type: "view").exists?
        flash[:notice] = "You do not have permission to view that page."
        redirect to root_path
      end
    end

    def authorize_edit!
      if !@page.permissions.where(user_type_id: current_user.user_type_id, permission_type: "edit").exists?
        flash[:notice] = "You do not have permission to edit that page."
        redirect to root_path
      end
    end

end

(这假设您的应用中有current_user方法。)

答案 1 :(得分:1)

在过去的几年里,Rails的HABTM关系似乎已经失去了对Rails开发人员has_many :through关系的偏爱。您应该使用HABTM的唯一时间是您不需要有关两个模型之间关系的任何其他信息。在您的情况下,您可以通过创建两个HABTM关系来尝试模拟这个,当您可以通过具有可编辑属性的连接模型来有效地完成此任务。

在代码中,它看起来像这样:

class Page < ActiveRecord::Base
  has_many :page_permissions
  has_many :user_types, :through => page_permissions

  def editable_user_types
    page_permissions.includes(:user_types).where(:editable => true).map(&:user_type)
  end

  def read_only_user_types
    page_permissions.includes(:user_types).where(:editable => false).map(&:user_type)
  end      
end

class PagePermission < ActiveRecord::Base
  belongs_to :page
  belongs_to :user_type
  # When you create this model, you should have a boolean attribute for editable
end

class UserType < ActiveRecord::Base
  has_many :page_permissions
  has_many :pages, :through => :page_permissions
end

我认为,如果您需要在 Page < / em>和 UserType