Ruby on Rails Thursday, January 12, 2012

On Thu, Jan 12, 2012 at 5:02 PM, Mauro <mrsanna1@gmail.com> wrote:
Here are params:

{"utf8"=>"✓", "authenticity_token"=>"RpOtdQMIm6B45/e91h6ljXKpMCtRD//QJ+bP4knrcic=",
"manager"=>{"name"=>"q", "surname"=>"",
"fiscal_code"=>"1121111111111111", "city"=>"", "zip_code"=>"",
"address"=>"", "street_number"=>"", "tel"=>"", "email"=>""},
"commit"=>"Crea Amministratore", "action"=>"create",
"controller"=>"managers", "company_id"=>"6"}


Started POST "/companies/6/managers" for 0:0:0:0:0:0:0:1 at 2012-01-12
16:58:49 +0100
 Processing by ManagersController#create as JS
 Parameters: {"utf8"=>"✓",
"authenticity_token"=>"RpOtdQMIm6B45/e91h6ljXKpMCtRD//QJ+bP4knrcic=",
"manager"=>{"name"=>"q", "surname"=>"",
"fiscal_code"=>"1121111111111111", "city"=>"", "zip_code"=>"",
"address"=>"", "street_number"=>"", "tel"=>"", "email"=>""},
"commit"=>"Crea Amministratore", "company_id"=>"6"}

As you see i have company_id => but the association is not created, is
created only a new Manager but with no Company association.


You are correct (and I learned something). In this many_to_many association
a build and a later save on the newly build object, seems to NOT create
the intermediate association object in the database ... (this works as I would
expect in a straight has_many, but seemingly not in a has_many :through ...).
Using a 'create' resolves that problem, but that means you cannot delay the
saving to database to one consolidated save at the end, as I prefer to do.

Some code:

002:0> Company.create
  SQL (11.6ms)  INSERT INTO "companies" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", Thu, 12 Jan 2012 23:28:57 UTC +00:00], ["updated_at", Thu, 12 Jan 2012 23:28:57 UTC +00:00]]

004:0> @company = Company.find(1)
  Company Load (0.2ms)  SELECT "companies".* FROM "companies" WHERE "companies"."id" = ? LIMIT 1  [["id", 1]]
=> #<Company id: 1, created_at: "2012-01-12 23:28:57", updated_at: "2012-01-12 23:28:57">

006:0> @manager = @company.managers.build()
=> #<Manager id: nil, created_at: nil, updated_at: nil>

007:0> @manager.save!
  SQL (0.6ms)  INSERT INTO "managers" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", Thu, 12 Jan 2012 23:30:25 UTC +00:00], ["updated_at", Thu, 12 Jan 2012 23:30:25 UTC +00:00]]
=> true

## This does NOT save the intermediate management record :-(

008:0> @manager = @company.managers.create()
  SQL (0.5ms)  INSERT INTO "managers" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", Thu, 12 Jan 2012 23:30:42 UTC +00:00], ["updated_at", Thu, 12 Jan 2012 23:30:42 UTC +00:00]]
  SQL (0.8ms)  INSERT INTO "managements" ("company_id", "created_at", "manager_id", "role", "updated_at") VALUES (?, ?, ?, ?, ?)  [["company_id", 1], ["created_at", Thu, 12 Jan 2012 23:30:42 UTC +00:00], ["manager_id", 2], ["role", nil], ["updated_at", Thu, 12 Jan 2012 23:30:42 UTC +00:00]]
=> #<Manager id: 2, created_at: "2012-01-12 23:30:42", updated_at: "2012-01-12 23:30:42">

## but this does save the intermediate management record :-)

009:0> @manager.managements.first
  Management Load (0.3ms)  SELECT "managements".* FROM "managements" WHERE "managements"."manager_id" = 2 LIMIT 1
=> #<Management id: 1, company_id: 1, manager_id: 2, role: nil, created_at: "2012-01-12 23:30:42", updated_at: "2012-01-12 23:30:42">
010:0> @manager.managements.first.role = "test role"
  Management Load (0.3ms)  SELECT "managements".* FROM "managements" WHERE "managements"."manager_id" = 2 LIMIT 1
=> "test role"

## Huh, Y U Reload ? (this is a different problem)

011:0> @manager.managements.first.save!
  Management Load (0.3ms)  SELECT "managements".* FROM "managements" WHERE "managements"."manager_id" = 2 LIMIT 1
=> true

## Huh, Y U Reload again ... and now save a pristine management record without my role assigned ?
## I could not reproduce this behavior ... never seen this before.

013:0> management = @manager.managements.first
  Management Load (0.3ms)  SELECT "managements".* FROM "managements" WHERE "managements"."manager_id" = 2 LIMIT 1
=> #<Management id: 1, company_id: 1, manager_id: 2, role: nil, created_at: "2012-01-12 23:30:42", updated_at: "2012-01-12 23:30:42">
014:0> management.role = "test role"
=> "test role"
015:0> management.save!
   (0.4ms)  UPDATE "managements" SET "role" = 'test role', "updated_at" = '2012-01-12 23:32:24.704538' WHERE "managements"."id" = 1
=> true

# forcing management to be the same record

017:0> @manager.managements.first
  Management Load (0.3ms)  SELECT "managements".* FROM "managements" WHERE "managements"."manager_id" = 2 LIMIT 1
=> #<Management id: 1, company_id: 1, manager_id: 2, role: "test role", created_at: "2012-01-12 23:30:42", updated_at: "2012-01-12 23:32:24">
018:0> @manager.managements.first.role
  Management Load (0.3ms)  SELECT "managements".* FROM "managements" WHERE "managements"."manager_id" = 2 LIMIT 1
=> "test role"

And now, reading it back from the database yields the role.

Please not that the use of "first" here is dangerous, unless you make sure there is never
a double association record between the same combination of Company and Manager.

Another problem, I do not see the "role" value anywhere in your params, so probably also
the form needs fixing somewhere ?

HTH,

Peter

--
Peter Vandenabeele
http://twitter.com/peter_v

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

No comments:

Post a Comment