Kurt Mueller
Kurt Mueller

Reputation: 3224

has_one :through association returns nil

I have a has_one through association that returns nil. Basically, I have a Review model that belongs to an Enrollment model, which belongs to a Section model. The Section model belongs to a Cluster.

I'm specifying that a Review has_one :section, through: :enrollment - this works. However, Review has_one :cluster, through :section does not work. See below for how I have my models defined:

The Review model:

class Review < ActiveRecord::Base
  belongs_to :reviewer,
    class_name: 'Enrollment'

  has_one :section,
    through: :reviewer,
    source: :section

  has_one :cluster,
    through: :section
end

The Enrollment model:

class Enrollment < ActiveRecord::Base
  belongs_to :section,
    inverse_of: :enrollments

  has_one :cluster,
    through: :section

  has_many :reviews,
    foreign_key: :reviewer_id,
    inverse_of: :reviewer
end

The Section model:

class Section < Active::Record
  belongs_to :cluster,
    inverse_of: :sections

  has_many :enrollments,
    inverse_of: :section
end

Finally, the Cluster model:

class Cluster < ActiveRecord::Base
  has_many :sections,
    inverse_of: :cluster
end

In my rails console:

[30] pry(main)> r = Review.new(reviewer: Enrollment.all.sample)
  Enrollment Load (3.5ms)  SELECT "enrollments".* FROM "enrollments" => #<Review id: nil, submission_id: nil, created_at: nil, updated_at: nil, expires_at: nil, reviewer_id: 94, completed_at: nil, submitted: false>
[31] pry(main)> r.section
  Section Load (0.5ms)  SELECT  "sections".* FROM "sections" INNER JOIN "enrollments" ON "sections"."id" = "enrollments"."section_id" WHERE "enrollments"."id" = $1  ORDER BY sections.class_number ASC LIMIT 1  [["id", 94]]
=> #<CampusSection id: 3, created_at: "2014-08-30 19:17:47", updated_at: "2014-08-30 19:17:47", cluster_id: 1, class_number: 157593622, type: "CampusSection", carmen_id: "218401898">
[32] pry(main)> r.section.cluster
  Cluster Load (0.2ms)  SELECT  "clusters".* FROM "clusters"  WHERE "clusters"."id" = $1 LIMIT 1  [["id", 1]]
=> #<Cluster id: 1, created_at: "2014-08-30 19:17:47", updated_at: "2014-08-30 19:17:47", name: "Schuppe, Lueilwitz and Keeling 106", consent_agreement_id: 1>
[33] pry(main)> r.cluster
=> nil

Any help is appreciated. Thanks guys.

Post updated: Relevant parts of my schema:

ActiveRecord::Schema.define(version: 20140829191322) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "clusters", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "name"
    t.integer  "consent_agreement_id"
  end

  create_table "enrollments", force: true do |t|
    t.integer  "enrollee_id",                    null: false
    t.string   "enrollee_type",                  null: false
    t.integer  "section_id",                     null: false
    t.datetime "created_at"
    t.datetime "updated_at"
    t.datetime "disenrolled_at"
    t.boolean  "disenrolled",    default: false
    t.boolean  "consent",        default: false
    t.datetime "consented_at"
  end

  add_index "enrollments", ["disenrolled"], name: "index_enrollments_on_disenrolled", using: :btree
  add_index "enrollments", ["disenrolled_at"], name: "index_enrollments_on_disenrolled_at", using: :btree
  add_index "enrollments", ["enrollee_id", "enrollee_type", "section_id"], name: "index_enrollments_on_eid_and_etype_and_sid", unique: true, using: :btree

  create_table "reviews", force: true do |t|
    t.integer  "submission_id",                 null: false
    t.datetime "created_at"
    t.datetime "updated_at"
    t.datetime "expires_at",                    null: false
    t.integer  "reviewer_id",                   null: false
    t.datetime "completed_at"
    t.boolean  "submitted",     default: false, null: false
  end

  add_index "reviews", ["reviewer_id"], name: "index_reviews_on_reviewer_id", using: :btree
  add_index "reviews", ["submission_id", "reviewer_id"], name: "index_reviews_on_submission_id_and_reviewer_id", unique: true, using: :btree
  add_index "reviews", ["submission_id"], name: "index_reviews_on_submission_id", using: :btree

  create_table "sections", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "cluster_id",   null: false
    t.integer  "class_number", null: false
    t.string   "type",         null: false
    t.string   "carmen_id"
  end

  add_index "sections", ["carmen_id"], name: "index_sections_on_carmen_id", using: :btree
  add_index "sections", ["class_number"], name: "index_sections_on_class_number", using: :btree
end

Upvotes: 1

Views: 737

Answers (1)

Kaleidoscope
Kaleidoscope

Reputation: 3627

I guess the review needs to be persisted before you can get the corresponding cluster back directly, not sure why...

Upvotes: 1

Related Questions