Search code examples
ruby-on-railsseeding

Seeding model is not working with validatating user in model


My seeds look like:

seeds.rb

seed_file = File.join(Rails.root, 'db', 'seed.yml')
config = YAML::load_file(seed_file)
Article.create(config["articles"])
User::HABTM_Articles.create(config["articles_users"])

seed.yml

articles:
  - status: 0
    title: First article
    body: Some awesome text

articles_users:
  - article_id: 1
    user_id: 1

I make rake db:drop && rake db:create && rake db:migrate.

Then run rake db:seed --trace and get output:

** Invoke db:seed (first_time)
** Execute db:seed
** Invoke db:abort_if_pending_migrations (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:abort_if_pending_migrations

My Article table is empty, but Article::HABTM_Users is seeded.

I discovered that problem is in Article model:

article.rb

class Article < ActiveRecord::Base
  has_and_belongs_to_many :users
  validates :title, presence: true, uniqueness: true
  validates :body, presence: true
  validates :users, presence: true #OK when remove this line
  enum status: [:publ, :priv]
end

When remove validates :users, presence: true seeding works fine. How to make seeding run with that user presence validation?


Solution

  • The issue is that, at the time you're creating the Article, it has no Users. I know your seed file lists the Users as the very next thing, but ActiveRecord isn't patient about validations! So what you need to do is create the ArticleUsers at the exact same time you create the Article, which you can do in a few ways:

    • Push the article_users definition up and into your articles definition:

      articles:
        - status: 0
          title: First article
          body: Some awesome text
          user_ids: [ 1 ]
      

      I did some testing, and this should actually work:

      irb(main):006:0> Thing.create(name: "thing1", user_ids: [ 1 ] ).users
        User Load (3.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]
        SQL (1.4ms)  INSERT INTO "things" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "thing1"], ["created_at", "2015-07-25 16:38:47.717614"], ["updated_at", "2015-07-25 16:38:47.717614"]]
        SQL (0.5ms)  INSERT INTO "things_users" ("user_id", "thing_id") VALUES ($1, $2) RETURNING "id"  [["user_id", 1], ["thing_id", 2]]
      => #<ActiveRecord::Associations::CollectionProxy [#<User id: 1, name: "Bob", age: nil, created_at: "2015-07-25 16:37:13", updated_at: "2015-07-25 16:37:13">]>
      
    • Use factories, which allow you to express a way to generate test objects more elegantly, a more robust fixture solution, or just turn your seeds file into a Ruby script that knows how to build the seeds properly.