This project is archived and is in readonly mode.

#3480 ✓invalid

has_one through associations not saved correctly

Reported by gerad | November 11th, 2009 @ 12:15 AM


Attributes created using has_one :through associations are lost upon serialization to the database.


class Club < ActiveRecord::Base
  has_one :membership
class Membership < ActiveRecord::Base
  belongs_to :person
  belongs_to :club
class Person < ActiveRecord::Base
  has_one :membership
  has_one :club, :through => :membership
require 'test_helper'

class PersonTest < ActiveSupport::TestCase
  test "person's club is saved" do
    p =
    c = = c
    assert_equal c,!; c.reload!; p.reload
    assert_equal c,
$ ruby -Itest test/unit/person_test.rb
Loaded suite test/unit/person_test
Finished in 0.057744 seconds.

  1) Failure:
test_person's_club_is_saved(PersonTest) [test/unit/person_test.rb:11]:
<#<Club id: 1, created_at: "2009-11-11 01:01:47", updated_at: "2009-11-11 01:01:47">> expected but was

1 tests, 2 assertions, 1 failures, 0 errors

Comments and changes to this ticket

  • gerad

    gerad November 11th, 2009 @ 01:03 AM

    Also happens on 2.3.4 version 7ba80252a5a6bd94c8445347caee663b12c1a526

  • Jigar Patel

    Jigar Patel July 24th, 2010 @ 12:58 PM

    Three cases -
    1. p =
    c = = c This line will insert a new row in memberships table with both person_id and club_id as nil. Both objects will be saved without any related membership. Hence your test case fails.

    1. p =
      c = = c

    This will create an entry in Membership table with club_id = "" and person_id as nil will save the object but without any related membership and hence without any related organization.

    1. p = p will be a Person with some id.
      c = c will be a Club with some id. = c This will create an entry in memberships table with person_id and club_id pointing to corresponding rows in persons and clubs tables. will save and you will be able to fetch club.
  • lakshmanan

    lakshmanan July 24th, 2010 @ 01:08 PM

    I ran your testcase statements in console and I test Membership after every statement. You are not saving anything

    In short -> you are playing in memory without saving anything. so literally you are playing with nils

    >> p =
    => #<Person id: nil, created_at: nil, updated_at: nil>
    >> Membership.last
    => nil
    >> c =
    => #<Club id: nil, created_at: nil, updated_at: nil>
    >> Membership.last
    => nil
    >> = c
    => #<Club id: nil, created_at: nil, updated_at: nil>
    >> Membership.last
    => nil
    => true
    >> Membership.last
    => nil
    >> c.reload
    => #<Club id: 2, created_at: "2010-07-24 11:57:24", updated_at: "2010-07-24 11:57:24">
    # after this statement - your test will pass
    => true
    >> Membership.last
    => #<Membership id: 2, club_id: nil, person_id: 2, created_at: "2010-07-24 11:57:43", updated_at: "2010-07-24 11:57:43">

    Hope it helps

  • Rohit Arondekar

    Rohit Arondekar September 27th, 2010 @ 02:52 PM

    • State changed from “new” to “invalid”
    • Importance changed from “” to “Low” and c are not the same. c is created when c is saved. While is created when p is saved.

  • csnk

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>