Skip to content

Commit 2004a78

Browse files
committed
Add MealPlan & Meal model
This commit creates the models necessary for generating meal plans for users, `MealPlan` and `Meal`. Additionally, this commit implements the initial randomization of the meal plan that a user can customize before persisting it.
1 parent 7d66a41 commit 2004a78

File tree

9 files changed

+149
-2
lines changed

9 files changed

+149
-2
lines changed

app/models/meal.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Meal < ApplicationRecord
2+
belongs_to :meal_plan
3+
belongs_to :recipe
4+
end

app/models/meal_plan.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class MealPlan < ApplicationRecord
2+
belongs_to :user
3+
has_many :meals
4+
5+
validates :start_date, presence: true
6+
validates :end_date, presence: true
7+
validates :user, presence: true
8+
9+
def build_meals
10+
user_recipe_ids = user.recipes.pluck(:id)
11+
12+
(start_date..end_date).each do |date|
13+
unused_recipe_ids = user_recipe_ids - meals.map(&:recipe_id)
14+
15+
if unused_recipe_ids.empty?
16+
available_recipe_ids = user_recipe_ids
17+
else
18+
available_recipe_ids = unused_recipe_ids
19+
end
20+
21+
meals.build(date: date, recipe_id: available_recipe_ids.sample)
22+
end
23+
end
24+
end

config/application.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# you've limited to :test, :development, or :production.
1616
Bundler.require(*Rails.groups)
1717

18-
module MealPlan
18+
module MealPlanner
1919
class Application < Rails::Application
2020
# Settings in config/environments/* take precedence over those specified here.
2121
# Application configuration should go into files in config/initializers
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CreateMealPlans < ActiveRecord::Migration[5.0]
2+
def change
3+
create_table :meal_plans do |t|
4+
t.date :start_date, null: false
5+
t.date :end_date, null: false
6+
t.references :user, null: false, foreign_key: true
7+
t.timestamps null: false
8+
end
9+
end
10+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CreateMeals < ActiveRecord::Migration[5.0]
2+
def change
3+
create_table :meals do |t|
4+
t.date :date, null: false
5+
t.references :meal_plan, null: false, foreign_key: true
6+
t.references :recipe, null: false, foreign_key: true
7+
t.timestamps null: false
8+
end
9+
end
10+
end

db/schema.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,30 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema.define(version: 20161119203421) do
13+
ActiveRecord::Schema.define(version: 20161205100045) do
1414

1515
# These are extensions that must be enabled in order to support this database
1616
enable_extension "plpgsql"
1717

18+
create_table "meal_plans", force: :cascade do |t|
19+
t.date "start_date", null: false
20+
t.date "end_date", null: false
21+
t.integer "user_id", null: false
22+
t.datetime "created_at", null: false
23+
t.datetime "updated_at", null: false
24+
t.index ["user_id"], name: "index_meal_plans_on_user_id", using: :btree
25+
end
26+
27+
create_table "meals", force: :cascade do |t|
28+
t.date "date", null: false
29+
t.integer "meal_plan_id", null: false
30+
t.integer "recipe_id", null: false
31+
t.datetime "created_at", null: false
32+
t.datetime "updated_at", null: false
33+
t.index ["meal_plan_id"], name: "index_meals_on_meal_plan_id", using: :btree
34+
t.index ["recipe_id"], name: "index_meals_on_recipe_id", using: :btree
35+
end
36+
1837
create_table "recipes", force: :cascade do |t|
1938
t.string "name", null: false
2039
t.text "description", null: false
@@ -36,5 +55,8 @@
3655
t.index ["remember_token"], name: "index_users_on_remember_token", using: :btree
3756
end
3857

58+
add_foreign_key "meal_plans", "users"
59+
add_foreign_key "meals", "meal_plans"
60+
add_foreign_key "meals", "recipes"
3961
add_foreign_key "recipes", "users"
4062
end

test/factories/meal_plans.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FactoryGirl.define do
2+
factory :meal_plan do
3+
start_date { Date.today }
4+
end_date { 6.days.from_now.to_date }
5+
6+
association(:user)
7+
end
8+
end

test/factories/meals.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FactoryGirl.define do
2+
factory :meal do
3+
4+
end
5+
end

test/models/meal_plan_test.rb

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
require "test_helper"
2+
3+
describe MealPlan do
4+
describe "validity" do
5+
let(:meal_plan) { MealPlan.new }
6+
7+
before do
8+
meal_plan.valid?
9+
end
10+
11+
it "requires a start date" do
12+
meal_plan.errors[:start_date].must_include "can't be blank"
13+
end
14+
15+
it "requires an end date" do
16+
meal_plan.errors[:end_date].must_include "can't be blank"
17+
end
18+
19+
it "requires a user" do
20+
meal_plan.errors[:user].must_include "can't be blank"
21+
end
22+
end
23+
24+
describe "generating a weekly plan" do
25+
let(:meal_plan) { build(:meal_plan) }
26+
27+
before do
28+
7.times do
29+
create(:recipe, user: meal_plan.user)
30+
end
31+
end
32+
33+
it "populates a meal for each day between the start date and the end date" do
34+
meal_plan.meals.size.must_equal 0
35+
36+
meal_plan.build_meals
37+
38+
meal_plan.meals.size.must_equal 7
39+
end
40+
41+
it "builds valid meals" do
42+
meal_plan.build_meals
43+
44+
meal_plan.meals.all?(&:valid?).must_equal true
45+
end
46+
47+
describe "with more days than recipes" do
48+
let(:meal_plan) { build(:meal_plan, end_date: 8.days.from_now) }
49+
50+
it "build valid meals" do
51+
meal_plan.build_meals
52+
53+
meal_plan.meals.all?(&:valid?).must_equal true
54+
end
55+
56+
it "reuses recipes where necessary" do
57+
meal_plan.build_meals
58+
59+
uniq_ids = meal_plan.meals.map(&:recipe_id).uniq
60+
uniq_ids.size.must_equal 7
61+
end
62+
end
63+
end
64+
end

0 commit comments

Comments
 (0)