Created
November 12, 2018 16:16
-
-
Save coralieco/8a1bd3a6c35fd2948c51037e22c6ee22 to your computer and use it in GitHub Desktop.
Thoughtbot upcase: Querying belongs_to Associations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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