0

検索可能で並べ替え可能なテーブルを作成しています。実際、いくつかの細かい部分を除いて、すでに作成しています。列名に従ってソートしていますが、レールのリジェクトはそのうちの 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。会議

belongs_to :developer, :class_name => 'User', :foreign_key => 'developer_id'

Railsは名前でソートしようとしていると思いますが、confには名前がなく、次のようなエラーが発生します

no such column: name: SELECT  "confs".* FROM "confs"

ユーザーの列で定義されたSort_columnですが、ユーザーの列は開発者の列とは異なるため、レールは動作すると思います。開発者の列を認識するようにレールを作成するにはどうすればよいですか? 注: Conf.developer.column_names.include?... を試しましたが、「undefined method developer」というエラーが表示されます

4

1 に答える 1

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この規則を許可するには、ロジックを変更する必要がある場合があります。

これを行う 1 つの方法は、次のようになります。

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

アップデート

したがって、2 番目の方法を使用すると、データの取得は次のようになります。

@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>

修飾名が必要になるため、2 番目の方法が適しているようです。classify.constantizeモデルクラスを動的にチェックするために使用すると、リスクの要素が含まれる可能性があることに注意してください。これを軽減するには、利用可能なクラスのホワイトリストを使用できます。これを示すために更新されました。

于 2013-09-03T13:24:19.980 に答える