Skip to content

Instantly share code, notes, and snippets.

@jrunning
Created March 12, 2014 16:45
Show Gist options
  • Save jrunning/9511047 to your computer and use it in GitHub Desktop.
Save jrunning/9511047 to your computer and use it in GitHub Desktop.
class College < ActiveRecord::Base
scope :ranked_at_least, ->(rank_low=nil) {
# If no value is given just return self without adding any conditions
if rank.nil? then self
else where("us_news_ranking <= ?", rank_low)
end
}
scope :with_sat_composite {
# Using an array for select() instead of a string means we can can chain
# selects and fields won't be duplicated
select([
"*",
"(colleges.sat_math_25 + colleges.sat_math_75 + "\
"colleges.sat_reading_25 + colleges.sat_reading_75) / 2 "\
"AS sat_composite"
])
}
scope :with_sat_composite_at_least, ->(sat_low=nil) {
if sat_low.nil? then self
else
# Use the `with_sat_composite` scope above to use the `sat_composite`
# field in our query
with_sat_composite.where("sat_composite >= ?", sat_low)
end
}
scope :with_sat_composite_at_most, ->(sat_high=nil) {
if sat_high.nil? then self
else with_sat_composite.where("sat_composite <= ?", sat_high)
end
}
scope :with_act_composite {
select([
"*",
"(colleges.act_composite_25 + colleges.act_composite_75) / 2 "\
"AS act_composite"
])
}
scope :with_act_composite_at_least, ->(act_low=nil) {
if act_low.nil? then self
else with_act_composite.where("act_composite >= ?", act_low)
end
}
scope :with_act_composite_at_most, ->(act_high=nil) {
if act_high.nil? then self
else with_act_composite.where("act_composite <= ?", act_high)
end
}
scope :with_tuition_for_state, ->(state_name=nil) {
# If no state is given, default to `out_of_state_tuition`
if state_name.nil?
"out_of_state_tuition AS tuition_for_state"
else
# Make sure we sanitize any value given by the user
tuition_for_state_sql = <<-ENDSQL
CASE WHEN colleges.state = #{ ActiveRecord::Base.sanitize state_name }
THEN in_state_tuition
ELSE out_of_state_tuition
END AS tuition_for_state
ENDSQL
select([ "*", tuition_for_state_sql ])
end
}
scope :with_total_cost_for_state, ->(state_name=nil) {
# Use the `with_tuition_for_state` scope from above to use the
# `tuition_for_state` field in our query
with_tuition_for_state(state_name)
# Calculate total cost and put it in a field named `total_cost_for_state`
.select([ "*", "tuition_for_state + room_and_board AS total_cost_for_state" ])
}
scope :with_total_cost_for_state_at_least, ->(state_name=nil, cost_low=nil) {
if cost_low.nil? then self
else
with_total_cost_for_state(state_name)
.where("total_cost_for_state >= ?", cost_low)
end
}
scope :with_total_cost_for_state_at_least, ->(state_name=nil, cost_high=nil) {
if cost_high.nil? then self
else
with_total_cost_for_state(state_name)
.where("total_cost_for_state <= ?", cost_high)
end
}
# Use an options hash so you don't have to remember what order you have to
# put the arguments in
def self.get_college(opts)
self.where( { category: opts[:type] } if opts[:type].present? )
# Since all of our scopes are set up to handle nil (and falsy) values we
# don't have to do any `if`s here and we can just chain the scopes one
# after the other
.ranked_at_least( opts[:rank_low] )
.with_sat_composite_at_least( opts[:sat_low] )
.with_sat_composite_at_most( opts[:sat_high] )
.with_act_composite_at_least( opts[:act_low] )
.with_act_composite_at_most( opts[:act_high] )
.with_total_cost_for_state_at_least( opts[:in_state], opts[:cost_low] )
.with_total_cost_for_state_at_most( opts[:in_state], opts[:cost_high] )
end
end
# Usage:
# With the options hash it's a lot more readable here, too
College.get_college( type: "national",
rank_low: 10,
sat_low: 1300,
in_state: "New York",
cost_high: 60_000 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment