Skip to content

Instantly share code, notes, and snippets.

@libbyschuknight
Last active November 23, 2018 03:28
Show Gist options
  • Save libbyschuknight/87091333b6633bd0b84f5b7acef1df37 to your computer and use it in GitHub Desktop.
Save libbyschuknight/87091333b6633bd0b84f5b7acef1df37 to your computer and use it in GitHub Desktop.
describe Person do
describe ".in_region" do
it "returns people in the named region" do
region = create(:region, name: "expected")
other_region = create(:region, name: "other")
in_region = create(:location, region: region)
in_other_region = create(:location, region: other_region)
create(:person, location: in_region, name: "in-expected-region-one")
create(:person, location: in_region, name: "in-expected-region-two")
create(:person, location: in_other_region, name: "in-other-region")
result = Person.in_region("expected")
expect(result.map(&:name)).
to match_array(%w(in-expected-region-one in-expected-region-two))
end
end
end
#==== SOLUTION ====#
class Person < ActiveRecord::Base
belongs_to :location
belongs_to :role
belongs_to :manager, class_name: "Person", foreign_key: :manager_id
has_many :employees, class_name: "Person", foreign_key: :manager_id
def self.in_region(region)
# all.select { |person| person.location.region.name == region }
joins(:location).merge(Location.in_region(region))
end
end
# sql
Person.joins(:location).merge(Location.in_region(region))
SELECT "people".*
FROM "people
INNER JOIN "locations"
ON "locations"."id" = "people"."location_id"
LEFT OUTER JOIN "regions"
ON "regions"."id" = "locations"."region_id"
WHERE "regions"."name" = 'expected'
```
```ruby
describe Person do
describe ".alphabetically_by_region_and_location" do
it "orders people by region name, then location name, then person name" do
region2 = create(:region, name: "region2")
region3 = create(:region, name: "region3")
region1 = create(:region, name: "region1")
location1 = create(:location, name: "location1", region: region2)
location4 = create(:location, name: "location4", region: region1)
location3 = create(:location, name: "location3", region: region1)
location5 = create(:location, name: "location5", region: region3)
location2 = create(:location, name: "location2", region: region1)
create(:person, name: "person1", location: location5)
create(:person, name: "person5", location: location2)
create(:person, name: "person4", location: location4)
create(:person, name: "person3", location: location1)
create(:person, name: "person2", location: location1)
create(:person, name: "person7", location: location1)
create(:person, name: "person6", location: location3)
result = Person.alphabetically_by_region_and_location
expect(result.map(&:name)).to eq(%w(
person5
person6
person4
person2
person3
person7
person1
))
end
end
end
#==== SOLUTION ====#
class Person < ActiveRecord::Base
belongs_to :location
belongs_to :role
# 1st iteration
def self.alphabetically_by_region_and_location
Person.all.sort_by do |person|
[person.location.region.name, person.location.name, person.name]
end
end
end
# 2nd iteration
# after looking here thought :(
# https://github.com/thoughtbot-upcase-exercises/advanced-activerecord-querying-belongs_to-associations/compare/featured-solution#toc
Person.joins(location: :region).order("regions.name, locations.name, name")
SELECT "people".* FROM "people"
INNER JOIN "locations" ON "locations"."id" = "people"."location_id"
INNER JOIN "regions" ON "regions"."id" = "locations"."region_id"
ORDER BY regions.name, locations.name, name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment