0

I have an application with some existing categories and want to add more categories to it. As there are quote a few additional categories I thought I'd add this to a seed file.

I don't want to overwrite any existing categories so I'm using the find_or_create method to add a :name and :category_parent_id based on this question.

Rails find_or_create by more than one attribute?

So I added the following to my seed file

categories = Category.find_or_create_by_name_and_category_parent_id(
  {name: "TV", category_parent_id: 2},
  {name: "Oven", category_parent_id: 2},
  {name: "Fridge", category_parent_id: 2},
  {name: "Microwave", category_parent_id: 2},
  {name: "Toaster", category_parent_id: 2}
)

The output I get if I run this in the console when no matching entries in the categories table is as follows

Category Load (0.5ms)  SELECT "categories".* FROM "categories" WHERE "categories"."name" = 'Microwave' AND "categories"."category_parent_id" = 2 LIMIT 1
   (0.3ms)  BEGIN
  Category Exists (0.6ms)  SELECT 1 AS one FROM "categories" WHERE "categories"."name" = 'Microwave' LIMIT 1
  SQL (18.8ms)  INSERT INTO "categories" ("category_parent_id", "category_type", "created_at", "name", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["category_parent_id", 2], ["category_type", nil], ["created_at", Fri, 15 Mar 2013 14:41:53 EST +11:00], ["name", "Microwave"], ["updated_at", Fri, 15 Mar 2013 14:41:53 EST +11:00]]
   (0.8ms)  COMMIT
 => #<Category id: 31, name: "Microwave", created_at: "2013-03-15 03:41:53", updated_at: "2013-03-15 03:41:53", category_type: nil, category_parent_id: 2>

So this only added 1 entry from the seed file. If none of these exist why aren't they all being entered?

Thanks for any help. :)


ANSWERED THANKS TO JIM AND JOHN

Thanks to Jim and John I was able to change my code to work with the following solution.

category_options = [
  {name: "TV", category_parent_id: 2},
  {name: "Oven", category_parent_id: 2},
  {name: "Fridge", category_parent_id: 2},
  {name: "Microwave", category_parent_id: 2},
  {name: "Toaster", category_parent_id: 2}
]

categories = category_options.each do |c|
Category.find_or_create_by_name_and_category_parent_id(c)
end
Community
  • 1
  • 1
Robert B
  • 2,863
  • 4
  • 31
  • 40

1 Answers1

1

You can't create multiple records with find_or_create_by_*. It will only create a single record. What you're seeing is kind of odd, but I suspect it has to do with nondeterministic hash ordering and some lucky parameter interpretation.

Check out activerecord-import for inserting multiple records at once. It's not going to be as easy as find-or-create-by; you'll have to do a separate find and figure out what to create, ideally in a transaction or something, but it will perform reasonably well.

Jim Stewart
  • 16,964
  • 5
  • 69
  • 89
  • Thanks for the response which gave me the idea on how to solve this. :) While I didn't use activerecord-import I did find a pretty easy work around. – Robert B Mar 15 '13 at 04:19