I got the JSON dump of recipes in pretty good shape last night simply by mucking with the various options that
ActiveRecord
's to_json
method recognizes (:include
, :except
, and :methods
). That accounts for most of a recipe's infomation, but not the photos.So how to deal with photos? Continue to use a CouchDB-tailored attachment_fu (or switch to a CouchDB tailored paperclip)? Fortunately, the answer is a little more direct than that—CouchDB itself supports attachments.
My preference would be to use the nicer REST API that CouchDB provides for "Standalone Attachments" (see the CouchDB HTTP Document API, toward the bottom for more details). That is a recent addition, not available in the stock 0.8 that is packaged in Ubuntu's universe. Rather than shaving that yak, I will stick with "Inline" CouchDB attachments for now.
The thing about inline attachments in CouchDB is that they need to be Base64 encoded (and stripped of newline characters). So we need to grab the images from the file system (via attachment_fu that the old code uses), Base64 encode it, and put it into CouchDB. For CouchDB to recognize them, they need to be added in the record's
_attachments
key.To grab it from the file system:
jpeg = File.open(recipe.image.full_filename).readBase64 encoding (and removing newlines) is easy enough:
require 'base64'To get this into the JSON data structure (and thus into CouchDB), define an
Base64.encode64(jpeg).gsub(/\n/, '')
_attachements
method in the Recipe
class:class RecipeNext update the
def _attachments
{
self.image.filename =>
{
:data => Base64.encode64(File.open(self.image.full_filename).read).gsub(/\n/, ''),
:content_type => "image/jpeg"
}
}
end
end
to_json
method to include the _attachments
method in the :methods
option:json = recipe.to_json(Lastly, put this into the DB with a simple RestClient put:
:methods => [:tag_names, :_id, :_attachments],
:include => {
:preparations =>
{
:include =>
{
:ingredient => { :except => :id }
},
:except => [:ingredient_id, :recipe_id, :id]
},
:tools => { :except => [:id, :label] } },
:except => [:id, :label])
RestClient.put "http://localhost:5984/eee-meals/#{recipe._id}", json,Viewing the record in futon, we see that it does have a JPEG image attachment:
:content_type => 'application/json'
Clicking the attachment returns the original image:
At this point, we have a nice mechanism for transporting the data from the old relational DB into CouchDB. It needs to be expanded to run through all recipes (and maybe to add some error handling). Also, we still have to get this working for meal documents. The spike, and that is what this has been—a spike to understand how to transfer data from the legacy Rails application into CouchDB—is complete.
No comments:
Post a Comment