2017-05-31 49 views
0

我有一个员工视图,其中列出了所有技能,这些技能都写在我的数据库的技能表中。对每一位员工来说,所有技能都会显示出来,就像想要的一样。Rails,解决这个n + 1的技巧?

员工和技能彼此之间有很多关联:通过关联。

class Employee < ApplicationRecord 
    has_many :employeeskillsets, foreign_key: "employee_id" 
    has_many :skills, through: :employeeskillsets 
end 

class Skill < ApplicationRecord 
    has_many :employeeskillsets, foreign_key: "skill_id" 
    has_many :employees, through: :employeeskillsets 
end 

class Employeeskillset < ApplicationRecord 
    belongs_to :employee, foreign_key: 'employee_id' 
    belongs_to :skill, foreign_key: 'skill_id' 
end 

所有这些技能都显示为按键,分别是切换启用/禁用该员工的特定技能(每点击直接插入/删除,没有多余的提交需要)。

<%= link_to apply_skill_employee_path(employee: @employee, skill_id: skill.id), method: :put, remote: :true do %> 
<%= skill.name %></div><% end %> 

但现在,我想要按钮显示颜色,当您加载页面。如果技能已经启用,buttoncolor应该是绿色的,否则是灰色的。这里开始我的问题: 我的应用程序检查每个技能与一个单独的选择语句。我为此使用以下代码:

<%= link_to apply_skill_employee_path(employee: @employee, skill_id: skill.id), method: :put, remote: :true do %> 
    <% if @employee.skills.exists?(skill.id) %> 
    <div class="button skill e-true"><%= skill.name %></div> 
    <% else %> 
    <div class="button skill"><%= skill.name %></div> 
    <% end %> 

我已经尝试使用includes,但似乎存在?独立检查每项技能。

有没有人在这里有一个建议,我怎么能解决这个问题,通过使用一个单一的选择?

在此先感谢,我希望我已经提到了一切,什么是必要的。编辑1:我忘了提及,我通过部分渲染(如果知道这很重要)。 这里是employees_controller中当前使用的@employee var。

@employee = Employee.find_by(id: params[:id]) 

回答

0

尝试pluck荷兰国际集团的ID,然后检查include?因为你并不需要获取的skills

<% skills = @employee.skills.pluck(:id) %> 
<%= link_to apply_skill_employee_path(employee: @employee, skill_id: skill.id), method: :put, remote: :true do %> 
<% if skills.include?(skill.id) %> 
    <div class="button skill e-true"><%= skill.name %></div> 
<% else %> 
    <div class="button skill"><%= skill.name %></div> 
<% end %> 
+0

@max请详细说明,afaik作用域查询分贝.. –

0

由于skill也是一个活动记录模式,可以使用include?对员工的技能集检查,如果员工有一个特殊的技能。

@employee.skills.include?(skill) 

这种方式,您可以自由使用includes条款热切负载员工的技能。

0

这所有属性将不会触发额外的查询

<% if @employee.skill_ids.exists?(skill.id) %> 

同时,为了避免n+1在以下行

apply_skill_employee_path(employee: @employee, skill_id: skill.id) 

确保您包括skills

@employee = Employee.includes(:skills).where(......) 
0

Rails的方式就简单得多了。

当您在ActiveRecord的使用has_many宏也带来了_ids方法,其可用于与阵列添加或删除关系:

@employee.skills_ids = [1,2,3] 

这也适用于与:through选项间接关联设定。

您可以用表格收集助手一起使用它来创建选择或复选框标签:

<%= form_for(@employee) do |f| %> 
    <%= f.label :skill_ids, 'Skills' %> 
    <%= f.collection_check_boxes(:skills_ids, Skill.all, :id, :name) %> 
<% end %> 

为了避免额外的查询,你可以做一个左外连接控制器:

def edit 
    # left_outer_joins is new in Rails 5 
    # see https://blog.bigbinary.com/2016/03/24/support-for-left-outer-joins-in-rails-5.html 
    @employee.left_outer_joins(:skills).find(params[:id]) 
end 

您也不需要在控制器中使用一个愚蠢的额外方法来处理应该作为正常更新处理的内容。吻。

+0

这将真正清理我的代码,但我不知道,我可以如何在我的分类中使用它,其结构如下:Topcategories { ,类别:{技能,子类别:{技能}}} – Fast

+0

这似乎不是一个非常优化的布局 - 你应该只需要一个类别模型,并使其自行加入构建层次结构。但那是一个完全不同的问题。 – max

+0

我刚刚为此创建了一个新问题,如果你能帮助我,那会很棒。 https://stackoverflow.com/questions/44324189/rails-category-as-self-referenced-model – Fast