当我有这样的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'"
答案 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)
我认为最终需要成为某种类型的方法(如果你想变得更复杂的话,还需要struct
或hash
)。
使用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
leads
和prospects
联系,我这样称呼它:
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
找到另一种访问这些模型的方法,并实现相同的目标。