Wednesday, September 16, 2009

Alternative Seeds, Seeds for Replacements

‹prev | My Chain | next›

First up tonight, a wonderful feeling:
cstrom@jaynestown:~/repos/eee-code$ cucumber features
...
37 scenarios (1 pending, 36 passed)
334 steps (1 pending, 333 passed)
0m40.713s
cstrom@jaynestown:~/repos/eee-code$ rake
(in /home/cstrom/repos/eee-code)

==
Sinatra app spec
..............................................

Finished in 1.558958 seconds

46 examples, 0 failures

==
Helper specs
.......................................................................................

Finished in 0.120922 seconds

87 examples, 0 failures

==
View specs
......................................................................................................

Finished in 1.203112 seconds

102 examples, 0 failures
36 passing Cucumber scenarios with 333 passing steps in them. 235 passing RSpec examples. That's a happy place.

Before deploying my latest features (hiding recipes that have been updated and alternate preparations for recipes), I need to prepare seed data for the new CouchDB database from the legacy Rails application.

The alternate preparations were called "Recipe Groups" in the legacy Rails application:
class RecipeGroup < ActiveRecord::Base
has_many :recipes
end
When last I made seed data, I populated the CouchDB database via Restclient calls from the Rails ./script/console. To get seed data, I then used the couch_docs gem to dump the data to the file system.

This time, I skip the middleman and dump the JSON directly to the file system from ./script/console:
cstrom@jaynestown:~/repos/eee.old$ ./script/console
>> RecipeGroup.find(:all).each do |group|
alternate = { :type => "Alternative",
:name => group.name,
:recipes => group.recipes.map{|r| r.uri.gsub(/\//, '-')} }
file = File.new("/tmp/#{group.name}.json", "w+")
file.write(alternate.to_json)
file.close
end
The recipe updates are a little trickier. In the CouchDB version of the application (and the original XML based version of the application), the list of updates to a particular recipe are stored in a separate update document. In the legacy Rails application, the updates were stored as a linked list:
class RecipeUpdate < ActiveRecord::Base
belongs_to :successor, :class_name => "Recipe", :foreign_key => :successor_id
belongs_to :predecessor, :class_name => "Recipe", :foreign_key => :predecessor_id
end
To obtain the list of updates, first I need the most recent version of the recipe, which I can find by detecting all recipe updates with a "successor" that itself has no successor (update):
RecipeUpdate.find(:all).
reject { |update| update.successor.has_replacement? }
With the most recent version of the recipe in hand, I need to recursively work my way back through the list of previous recipes. I can make use of the Recipe#replacement_for method from the legacy Rails app for that:
>> def update_list(recipe, list=[])
if recipe.is_replacement?
update_list(recipe.replacement_for,
list + [{:id => recipe.uri.gsub(/\//, '-')}])
else
list + [{:id => recipe.uri.gsub(/\//, '-')}]
end
end
Putting the two together, I get the list of updates:
>> RecipeUpdate.find(:all).
reject { |update| update.successor.has_replacement? }.
map {|update| update_list(update.successor)}
...
=> [[{:id=>"2002-12-31-crabs"}, {:id=>"2001-12-31-crabs"}],
[{:id=>"2003-05-26-gravy"}, {:id=>"2002-02-10-biscuits_gravy"}],
[{:id=>"2003-03-30-artichoke"}, {:id=>"2001-10-29-index"}],
[{:id=>"2003-08-17-potatoes"}, {:id=>"2001-09-02-potatoes"}],
[{:id=>"2003-12-24-seafood"}, {:id=>"2001-12-27-seafood_salad"}],
[{:id=>"2003-12-20-soup"}, {:id=>"2002-01-15-gingered_lentil_soup"}],
[{:id=>"2004-05-08-salad"}, {:id=>"2002-01-30-sherry_vinaigrette"}],
[{:id=>"2003-11-25-caesar_salad"}, {:id=>"2001-10-30-caesar_salad"}],
[{:id=>"2003-09-22-soup"}, {:id=>"2002-10-08-soup"}],
[{:id=>"2005-05-29-crabcake"}, {:id=>"2003-04-29-crabcake"}],
[{:id=>"2003-05-26-biscuits"}, {:id=>"2001-09-22-index"}],
[{:id=>"2002-01-29-mashed_potatoes"}, {:id=>"2001-11-06-mashed_potatoes"}],
[{:id=>"2002-05-09-meatballs"}, {:id=>"2002-01-20-meatballs"}],
[{:id=>"2005-04-11-eggplant"}, {:id=>"2002-11-02-eggplant"}],
[{:id=>"2003-10-08-fries"}, {:id=>"2002-05-04-potatoes"}],
[{:id=>"2002-01-19-beef_tenderloin"}, {:id=>"2001-12-10-beef_tenderloin"}],
[{:id=>"2003-02-05-pizza_bread"}, {:id=>"2001-10-30-index"}],
[{:id=>"2003-02-05-balsamic_vinaigrette"}, {:id=>"2002-01-28-balsamic_vinaigrette"}],
[{:id=>"2002-03-28-pizza_dough"}, {:id=>"2002-01-28-pizza_crust"}, {:id=>"2001-12-30-pizza"}],
[{:id=>"2005-06-15-fish"}, {:id=>"2001-11-26-tilapia"}]]
Adding the same to_json here will also dump the JSON seed data.

I will call it a day at this point and pick up tomorrow with actually loading the data into my CouchDB server—and deploying the data and latest features to the soon to be not-beta site.

No comments:

Post a Comment