Rails活动记录查询到字符串

时间:2015-04-15 18:40:59

标签: mysql ruby-on-rails ruby ruby-on-rails-3

当我有这样的AR查询时:

MyModel.joins(:related_model).where('related_model.some_column = ?', 'somevalue')

如果我在上面的代码中使用to_sql,它会生成如下内容:

"SELECT * FROM MY_MODEL INNER JOIN RELATED_MODEL ON RELATED_MODEL.SOME_ID = MY_MODEL.SOME_ID WHERE RELATED_MODEL.SOME_COLUMN = 'SOMEVALUE'"

我正在创建一个稍微或更复杂的查询,我讨厌重复代码。有没有办法让我可以用一些命令来改变下面生成的SQL?

INNER JOIN RELATED_MODEL ON RELATED_MODEL.SOME_ID = MY_MODEL.SOME_ID WHERE RELATED_MODEL.SOME_COLUMN = 'SOMEVALUE'"

2 个答案:

答案 0 :(得分:0)

foo = MyModel.joins(:related_model).where('related_model.some_column = ?', 'somevalue').to_sql`

core_sql = foo.sub(/^SELECT * FROM MY_MODEL /,'')`

答案 1 :(得分:0)

我认为最终需要成为某种类型的方法(如果你想变得更复杂的话,还需要structhash)。

使用table_name方法访问模型后面的基础表,您可以执行类似的操作。

def auto_joins (primary_model, related_models, values)
   search = primary_model + '.table_name'
   primary_table_name = eval(search)
   primary_id = primary_table_name + '_id'
   output_sql = "SELECT * FROM #{primary_table_name}"
   related_models.each do |model|
       search = model + '.table_name'
       table_name = eval(search)
       output_sql += " INNER JOIN #{table_name} ON #{table_name}.#{primary_id} = #{primary_table_name}.id "
   end
   output_sql += "WHERE 1 = 1 " #overcome no values passed in...
   values.each do |where|
        output_sql += "AND #{where}"
   end
   output_sql
end

在我的测试数据库中,我与had_many leadsprospects联系,我这样称呼它:

auto_joins('Contact', ['Lead', 'Prospect'], ["contact.first_name = 'Brian'"])

它产生了这个:

SELECT * FROM contacts 
  INNER JOIN leads ON leads.contacts_id = contacts.id  
  INNER JOIN prospects ON prospects.contacts_id = contacts.id 
  WHERE 1 = 1 AND contact.first_name = 'Brian'

如果你想进一步采取行动,你可以得到{model: 'Contact', where: "first_name = 'Brian'"}的哈希值,以及基于此的地点和联接。

编辑注意:如果您将任何此类内容暴露给用户输入,则Evals不安全。您可以通过activerecord找到另一种访问这些模型的方法,并实现相同的目标。

相关问题