Last Updated: January 28, 2019
·
786
· wojtekkruszewsk

Reusing SQL logic in Rails models

Suppose you have following named scope:

class Task
scope :active, ->{ where("LOTS OF LOGS OF FUNKY SQL") }
end

and you also want to have #active? attribute in model instance, maybe for styling.

You could of course re-implement "LOTS OF LOGS OF FUNKY SQL" in Ruby, but it's very error prone for complex logic.

Instead you can add a "virtual" attribute:

scope :with_active_attribute, ->{
    subquery = active.select('tasks.id, true AS active').to_sql
    joins("LEFT JOIN (#{subquery}) AS tasks_active ON tasks_active.id = tasks.id").select('tasks.*, tasks_active.active AS active')
}

Now all Task instances loaded with withactiveattribute will have an extra 'active' attribute available:

Task.with_active_attribute.first.active? # true/false

"I don't always push logic into database, but when I do, I reuse it in the models."