4

I'm having trouble seeding my database using seed.rb, specifically where table relationships are concerned.

Here's a sample of the code:

# seed.rb
user = User.find_or_create_by_login(  
  :login => "myname",  
  :email => "myname@gmail.com",  
  :user_type => "Admin",  
  :password => "admin",  
  :password_confirmation => "admin")

project = Project.find_or_create_by_user_id(
  :user_id => user.id,
  :name => "Test Project")

When project is created (along with other unrelated parameters I've left out from above), user_id is empty. How can I get this to work?


This is the strangest behavior I've seen in something so simple. In my seed file, I have about eight tables being created and some are nested 3-4 levels deep (i.e. user has_many projects; projects has_many tasks, etc.).

When I call user user as above and reference user.id multiple times after that, it only works once! I tried adding [user.reload] before each new record is created but to no avail. I don't imagine this will make sense to anyone, but are there any possibilities here? Thanks all.

sscirrus
  • 55,407
  • 41
  • 135
  • 228

5 Answers5

5

I figured out what the problem was. The fields that weren't populating were not listed explicitly in attr_accessible in their respective models. The fields listed were being saved correctly.

Thank you very much for your help everyone.

sscirrus
  • 55,407
  • 41
  • 135
  • 228
3

The code is fine and is the correct syntax for find_or_create. As others have said the most likely problem is that the user is invalid. Trying to call user.reload would make it blow up if the user is invalid and so will kind of make the problem more apparent, but the error you'll get from it will be useless (it'll moan about not being able to find a user without an id).

Unfortunately find_or_create doesn't work as a bang method to raise exceptions if it's invalid, so the best thing to do is probably raising an error and outputting the error after attempting to create the user:

user = User.find_or_create_by_login(:login => "myname")
raise "User is invalid: #{user.errors.full_messages}" unless user.valid?
idlefingers
  • 31,659
  • 5
  • 82
  • 68
  • Out of curiosity, did you guys find the find_or_create documentation somewhere? And, of course, Happy New Year! – Heikki Dec 31 '10 at 16:17
  • Rails Guides don't mention the hash syntax but "Dynamic attribute-based finders": here do http://apidock.com/rails/v3.0.0/ActiveRecord/Base – Heikki Dec 31 '10 at 23:29
  • Yeah, the docs in AR::Base are all it has. If you're interested in digging deeper, it's part of the `method_missing` stuff AR does to give the magic methods (in both base.rb and association_collection.rb depending on what you call it on), then it uses the [DynamicFinderMatch](http://api.rubyonrails.org/classes/ActiveRecord/DynamicFinderMatch.html) class to work out what type of magic method you're trying to use. Happy new year! – idlefingers Jan 01 '11 at 20:52
  • +1 solved my issue by giving me debug output to track things down! – Stephen Sprinkle Jun 28 '12 at 22:32
0

User created with success? if so..try user.reload if not. that is probably the error

0

Are you sure your user is saved? I think the right syntax for find_or_create_by_XX is Blog.find_or_create_by_title("Some Blog"). If you need to pass more data you need to use find_or_initialize first and set other data after that separately.

Loosely related thread: Rails find_or_create by more than one attribute?

--edit

Passing data as hash to find_or_create_by_XX seems to work too. Docs are under "Dynamic attribute-based finders" here http://apidock.com/rails/v3.0.0/ActiveRecord/Base

Community
  • 1
  • 1
Heikki
  • 15,329
  • 2
  • 54
  • 49
  • Thanks Heikki - the code I show in my question enables one to find or create a record by a certain set of parameters, and it inserts more values should it find them. find_or_create is very powerful in certain circumstances. – sscirrus Dec 31 '10 at 15:32
0

try this use User.find_or_create instead of User.find_or_create_by_login. It seems like your user object is not saved. Or before you assign user.id do user.reload

user = User.find_or_create(  
  :login => "myname",  
  :email => "myname@gmail.com",  
  :user_type => "Admin",  
  :password => "admin",  
  :password_confirmation => "admin")

[user.reload]

project = Project.find_or_create_by_user_id(  :user_id => user.id,
  :name => "Test Project")
Nishant
  • 2,975
  • 23
  • 38
Ross
  • 1,562
  • 1
  • 15
  • 26
  • Does plain `User.find_or_create` really work? How does it decide if that user exists or not? – Heikki Dec 31 '10 at 13:52
  • thanks for clarifying the user.reload point that Yise mentioned. I'm also confused about what criteria it would use to perform that find. – sscirrus Dec 31 '10 at 14:22
  • At least Rails 3 says `NoMethodError: undefined method `find_or_create'`. – Heikki Dec 31 '10 at 14:42