Please see http://dev.rubyonrails.org/tickets/6424 for further code on fixtures and foreign keys.
You might also be interested in the ar_fixtures plugin from topfunky to dump fixtures from dev to yaml. In most cases I'm using mocks and stubbing rather than canned data. Its much easier IMO to create a bunch of objects as you need them. That being said, fixtures are far from a "solved problem" and I look forward to your plugin. ------- Courtenay On Jul 22, 2007, at 5:39 AM, "Chris Hoffman" <[EMAIL PROTECTED]> wrote: > Have you tried just using fixture scenarios? Did it work? > > On 5/21/07, Carl Lerche <[EMAIL PROTECTED]> wrote: >> Sorry about the very long email, but this is a hairy topic that's >> been >> annoying me for some time and I decided to try to do something about. >> Also, if you got this twice, I apologize too, but it didn't seem to >> have successfully gone out the first time. >> >> Background: >> ---------- >> >> I've been dealing with Rails for about a year and a half now. I've >> been using Rails' built in testing framework, and it's fine... >> until I >> really have to start dealing with the fixtures. I am currently >> working >> on an application that really focuses on selecting data using complex >> logic. The only way to test the application in a meaningful way is by >> using a large number of fixtures. This has become a real nightmare to >> manage and I almost am spending more time keeping the fixtures up to >> date than I am coding or testing. So, I took a moment, stepped back, >> and took a good look at how I could I could improve fixtures to make >> my life a lot easier. >> >> I have gotten a quick and dirty prototype of my solution running, but >> before I really roll up my sleeves and start polishing it up, I >> thought I would try to get some suggestions from the community. >> >> Overview: >> --------- >> >> In my experience, the current fixture framework has three main >> problems: >> >> - There is no way to create different version of fixtures. What I >> mean >> by this is that you only can have one users.yml file even if your >> tests depend on different initial conditions. What this usually means >> is that you will just keep tagging on to the end of users.yml even >> though it is not the most efficient way to do it. >> - Managing relationships between tables is a really big pain. One >> must >> manually keep track of IDs. This can quickly become a major headache. >> - There is no clean way to quickly generate data. If I want 50 >> records that I could easily generate in a loop, I still gotta write >> them by hand (at least, I wasn't able to figure out how to add loops >> to my yaml files in a clean way). >> - There is a lot of repetition. No way to follow DRY. >> >> Solution: >> --------- >> >> + Versioned Fixtures >> >> First, to address the fixture "versions", I thought the easiest way >> to >> do this would be scenarios (I was inspired from fixture-scenarios). >> The way fixtures could be laid out is as follows: >> >> + specs >> |- fixtures >> |- global >> |- only_one_signed_up_user >> |- lots_of_posts_in_los_angeles >> |- ... >> >> All global fixtures (fixtures that should be loaded before every >> spec) >> go into global, then, for each different scenario, there is a >> directory created with the relevant fixtures in there. Then, in the >> specs, you could do the following >> >> ------------------------------- >> require File.dirname(__FILE__) + '/../spec_helper' >> >> describe User, :when => :only_one_signed_up_user do >> >> it "should be the only user" do >> User.count.should == 1 >> end >> end >> ------------------------------- >> >> The key part here would be the :when => :scenario_name option to the >> describe method. >> >> + Writing the fixtures >> >> Writing fixtures with YAML is quite ugly. I think a better way to do >> it would be using a DSL, but coming up with a good syntax is hard. >> This is where I am the most hesitant. I have two "options" and I was >> wondering if people could comment on them and give me some feedback >> and suggestions. >> >> - The first option is how I started out: http://pastie.caboo.se/63359 >> >> In this option, fixtures for multiple tables can be written in a >> single file. You would start out by using the _create_ method to tell >> the parser what table the fixtures are for and you could also specify >> :with, which would set default attributes for fixtures. >> >> You could also nest fixtures in order to easily scope them (see the >> last user fixture how I specified nested post fixtures). >> >> - The second option is what I currently prefer: http://pastie.caboo.se/63361 >> >> In this option, I keep the one table per file concept that is >> currently used. As such, we don't need to specify what table we want >> to use before hand. I make available a with_options method which lets >> you set default attributes for fixtures. It's also easy to create >> loops to automatically generate fixtures, as I show in the second >> half >> of the file. The f method is the actual method for creating a >> fixture. >> it takes a name as a string and a block in which the attributes of >> the >> fixtures are specified. However, the method_missing method is >> implemented to handle any missing methods and use that to create >> fixtures too as seen with fixture_name { ... } >> >> + Dealing with relationships >> >> I think what I hate the most about fixtures right now is having to >> deal with table relationships. Having to keep track of IDs myself is >> horrible. So, I thought that the easiest way to do this is making the >> table_name(:fixture_name) method available straight inside the >> fixtures. So, if I have a user model that has a location associated >> with it (let's say a zip code, longitude, and latitude), instead of >> having to copy / paste that data across fixtures, I can do the >> following: >> >> ------------------------------- >> local_guy { >> zip_id zips(:portland) >> longitude zips(:portland).longitude >> latitude zips(:portland).latitude >> } >> ------------------------------- >> >> This is much easier to deal with than the other way around. This also >> introduces dependencies between fixtures, I thought the easiest way >> to >> handle it would be adding a fixture_order configuration: >> >> ------------------------------- >> Spec::Runner.configure do |config| >> config.fixture_order = :zips, :categories, :users, :posts >> end >> ------------------------------- >> >> + What's not solved with this >> >> I haven't figured out a good way to handle counter_cache columns. >> Right now, this would still require you to manually count how many >> fixtures you have associated with a parent and add that to the >> counter_cache column. Any ideas of a better way to do this? >> >> Well, that's all I came up with. I'm going to keep hacking away at >> this and hopefully you all have some feedback to improve this >> concept. >> >> -- >> EPA Rating: 3000 Lines of Code / Gallon (of coffee) >> _______________________________________________ >> rspec-users mailing list >> rspec-users@rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > _______________________________________________ > rspec-users mailing list > rspec-users@rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users