Rails AjaxDatatablesRails::ActiveRecord 同じモデルに LEFT JOIN すると検索エラーが発生する
概要
私のトランザクション モデルには、在庫室モデル オブジェクトを参照する 2 つのフィールドがありました。これにより、検索時にエラーが発生します。これらのフィールドのいずれかによる検索または並べ替えでは、最初の left_join からのデータのみが使用されます。
class Transaction < ApplicationRecord
belongs_to :stored_product
belongs_to :user
belongs_to :from_stockroom, class_name: 'Stockroom', foreign_key: 'from_stockroom_id', optional: true
belongs_to :to_stockroom, class_name: 'Stockroom', foreign_key: 'to_stockroom_id', optional: true
attr_accessor :user_selection
解決策
私のトランザクション モデルには、在庫室モデル オブジェクトを参照する 2 つのフィールドがありました。これにより、検索時にエラーが発生します。これらのフィールドのいずれかによる検索または並べ替えでは、最初の left_join からのデータのみが使用されます。
class TransactionsDatatable < AjaxDatatablesRails::ActiveRecord
extend Forwardable
def_delegators :@view, :current_user
def initialize(params, opts = {})
@view = opts[:view_context]
super
end
def view_columns
@view_columns ||= {
id: { source: 'Transaction.id', cond: :eq, searchable: true },
stored_product_id: { source: 'StoredProduct.name', searchable: true },
user_id: { source: 'User.name', cond: :like, searchable: true },
from_stockroom_id: { source: 'from_stockroom_name', cond: :like, searchable: true, orderable: true },
to_stockroom_id: { source: 'to_stockroom_name', cond: :like, searchable: true, orderable: true },
quantity: { source: 'Transaction.quantity', searchable: false, orderable: false },
comment: { source: 'Transaction.comment', cond: :like, searchable: true, orderable: false },
created_at: { source: 'Transaction.created_at', searchable: false }
}
end
def data
records.map do |record|
{
id: record.id,
stored_product_id: record.stored_product.name,
user_id: record.user.name,
from_stockroom_id: record.from_stockroom.present? ? record.from_stockroom.name : 'Поставка',
to_stockroom_id: record.to_stockroom.present? ? record.to_stockroom.name : 'Списание',
quantity: record.quantity,
comment: record.comment,
created_at: record.created_at.strftime('%d.%m.%Y'),
DT_RowId: record.id
}
end
end
def get_raw_records
Transaction.where(deleted: false)
.joins(:stored_product, :user)
.joins('LEFT JOIN stockrooms AS from_stockrooms ON from_stockrooms.id = transactions.from_stockroom_id')
.joins('LEFT JOIN stockrooms AS to_stockrooms ON to_stockrooms.id = transactions.to_stockroom_id')
.select('transactions.*, from_stockrooms.name as from_stockroom_name, to_stockrooms.name as to_stockroom_name')
end
def filter_records(records)
to_search_value = params[:columns]['4']['search']['value']
from_search_value = params[:columns]['3']['search']['value']
multiple_search_value = params['search']['value']
records = records.where('LOWER(from_stockrooms.name) LIKE ?', "%#{from_search_value.downcase}%") if from_search_value.present?
records = records.where('LOWER(to_stockrooms.name) LIKE ?', "%#{to_search_value.downcase}%") if to_search_value.present?
return records.where(build_conditions) unless multiple_search_value.present?
records.where(build_conditions)
.or(records.where(build_conditions_for_selected_columns).and(stockrooms_colums_search(records,multiple_search_value)))
end
def stockrooms_colums_search(records, multiple_search_value)
records.where('LOWER(to_stockrooms.name) LIKE ?', "%#{multiple_search_value.downcase}%")
.or(records.where('LOWER(from_stockrooms.name) LIKE ?', "%#{multiple_search_value.downcase}%"))
end
end
params[:columns][“4”][“search”][“value”] は、検索可能なすべての列ではなく単一列での検索に使用されます