Rake db:fixtures:load - can't set fixture_class_name. #9516

Closed
jacobstr opened this Issue Mar 2, 2013 · 10 comments

Projects

None yet

8 participants

@jacobstr
Contributor
jacobstr commented Mar 2, 2013

I have a many to many relation using a through table:

class User < ActiveRecord::Base
  has_many :badges, :through => :users_badges 
end

class UsersBadges < ActiveRecord::Base
  belongs_to :user
  belongs_to :badge
  belongs_to :badgesource, :polymorphic => true
end

class Badge < ActiveRecord::Base
  attr_accessible :points, :description
  has_many :users, :through => :users_badges
end

And a fixtures file named users_badges.yaml inside of test/fixtures.

The first issue was really that it was recognizing the class name for my UsersBadges model as UsersBadge ( which I'm not sure is correct - I couldn't find documentation on this).

So - the workaround was to add set_fixture_class before the fixtures are loaded inside of test_helper.rb

Unfortunately, this only works in the test context. It's nice to interact with the fixtures in the console but running rake:db:fixtures:load does the same naming conversion translation.

When it gets the class name wrong, it doesn't correctly grok the fixture file. My fixtures are related using labels. The SQL insert statement isn't adjusted to use ids and I get:

table users_badges has no column named user:

INSERT INTO "users_badges" ("user", "badge", "badgesource") VALUES ('user1', 'mood_badge', 'rocking_out (Generic)').

The relevant code is around lib/active_record/fixtures.rb:492

@schneems
Member
schneems commented Mar 3, 2013

The convention is to use singular model names, other wise when you're dealing with multiple UsersBadges, you would call them UsersBadges-s which wouldn't make much sense. Rails expects it to be UserBadge or UsersBadge (though the first makes more sense).

If you're not following this convention, you'll need to manually specify your table name in your has_many lines. Try that and see if it fixes your issue.

You will also need to check that this behavior is the same in 4.0.0. The line you referenced is an end in master.

@senny
Member
senny commented Mar 17, 2013

The model name should always be singular. Rails will pluralize it in many places and expects the class name to be singular.

@senny
Member
senny commented Apr 9, 2013

I'm closing this issue as it has been over a month since we heard from you. Please feel free to report back if this issue still persists and the advice from @schneems did not fix the problem.

Thanks for reporting 💛

@senny senny closed this Apr 9, 2013
@azul
Contributor
azul commented Sep 6, 2014

@senny, I've run into a similar issue. Maybe it's time to reopen this:

  • I'm using acts_as_taggable_on which has ActsAsTaggableOn::Tag and ActsAsTaggableOn::Tagging classes.
  • their fixtures live in tag.yml and tagging.yml.
  • in my tests i use set_fixture_class and everything is fine.

I run into errors when trying to load the fixtures into the database with rake db:fixtures:load though.
This is due to the fact that the rake task sends no third param to create_fixtures
while load_fixtures hands over the class lookup hash.

I was thinking about providing a patch. But I could not figure out any good place to store the class names. Including ActiveRecord::TestFixtures felt like a bit too much and it would also still require additional calls to set_fixture_class. Loading the test_helper and using the TestCase class feels wrong. So maybe these settings should go somewhere more generic and be set in an initializer or config?

@senny
Member
senny commented Sep 8, 2014

@jacobstr thanks for reporting back. I'll reopen.

@senny senny reopened this Sep 8, 2014
@rails-bot

This issue has been automatically marked as stale because it has not been commented on for at least
three months.

The resources of the Rails team are limited, and so we are asking for your help.

If you can still reproduce this error on the 4-1-stable, 4-0-stable branches or on master,
please reply with all of the information you have about it in order to keep the issue open.

Thank you for all your contributions.

@rails-bot rails-bot added the stale label Jan 2, 2015
@rafaelfranca rafaelfranca added pinned and removed stale labels Mar 20, 2015
@repinel
Contributor
repinel commented Jun 12, 2015

Why trying to duplicate the issue using master, I didn't have any SQL problem. However, the fixture were not properly loaded into the database.

My sample app has the following models:

class Post < ActiveRecord::Base
  self.table_name = 'records'
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

And schema.rb:

  create_table "comments", force: :cascade do |t|
    t.string   "content"
    t.integer  "post_id"
  end

  create_table "records", force: :cascade do |t|
    t.string "title"
  end

records.yml:

one:
  title: foo

comments.yml

great:
  content: 'great'
  post: one

You may check by the app tests that the fixtures load fine for the tests having set_fixture_class records: Post in the test_helper.rb.

@senny What's your opinion on having something like a mapping.rb file on fixtures directory that would holder the set_fixture_class statements make it easier to share that with the db:fixtures:load? One other option could be having the class name defined in the fixture itself with something like CLASS_NAME and being ignored just like is done for DEFAULTS.

@senny
Member
senny commented Jun 15, 2015

Backtracking in the git history, it looks like ada11d6 was the origin of set_fixture_class. I still feel like this configuration is directly related to the fixture and not the TestCase (the way it's currently implemented).

If that's the case (maybe @jeremy can elaborate more about the origin) I think we could make the configuration accessible directly in the fixture file itself. Something along the lines of:

<% set_fixture_class "Book" %>

one:
  title: "Odyssey"

two:
  title: "Ulysses"
@trak3r
Contributor
trak3r commented Aug 21, 2015

I'm getting bit by this now as well.

I agree with @senny sentiment, "feel like this configuration is directly related to the fixture and not the TestCase" and also his suggestion for the declaration in the fixture file.

@senny senny closed this in #20574 Sep 30, 2015
@senny
Member
senny commented Sep 30, 2015

with #20574 merged Rails 5 will allow you to configure the fixture class directly in the YAML file:

test/fixtures/accounts.yml

_fixture:
  model_class: User
david:
  name: David
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment