我正在做一个可搜索的&可排序表。实际上我已经把它与一些小细节分开了。我根据列名进行排序,但rails拒绝识别其中的1个。现在,那就是我的index.html.erb:
<table class="pretty" border="1" cellpadding="10">
<tr>
<th><%= sortable("machine_name", "M.Name") %></th>
<th><%= sortable("machine_brand", "M.Brand") %></th>
<th><%= sortable("machine_model", "M.Model") %></th>
<th><%= sortable("control_unit_brand", "C.Unit Brand") %></th>
<th><%= sortable("control_unit_model", "C.Unit Model") %></th>
<th><%= sortable("tool_axis_x", "Axis X") %></th>
<th><%= sortable("tool_axis_y", "Axis Y") %></th>
<th><%= sortable("tool_axis_z", "Axis Z") %></th>
<th><%= sortable("rotary_axis_number", "R.Axis") %></th>
<th><%= sortable("linear_axis_number", "L.Axis") %></th>
<th><%= sortable "description" %></th>
<th><%= sortable("name", "Developer") %></th>
<th><%= sortable "updated_at" %></th>
</tr>
<% for conf in @confs %>
<tr class="<%= cycle('oddrow', 'evenrow') -%>">
<td><%= link_to conf.machine_name, conf %></td>
<td><%= conf.machine_brand %></td>
<td><%= conf.machine_model %></td>
<td><%= conf.control_unit_brand %></td>
<td><%= conf.control_unit_model %></td>
<td><%= conf.tool_axis_x %></td>
<td><%= conf.tool_axis_y %></td>
<td><%= conf.tool_axis_z %></td>
<td><%= conf.rotary_axis_number %></td>
<td><%= conf.linear_axis_number %></td>
<td><%= conf.description %></td>
<td><%= conf.developer.name unless conf.developer_id.blank? %></td>
<td><%= conf.updated_at %></td>
</tr>
<% end %>
</table>
您可以通过developer_id了解我是如何与模型Conf的开发人员联系并显示其名称的。这部分是有效的,但是,当它打破它时!可排序的操作使用sort_column,就是这样:
def sort_column
( (User.column_names.include?(params[:sort])) || (Conf.column_names.include?(params[:sort])) ) ? params[:sort] : "machine_name"
end
用户是模特。 Conf是另一种模式。用户has_many confs。 CONF
belongs_to :developer, :class_name => 'User', :foreign_key => 'developer_id'
我认为rails尝试按名称排序,但conf没有名称,给出错误,如
no such column: name: SELECT "confs".* FROM "confs"
使用用户列定义Sort_column但我认为rails的行为与User列的不同于开发人员列。如何识别开发人员列? 注意:我试过Conf.developer.column_names.include?...但是收到错误“undefined method developer”
答案 0 :(得分:1)
最简单的解决方案是在提取数据时添加'developer_name'列:
@conf = your_current_logic.
includes(:developer). # eager load your developer relation
where('users.id IS NULL OR users.id IS NOT NULL'). # a meaningless filter to force a LEFT JOIN
select("confs.*, users.name as developer_name")
然后,您可以在可排序列中引用“developer_name”。
或者,您只需将sortable('name', ...)
替换为sortable('users.name', ...)
即可。您可能需要修改sort_column
逻辑以允许此约定。
这样做的一种方法可能是这样的:
def sort_column
if params[:sort] =~ /([^\.]+)\.([^\.]+)/ && # check if 'table.column' format is used
%w(users confs).include? $1 && # check if table name matches expectations
$1.classify.constantize.column_names.include?($2) # check if column is present in table's class
params[:sort] # 'table.column' format
elsif Conf.column_names.include?(params[:sort])) # if 'column' format is used, just check Conf class
params[:sort] # 'column' format
else
"machine_name" # default sort column
end
end
<强>更新强>
因此,使用第二种方法,您的数据检索可能如下所示:
@confs = Conf.search(params[:search]).
includes(:developer).
where('users.id IS NULL OR users.id IS NOT NULL').
order(sort_column + ' ' + sort_direction).
paginate(:per_page => 10, :page => params[:page])
任何含糊不清的列(例如updated_at)都应按表名限定:
<th><%= sortable "confs.updated_at" %></th>
由于你将需要合格的名字,这听起来像是第二种方法。请注意,使用classify.constantize
动态检查模型类可能存在风险因素 - 您可以使用可用类的白名单来缓解此问题。更新以证明这一点。