Rails Arel加入连接表

时间:2019-10-01 16:30:04

标签: ruby-on-rails

因此,当用户的角色名称与Region的名称匹配时,我试图过滤,而在三个表之间的Arel连接上却卡住了。

用户具有名称,role_id,电子邮件等。用户具有has_many个角色。角色表具有ID和名称。区域具有名称,位置。地区不属于用户。

示例:

  • John Smith,id:20,role_id:15
  • 角色ID:15,名称:Pacific Northwest
  • 地区ID:5,名称:Pacific Northwest

所以我想是用户加入区域名称匹配的区域

到目前为止我所拥有的:

scope :for_user, lambda { |user|
 if user.super_admin?
  self
 else
  joins(:region).where(
  Region.arel_table[:name].matches(Role.arel_table[:id].eq(User.arel_table[:role_id]))
 )
 end
}

def viewable_by?(user)
 return user.super_admin? || user&.role.name == region.name
end

我在事件控制器中引用了for_user和viewable_by

def index
 @events = search_event.paginate(page: params[:page])
end

def search_event
 Event.order(sortable_query)
    .for_user(current_user)
    .includes(:region)
    .advanced_search(
     params[:search],
     params[:region_id]
    )
end

def load_event
 @event = Event.find_by!(id: params[:id])
 raise DeniedError unless @event.viewable_by?(current_user)
end

我认为这可能是比赛问题,所以我也尝试了。出现同样的问题:没有将Symbol隐式转换为String。

这个想法是给用户分配了一个角色,并且只能查看具有与该角色匹配的名称的事件。

因此,如果约翰·史密斯(John Smith)登录,他只会看到太平洋西北地区的那些事件。

2 个答案:

答案 0 :(得分:2)

我可能还没有完全理解您的问题,但是看来您应该能够执行以下操作:

Event < ApplicationRecord
  belongs_to :region

  class << self

    def for_user(user)
      return self if user.super_admin?
      joins(:region).where(region: {id: Region.where(name: user.role.name)})
    end

  end
end

这应该返回所有Event,其中event.region_id持有任何idRegion匹配的name的{​​{1}}在name的{​​{1}}中。

您可以从Specifying Conditions on the Joined Tablesdocs了解更多信息。

我看到您有一种使用user的方法。我将以非role,非arel_table,非arel_table的方法来处理。

此外,我将在评论中重申docs的状态:

  

使用类方法是接受范围参数的首选方法。

答案 1 :(得分:0)

在百灵鸟上我尝试了,并且奏效了:

joins(:region).where(
              Region.arel_table[:name].matches("%#{user&.role.name}%")
            )