###Setting up the project
- run "git clone http://github.com/madebydna/Vegtastic"
- if using rvm, then switch to ruby 1.9.2 and create new gemset called vegtastic ("rvm gemset create vegatstic")
- install bundler gem: "gem install bundler"
- run "bundle install" from project folder
- change content of "database.template.yml" and rename to "database.yml"
- run "rake db:create" and "rake db:migrate" to set up tables
- To run unit tests "rspec spec/models". (The controller tests are generated by the rails scaffold, so they won't run. I don't have much going on in that department anyways, since I only have 2 vanilla restful controllers at the moment.)
The following steps are only necessary if you want to run the site on a local server:
- To install the data for the lookup tables run "rake import_usda_data" (beware: the rake task takes about 10-15 minutes because of the size of the data set).
- Run "rake ts:index" to index the database with Thinking Sphinx
- "rails server" to start server on "http://localhost:3000/"
I am preparing a deploy to a VPS. This will be ready in about an hour. I'll send you an email when it's live with the url.
###About Vegtastic
Please refer to the README file for an introduction to the scope of the project and a general overview.
####Step By Step Site Creation With Particular Challenges
- original data source for foods and nutrients provided by the USDA was in MS Access format and contained a lot of irrelevant data
- creation of rails compatible data tables with appropriate associations to reflect the relationships in the original data source
- import of relevant data via CSV and rake
- setting up the user facing recipe and ingredients models (one-to-many relationship between recipe and ingredients)
- the intention was from the beginning to create the recipe along with its ingredients utilizing a nested form, which implies that the ingredients get validated and saved along with the recipe
- a nutritional profile of the recipe should be created at the time that the recipe gets saved or updated
- since on a live website, reading from the DB occurs far more often than writing, the nutritional profile should get persisted in a "cache" table called recipe_profiles
- in order for the recipe profile to get calculated, we need to profile the ingredients first
- ingredient profiles are also persisted in a ingredient_profiles table
- ingredients can only be profiled if their name and unit can be matched in the USDA provided tables
- if found, a particular formula calculates the nutritional amount in each ingredient based on its unit and amount
- a cascade of callbacks ensures that the ingredients are looked up, profiled and the nutritional profile of the recipe calculated based on aggregated values of the ingredients
- profiling is optimized in the sense that on updates ingredients are only re-profiled if they have changed significantly
A particular challenge was to reliably match ingredients provided by the user to entries in the USDA foods table. Therefore I needed to take peculiarities in the original data source into account.
Thinking Sphinx is used to help with the search, since it has full-text search and stemming capabilities. In addition to using Thinking Sphinx I set up an algorithm to perform multiple searches if necessary and depending on the number of results returned from the first search. Details can be found in the IngredientParser model, that is responsible to find the food and the weight associated with an ingredient and flag it according to the results.
After a food corresponding to the ingredient is found, a similar algorithm is employed to find the right household measure for the ingredient, since that is necessary to be able to quantitatively profile the recipe. That algorithm is still under development. Basically the algorithm tries a few other common measures or units if the one provided by the user could not be found. This is incomplete still, since we would need to convert the unit indicated by the user and the unit found in the weights table. For now I was aiming to maximize the "hits", i.e. the ingredients fully profiled, so that the profile of the recipe is based on as many ingredients as possible.
On the UI side, I tried to place the recipe entry and search in the context of a (mocked-up) website. Some Ajax has been applied to the nested form, so that users can add as many ingredients as is necessary by generating the sub-form for ingredients on the fly.
###Still To Do
- improve algorithm for finding foods and weights
- more complete test suite for edge cases