在rails 3中构建动态查询

时间:2014-05-07 20:21:35

标签: ruby-on-rails-3

我在这个问题上一直在苦苦挣扎。我有一个相当复杂的查询,我拼凑在一起,但在我看来,它太冗长和丑陋。 我有一个高级门票搜索表单,其中包含8个不同的搜索字段,以及created_at和updated_at搜索选项,用户可以在其中选择日期,月份和/或年份来过滤其结果。
我正在我的ticket_controller中构建查询条件,如下所示。

conditions  = String.new
  arguments = []

  unless params[:id].blank?
    conditions << ' AND ' unless conditions.length == 0
    conditions << 'tickets.id = ?'
    arguments << params[:id]
  end

  unless params[:organization].blank?
    conditions << ' AND ' unless conditions.length == 0
    conditions << 'organizations.name ILIKE ?'
    arguments << "%#{params[:organization]}%" 
  end

  unless params[:keywords].blank?
    conditions << ' AND ' unless conditions.length == 0
    conditions << 'subject ILIKE ?'
    arguments << "%#{params[:keywords]}%"
  end

  unless params[:status_id].blank?
    conditions << ' AND ' unless conditions.length == 0
    conditions << 'status_id = ?'
    arguments << params[:status_id]
  end

  unless params[:resolution_status_id].blank?
    conditions << ' AND ' unless conditions.length == 0
    conditions << 'resolution_status_id = ?'
    arguments << params[:resolution_status_id]
  end

  unless params[:priority_id].blank?
    conditions << ' AND ' unless conditions.length == 0
    conditions << 'priority_id = ?'
    arguments << params[:priority_id]
  end

  unless params[:assigned_to_id].blank?
    conditions << ' AND ' unless conditions.length == 0
    conditions << 'assigned_to_id = ?'
    arguments << params[:assigned_to_id]
  end


  @tickets = Ticket.joins(:organization).where(conditions, arguments).paginate(:page => params[:page], :per_page => 20).order("updated_at DESC")

对于有特殊连接的字段,我会感到困惑。例如,我有另一个表上的电子邮件列,并在tickets.rb中创建了一个单独的方法,如下所示。

def self.email(email)
    joins('LEFT OUTER JOIN assignments ON assignments.person_id = tickets.owner_id').where('assignments.email_address ILIKE ?', email)
end

然后用这样的术语来调用它

params[:email].blank? ? nil : @tickets = @tickets.email("%#{params[:email]}%")

我还有一个联系人搜索字段,用于搜索我的人员表的名字和姓氏。我创建了一个看起来像这样的单独方法......

def self.contact(contact)  
  joins('LEFT OUTER JOIN people ON people.user_id = tickets.owner_id').where('people.last ILIKE ? OR people.first ILIKE ?', contact, contact)
end

然后像在params [:email]中那样用另一种方式调用它。 这对我而言似乎并不是最好的方式,但我是编程的新手,并且能够想出任何更优雅的东西。我有一些或这些三元运算符正在构建我的查询,虽然它工作得很好,但我不能帮助,但感觉我在这里做错了什么。 我希望这是足够的信息继续下去,如果不是我可以在需要时澄清。

1 个答案:

答案 0 :(得分:0)

在我看来,你正在手动完成所有ActiveRecord的工作。

我的每个案例都有一个范围:

例如:

#class Ticket < ActiveRecord::Base

scope :with_subject lambda { |keyword| where('subject ILIKE ?', keyword) }
scope :with_status_id { |s_id| where(status_id: s_id) }

将按如下方式使用:

@tickets = Ticket.scoped
@tickets = @tickets.with_subject(params[:keywords]) unless params[:keywords].blank?
@tickets = @tickets.with_status_id(params[:status_id]) if params[:status_id].present?

连接也可以链接在AR语法

@tickets = @tickets.joins('LEFT OUTER JOIN people ON people.user_id = tickets.owner_id')

唯一的问题是使用OR子句,IMO在SQL语法中更具可读性

where('people.last ILIKE ? OR people.first ILIKE ?', contact, contact)

希望它有所帮助。

PS:您可以在相关的Rails guide

上找到有关此主题的更多信息