Skip to content

Instantly share code, notes, and snippets.

@JunichiIto
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JunichiIto/e27150de2700e92983bb to your computer and use it in GitHub Desktop.
Save JunichiIto/e27150de2700e92983bb to your computer and use it in GitHub Desktop.
Sample for self joins
class Event < ActiveRecord::Base
has_many :groups
# reference: http://guides.rubyonrails.org/association_basics.html#self-joins
has_many :next_events, class_name: "Event", foreign_key: "previous_event_id"
belongs_to :previous_event, class_name: "Event"
end
# schema.rb
create_table "events", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "previous_event_id"
t.integer "next_event_id"
end
# rails console
irb(main):029:0> Event.joins(:previous_event).where(previous_event: {name: 'prev'})
Event Load (0.3ms) SELECT "events".* FROM "events" INNER JOIN "events" "previous_events_events" ON "previous_events_events"."id" = "events"."previous_event_id" WHERE "previous_events_events"."name" = ? [["name", "prev"]]
=> #<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-15 21:09:01", previous_event_id: 2, next_event_id: nil>]>
irb(main):030:0> Event.joins(:previous_event).where(previous_event: {name: 'prevx'})
Event Load (0.1ms) SELECT "events".* FROM "events" INNER JOIN "events" "previous_events_events" ON "previous_events_events"."id" = "events"."previous_event_id" WHERE "previous_events_events"."name" = ? [["name", "prevx"]]
=> #<ActiveRecord::Relation []>
irb(main):031:0> Event.includes(:previous_event).references(:previous_event).where(previous_event: {name: 'prevx'})
SQL (0.3ms) SELECT "events"."id" AS t0_r0, "events"."name" AS t0_r1, "events"."created_at" AS t0_r2, "events"."updated_at" AS t0_r3, "events"."previous_event_id" AS t0_r4, "events"."next_event_id" AS t0_r5, "previous_events_events"."id" AS t1_r0, "previous_events_events"."name" AS t1_r1, "previous_events_events"."created_at" AS t1_r2, "previous_events_events"."updated_at" AS t1_r3, "previous_events_events"."previous_event_id" AS t1_r4, "previous_events_events"."next_event_id" AS t1_r5 FROM "events" LEFT OUTER JOIN "events" "previous_events_events" ON "previous_events_events"."id" = "events"."previous_event_id" WHERE "previous_events_events"."name" = ? [["name", "prevx"]]
=> #<ActiveRecord::Relation []>
irb(main):032:0> Event.includes(:previous_event).references(:previous_event).where(previous_event: {name: 'prev'})
SQL (0.1ms) SELECT "events"."id" AS t0_r0, "events"."name" AS t0_r1, "events"."created_at" AS t0_r2, "events"."updated_at" AS t0_r3, "events"."previous_event_id" AS t0_r4, "events"."next_event_id" AS t0_r5, "previous_events_events"."id" AS t1_r0, "previous_events_events"."name" AS t1_r1, "previous_events_events"."created_at" AS t1_r2, "previous_events_events"."updated_at" AS t1_r3, "previous_events_events"."previous_event_id" AS t1_r4, "previous_events_events"."next_event_id" AS t1_r5 FROM "events" LEFT OUTER JOIN "events" "previous_events_events" ON "previous_events_events"."id" = "events"."previous_event_id" WHERE "previous_events_events"."name" = ? [["name", "prev"]]
=> #<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-15 21:09:01", previous_event_id: 2, next_event_id: nil>]>
# with squeel
irb(main):034:0> Event.joins{previous_event.outer}.where{previous_event.name == 'prev'}
Event Load (2.0ms) SELECT "events".* FROM "events" LEFT OUTER JOIN "events" "previous_events_events" ON "previous_events_events"."id" = "events"."previous_event_id" WHERE "previous_events_events"."name" = 'prev'
=> #<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-15 21:09:01", previous_event_id: 2, next_event_id: nil>]>
irb(main):035:0> Event.joins{previous_event}.where{previous_event.name == 'prev'}
Event Load (0.3ms) SELECT "events".* FROM "events" INNER JOIN "events" "previous_events_events" ON "previous_events_events"."id" = "events"."previous_event_id" WHERE "previous_events_events"."name" = 'prev'
=> #<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-15 21:09:01", previous_event_id: 2, next_event_id: nil>]>
# ==============
class Event < ActiveRecord::Base
has_many :groups
has_many :next_events, class_name: "Event", foreign_key: "previous_event_id"
belongs_to :previous_event, class_name: "Event"
has_many :previous_events, class_name: "Event", foreign_key: "next_event_id"
belongs_to :next_event, class_name: "Event"
end
create_table "events", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "previous_event_id"
t.integer "next_event_id"
end
>> Event.joins(:previous_event, :next_event)
#<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-17 03:35:28", previous_event_id: 2, next_event_id: 6>]>
>> Event.joins(:previous_event, :next_event).to_sql
"SELECT \"events\".* FROM \"events\" INNER JOIN \"events\" \"previous_events_events\" ON \"previous_events_events\".\"id\" = \"events\".\"previous_event_id\" INNER JOIN \"events\" \"next_events_events\" ON \"next_events_events\".\"id\" = \"events\".\"next_event_id\""
>> Event.joins(:previous_event, :next_event).where(previous_event: {name: 'prev'}, next_event: {name: 'next'})
#<ActiveRecord::Relation []>
>> Event.joins(:previous_event, :next_event).where(previous_event: {name: 'prev'}, next_event: {name: 'next event'})
#<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-17 03:35:28", previous_event_id: 2, next_event_id: 6>]>
>> Event.joins(:previous_event, :next_event).where(previous_event: {name: 'prev'}, next_event: {name: 'next event'}).to_sql
"SELECT \"events\".* FROM \"events\" INNER JOIN \"events\" \"previous_events_events\" ON \"previous_events_events\".\"id\" = \"events\".\"previous_event_id\" INNER JOIN \"events\" \"next_events_events\" ON \"next_events_events\".\"id\" = \"events\".\"next_event_id\" WHERE \"previous_events_events\".\"name\" = 'prev' AND \"next_events_events\".\"name\" = 'next event'"
>> Event.includes(:previous_event, :next_event).references(:previous_event, :next_event).where(previous_event: {name: 'prev'}, next_event: {name: 'next event'}).to_sql
"SELECT \"events\".\"id\" AS t0_r0, \"events\".\"name\" AS t0_r1, \"events\".\"created_at\" AS t0_r2, \"events\".\"updated_at\" AS t0_r3, \"events\".\"previous_event_id\" AS t0_r4, \"events\".\"next_event_id\" AS t0_r5, \"previous_events_events\".\"id\" AS t1_r0, \"previous_events_events\".\"name\" AS t1_r1, \"previous_events_events\".\"created_at\" AS t1_r2, \"previous_events_events\".\"updated_at\" AS t1_r3, \"previous_events_events\".\"previous_event_id\" AS t1_r4, \"previous_events_events\".\"next_event_id\" AS t1_r5, \"next_events_events\".\"id\" AS t2_r0, \"next_events_events\".\"name\" AS t2_r1, \"next_events_events\".\"created_at\" AS t2_r2, \"next_events_events\".\"updated_at\" AS t2_r3, \"next_events_events\".\"previous_event_id\" AS t2_r4, \"next_events_events\".\"next_event_id\" AS t2_r5 FROM \"events\" LEFT OUTER JOIN \"events\" \"previous_events_events\" ON \"previous_events_events\".\"id\" = \"events\".\"previous_event_id\" LEFT OUTER JOIN \"events\" \"next_events_events\" ON \"next_events_events\".\"id\" = \"events\".\"next_event_id\" WHERE \"previous_events_events\".\"name\" = 'prev' AND \"next_events_events\".\"name\" = 'next event'"
>> Event.includes(:previous_event, :next_event).references(:previous_event, :next_event).where(previous_event: {name: 'prev'}, next_event: {name: 'next event'})
#<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-17 03:35:28", previous_event_id: 2, next_event_id: 6>]>
>> Event.joins(:previous_events, :next_events)
#<ActiveRecord::Relation []>
>> Event.joins(:previous_events, :next_events).to_sql
"SELECT \"events\".* FROM \"events\" INNER JOIN \"events\" \"previous_events_events\" ON \"previous_events_events\".\"next_event_id\" = \"events\".\"id\" INNER JOIN \"events\" \"next_events_events\" ON \"next_events_events\".\"previous_event_id\" = \"events\".\"id\""
>> Event.includes(:previous_events, :next_events).references(:previous_events, :next_events)
#<ActiveRecord::Relation [#<Event id: 1, name: "current", created_at: "2015-02-11 12:38:38", updated_at: "2015-02-17 03:35:28", previous_event_id: 2, next_event_id: 6>, #<Event id: 2, name: "prev", created_at: "2015-02-11 12:40:10", updated_at: "2015-02-15 21:08:48", previous_event_id: nil, next_event_id: nil>, #<Event id: 3, name: nil, created_at: "2015-02-11 12:40:29", updated_at: "2015-02-11 12:40:29", previous_event_id: nil, next_event_id: nil>, #<Event id: 4, name: "hoge event", created_at: "2015-02-15 21:03:11", updated_at: "2015-02-15 21:03:11", previous_event_id: nil, next_event_id: nil>, #<Event id: 5, name: "prev event", created_at: "2015-02-15 21:03:32", updated_at: "2015-02-15 21:03:32", previous_event_id: nil, next_event_id: nil>, #<Event id: 6, name: "next event", created_at: "2015-02-15 21:03:44", updated_at: "2015-02-15 21:03:44", previous_event_id: nil, next_event_id: nil>]>
>> Event.includes(:previous_events, :next_events).references(:previous_events, :next_events).to_sql
"SELECT \"events\".\"id\" AS t0_r0, \"events\".\"name\" AS t0_r1, \"events\".\"created_at\" AS t0_r2, \"events\".\"updated_at\" AS t0_r3, \"events\".\"previous_event_id\" AS t0_r4, \"events\".\"next_event_id\" AS t0_r5, \"previous_events_events\".\"id\" AS t1_r0, \"previous_events_events\".\"name\" AS t1_r1, \"previous_events_events\".\"created_at\" AS t1_r2, \"previous_events_events\".\"updated_at\" AS t1_r3, \"previous_events_events\".\"previous_event_id\" AS t1_r4, \"previous_events_events\".\"next_event_id\" AS t1_r5, \"next_events_events\".\"id\" AS t2_r0, \"next_events_events\".\"name\" AS t2_r1, \"next_events_events\".\"created_at\" AS t2_r2, \"next_events_events\".\"updated_at\" AS t2_r3, \"next_events_events\".\"previous_event_id\" AS t2_r4, \"next_events_events\".\"next_event_id\" AS t2_r5 FROM \"events\" LEFT OUTER JOIN \"events\" \"previous_events_events\" ON \"previous_events_events\".\"next_event_id\" = \"events\".\"id\" LEFT OUTER JOIN \"events\" \"next_events_events\" ON \"next_events_events\".\"previous_event_id\" = \"events\".\"id\""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment