Skip to content

Instantly share code, notes, and snippets.

@coralieco
Created November 12, 2018 16:16
Show Gist options
  • Save coralieco/8a1bd3a6c35fd2948c51037e22c6ee22 to your computer and use it in GitHub Desktop.
Save coralieco/8a1bd3a6c35fd2948c51037e22c6ee22 to your computer and use it in GitHub Desktop.
Thoughtbot upcase: Querying belongs_to Associations
# frozen_string_literal: true
begin
require "bundler/inline"
rescue LoadError => e
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
raise e
end
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails", "5.2.0"
gem "sqlite3"
end
require "active_record"
require "logger"
require 'rails'
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :roles, force: true do |t|
t.string :position
t.boolean :billable
end
create_table :people, force: true do |t|
t.string :name
t.integer :role_id
end
end
class Person < ActiveRecord::Base
belongs_to :role
end
class Role < ActiveRecord::Base
has_many :people
end
role1 = Role.create(position: 'Developer Junior', billable: true)
role2 = Role.create(position: 'Developer Senior', billable: false)
person1 = Person.create(name: 'wait', role_id: role1.id)
person2 = Person.create(name: 'but', role_id: role1.id)
person3 = Person.create(name: 'why', role_id: role2.id)
puts "Person 1 is named: #{person1.name} and has role #{person1.role_id}"
puts "Person 2 is named: #{person2.name} and has role #{person2.role_id}"
puts "Person 3 is named: #{person3.name} and has role #{person3.role_id}"
puts ''
puts "----------------Performing Person.all"
puts Person.all
puts ''
puts "----------------Performing Person.all.select { |person| person.role.billable? }"
puts Person.all.select { |person| person.role.billable? }
puts ''
puts '----------------A better way would be to glue tables together so ActiveRecord performs a SQL join on its associations'
puts "----------------Performing Person.all.joins(:role)"
puts Person.all.joins(:role)
puts ''
puts '----------------We could now filter by billable or not'
puts "----------------Performing Person.all.joins(:role).where(roles: { billable: true })"
puts Person.all.joins(:role).where(roles: { billable: true })
puts ''
puts '----------------Now we can define a class method in Role to filter on billable'
class Role < ActiveRecord::Base
def self.billable
where(billable: true)
end
end
puts "----------------Performing Person.joins(:role).merge(Role.billable)"
puts Person.joins(:role).merge(Role.billable)
class Person < ActiveRecord::Base
def self.billable
joins(:role).merge(Role.billable)
end
end
puts ''
puts '----------------The best option is to create a class method in Person and call billable directly on Person'
puts "----------------Performing Person.billable"
puts Person.billable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment