When I have the AR query like this :
MyModel.joins(:related_model).where('related_model.some_column = ?', 'somevalue')
If I used to_sql
on the above code it would generate something like :
"SELECT * FROM MY_MODEL INNER JOIN RELATED_MODEL ON RELATED_MODEL.SOME_ID = MY_MODEL.SOME_ID WHERE RELATED_MODEL.SOME_COLUMN = 'SOMEVALUE'"
I'm creating a slightly, or way more complex query, and I hate to duplicate code. Is there are way that I can get this part with some command to alter the generated SQL below?
INNER JOIN RELATED_MODEL ON RELATED_MODEL.SOME_ID = MY_MODEL.SOME_ID WHERE RELATED_MODEL.SOME_COLUMN = 'SOMEVALUE'"
foo = MyModel.joins(:related_model).where('related_model.some_column = ?', 'somevalue').to_sql`
core_sql = foo.sub(/^SELECT * FROM MY_MODEL /,'')`
I think will end up needing to be a method of some sort with arrays (or a struct
or hash
if you want to get more complex).
Using the table_name
method to access the underlying table behind a model you could do something like this.
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
And in my test database I had contact that had_many
leads
and prospects
I called it like this:
auto_joins('Contact', ['Lead', 'Prospect'], ["contact.first_name = 'Brian'"])
and it generated this:
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'
If you wanted to take it further you could have a hash for {model: 'Contact', where: "first_name = 'Brian'"}
and both the where and joins together based on that.
Edit Note: Evals are unsafe if you are exposing any of this to user input. You could find another way to access these models through activerecord
and accomplish the same goal.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.