diff --git a/app/assets/javascripts/calculator.js b/app/assets/javascripts/calculator.js index 08b4f0e..106b795 100644 --- a/app/assets/javascripts/calculator.js +++ b/app/assets/javascripts/calculator.js @@ -58,7 +58,7 @@ } }); - $(document).on("ready page:load", function() { + $(document).on("turbolinks:load", function() { var state = new State(); var $input = $("#input"); diff --git a/app/assets/javascripts/flash_messages.js b/app/assets/javascripts/flash_messages.js index 443dd9f..a603ecf 100644 --- a/app/assets/javascripts/flash_messages.js +++ b/app/assets/javascripts/flash_messages.js @@ -33,7 +33,7 @@ function flashMessage(flashType, message) { }, 5000); } -$(document).on("ready page:load", function() { +$(document).on("turbolinks:load", function() { $("#flashHolder").find("div").each(function(idx, div) { var $div = $(div); var type = $div.attr("class"); diff --git a/app/assets/javascripts/ingredients.js b/app/assets/javascripts/ingredients.js index baa04f7..5517adf 100644 --- a/app/assets/javascripts/ingredients.js +++ b/app/assets/javascripts/ingredients.js @@ -80,7 +80,7 @@ window.INGREDIENT_API = {}; } }); - $(document).on("ready page:load", function() { + $(document).on("turbolinks:load", function() { window.INGREDIENT_API.initialize(); }); diff --git a/app/assets/javascripts/recipe_editor.js b/app/assets/javascripts/recipe_editor.js index 9ab260e..116af43 100644 --- a/app/assets/javascripts/recipe_editor.js +++ b/app/assets/javascripts/recipe_editor.js @@ -156,7 +156,7 @@ return data; } - $(document).on("ready page:load", function() { + $(document).on("turbolinks:load", function() { var $ingredientList = $("#ingredient-list"); var $stepList = $("#step-list"); diff --git a/app/assets/javascripts/recipes.js b/app/assets/javascripts/recipes.js index 6a6c937..e9eacfb 100644 --- a/app/assets/javascripts/recipes.js +++ b/app/assets/javascripts/recipes.js @@ -1,6 +1,6 @@ (function($) { - $(document).on("ready page:load", function() { + $(document).on("turbolinks:load", function() { $(".recipe-view ul.ingredients").checkable(); $(".recipe-view ol.steps").checkable(); }); diff --git a/app/controllers/logs_controller.rb b/app/controllers/logs_controller.rb index a6dda76..348ad6a 100644 --- a/app/controllers/logs_controller.rb +++ b/app/controllers/logs_controller.rb @@ -1,11 +1,11 @@ class LogsController < ApplicationController + before_action :ensure_valid_user + before_action :set_log, only: [:show, :edit, :update, :destroy] before_action :set_recipe, only: [:index, :new, :create] before_action :require_recipe, only: [:new, :create] - before_action :ensure_valid_user - def index @logs = Log.for_user(current_user) if @recipe @@ -33,12 +33,17 @@ class LogsController < ApplicationController def new @log = Log.new + @log.user = current_user + @log.source_recipe = @recipe + @log.recipe = @recipe.log_copy(current_user) end def create - @log = Recipe.new(log_params) + @log = Log.new + @log.recipe = @recipe.log_copy(current_user) + @log.assign_attributes(log_params) @log.user = current_user - @log.souce_recipe = @recipe + @log.source_recipe = @recipe if @log.save redirect_to @log, notice: 'Log Entry was successfully created.' @@ -62,18 +67,18 @@ class LogsController < ApplicationController def set_recipe if params[:recipe_id].present? - @recipe = Recipe.find(params[:recipe_id]) + @recipe = Recipe.includes([{recipe_ingredients: [:ingredient]}, :recipe_steps]).find(params[:recipe_id]) end end - def require_recepe + def require_recipe unless @recipe raise ActiveRecord::RecordNotFound end end def log_params - params.require(:log).permit() + params.require(:log).permit(:date, :rating, recipe_attributes: [:name, :description, :source, :yields, :total_time, :active_time, recipe_ingredients_attributes: [:name, :ingredient_id, :quantity, :units, :preparation, :sort_order, :id, :_destroy], recipe_steps_attributes: [:step, :sort_order, :id, :_destroy]]) end end \ No newline at end of file diff --git a/app/models/log.rb b/app/models/log.rb index 01be794..2649f47 100644 --- a/app/models/log.rb +++ b/app/models/log.rb @@ -6,8 +6,11 @@ class Log < ActiveRecord::Base validates :date, presence: true validates :user_id, presence: true + validates :rating, numericality: { only_integer: true, allow_blank: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5, message: 'must be an integer between 1 and 5, inclusive' } scope :for_user, ->(user) { where(user: user) } scope :for_recipe, ->(recipe) { where(source_recipe: recipe) } + accepts_nested_attributes_for :recipe, update_only: true, allow_destroy: false + end diff --git a/app/models/recipe.rb b/app/models/recipe.rb index c76386f..ddabc59 100644 --- a/app/models/recipe.rb +++ b/app/models/recipe.rb @@ -4,7 +4,9 @@ class Recipe < ActiveRecord::Base has_many :recipe_steps, -> { order :sort_order }, inverse_of: :recipe, dependent: :destroy belongs_to :user - scope :active, -> { where('deleted <> ? OR deleted IS NULL', true) } + scope :undeleted, -> { where('deleted <> ? OR deleted IS NULL', true) } + scope :not_log, -> { where('is_log <> ? OR is_log IS NULL', true) } + scope :active, -> { undeleted.not_log } accepts_nested_attributes_for :recipe_ingredients, allow_destroy: true accepts_nested_attributes_for :recipe_steps, allow_destroy: true @@ -57,6 +59,29 @@ class Recipe < ActiveRecord::Base @parsed_yield end + # Creates a copy of this recipe suitable for associating to a log + def log_copy(user) + copy = Recipe.new + copy.user = user + copy.is_log = true + copy.name = self.name + copy.description = self.description + copy.source = self.source + copy.yields = self.yields + copy.total_time = self.total_time + copy.active_time = self.active_time + + self.recipe_ingredients.each do |ri| + copy.recipe_ingredients << ri.log_copy + end + + self.recipe_steps.each do |rs| + copy.recipe_steps << rs.log_copy + end + + copy + end + private def calculate_nutrition_data diff --git a/app/models/recipe_ingredient.rb b/app/models/recipe_ingredient.rb index 0be47b2..8397dfa 100644 --- a/app/models/recipe_ingredient.rb +++ b/app/models/recipe_ingredient.rb @@ -110,4 +110,16 @@ class RecipeIngredient < ActiveRecord::Base end end + def log_copy + copy = RecipeIngredient.new + copy.ingredient = self.ingredient + copy.name = self.name + copy.sort_order = self.sort_order + copy.quantity = self.quantity + copy.units = self.units + copy.preparation = self.preparation + + copy + end + end diff --git a/app/models/recipe_step.rb b/app/models/recipe_step.rb index 8248001..30064ed 100644 --- a/app/models/recipe_step.rb +++ b/app/models/recipe_step.rb @@ -5,4 +5,12 @@ class RecipeStep < ActiveRecord::Base validates :step, presence: true validates :sort_order, presence: true + def log_copy + copy = RecipeStep.new + copy.sort_order = self.sort_order + copy.step = self.step + + copy + end + end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f5845cd..e4e688b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -60,6 +60,8 @@ +<%= yield(:page_bottom) %> + \ No newline at end of file diff --git a/app/views/logs/_form.html.erb b/app/views/logs/_form.html.erb index d84b0f7..a4c297d 100644 --- a/app/views/logs/_form.html.erb +++ b/app/views/logs/_form.html.erb @@ -1,11 +1,25 @@ -<%= form_for(@log) do |f| %> +<%= form_for([@recipe, @log]) do |f| %> <%= render partial: 'shared/error_list', locals: {model: @log} %>
- <%= f.label :name, class: 'control-label' %> - <%= f.text_field :name, class: 'form-control name', autofocus: true %> + <%= f.label :date, class: 'control-label' %> + <%= f.text_field :date, class: 'form-control name', autofocus: true %> +
+ +
+ <%= f.label :rating, class: 'control-label' %> + <%= f.text_field :rating, class: 'form-control name' %> +
+ + <%= f.fields_for(:recipe, include_id: false) do |rf| %> + <%= render partial: 'recipes/editor', locals: {f: rf} %> + <% end %> +

+ +
+ <%= f.submit class: 'btn btn-primary' %>
<% end %> \ No newline at end of file diff --git a/app/views/logs/new.html.erb b/app/views/logs/new.html.erb index e69de29..0fd5857 100644 --- a/app/views/logs/new.html.erb +++ b/app/views/logs/new.html.erb @@ -0,0 +1,12 @@ +
+
+ + + <%= render 'form' %> + + <%= link_to 'Back', recipes_path, class: 'btn btn-default' %> + +
+
diff --git a/app/views/recipes/_editor.html.erb b/app/views/recipes/_editor.html.erb new file mode 100644 index 0000000..b200eda --- /dev/null +++ b/app/views/recipes/_editor.html.erb @@ -0,0 +1,102 @@ + +
+ +
+
+
+ <%= f.label :name, class: "control-label" %> + <%= f.text_field :name, class: 'form-control' %> +
+
+ +
+
+ <%= f.label :source, class: "control-label" %> + <%= f.text_field :source, class: 'form-control' %> +
+
+
+ + +
+ <%= f.label :description, class: "control-label" %> + <%= f.text_area :description, class: 'form-control' %> +
+ +
+
+
+ <%= f.label :yields, class: "control-label" %> + <%= f.text_field :yields, class: 'form-control', placeholder: 'Servings' %> +
+
+
+
+ <%= f.label :total_time, class: "control-label" %> + <%= f.number_field :total_time, class: 'form-control', placeholder: 'Minutes' %> +
+
+
+
+ <%= f.label :active_time, class: "control-label" %> + <%= f.number_field :active_time, class: 'form-control', placeholder: 'Minutes' %> +
+
+
+ + +

Ingredients

+ +
+ <%= f.fields_for :recipe_ingredients do |ri_form| %> + <%= render partial: 'recipes/editor/ingredient', locals: { f: ri_form } %> + <% end %> +
+ +
+ + <%= link_to_add_association 'Add Ingredient', f, :recipe_ingredients, partial: 'recipes/editor/ingredient', :'data-association-insertion-node' => '#ingredient-list', :'data-association-insertion-method' => 'append', class: 'btn btn-primary', id: 'addIngredientButton' %> + + +

Steps

+ +
+ <%= f.fields_for :recipe_steps do |rs_form| %> + <%= render partial: 'recipes/editor/step', locals: { f: rs_form } %> + <% end %> +
+ +
+ + <%= link_to_add_association 'Add Step', f, :recipe_steps, partial: 'recipes/editor/step', :'data-association-insertion-node' => '#step-list', :'data-association-insertion-method' => 'append', class: 'btn btn-primary', id: 'addStepButton' %> + + <% content_for(:page_bottom) do %> + + <%= render partial: 'recipes/editor/bulk_ingredient_dialog' %> + <%= render partial: 'recipes/editor/bulk_step_dialog' %> + + + + <% end %> + +
\ No newline at end of file diff --git a/app/views/recipes/_form.html.erb b/app/views/recipes/_form.html.erb index fb81d3f..9f9f31b 100644 --- a/app/views/recipes/_form.html.erb +++ b/app/views/recipes/_form.html.erb @@ -2,102 +2,10 @@ <%= render partial: 'shared/error_list', locals: {model: @recipe} %> -
-
-
- <%= f.label :name, class: "control-label" %> - <%= f.text_field :name, class: 'form-control' %> -
-
- -
-
- <%= f.label :source, class: "control-label" %> - <%= f.text_field :source, class: 'form-control' %> -
-
-
- - -
- <%= f.label :description, class: "control-label" %> - <%= f.text_area :description, class: 'form-control' %> -
- -
-
-
- <%= f.label :yields, class: "control-label" %> - <%= f.text_field :yields, class: 'form-control', placeholder: 'Servings' %> -
-
-
-
- <%= f.label :total_time, class: "control-label" %> - <%= f.number_field :total_time, class: 'form-control', placeholder: 'Minutes' %> -
-
-
-
- <%= f.label :active_time, class: "control-label" %> - <%= f.number_field :active_time, class: 'form-control', placeholder: 'Minutes' %> -
-
-
- - -

Ingredients

- -
- <%= f.fields_for :recipe_ingredients do |ri_form| %> - <%= render partial: 'recipes/editor/ingredient', locals: { f: ri_form } %> - <% end %> -
- -
- - <%= link_to_add_association 'Add Ingredient', f, :recipe_ingredients, partial: 'recipes/editor/ingredient', :'data-association-insertion-node' => '#ingredient-list', :'data-association-insertion-method' => 'append', class: 'btn btn-primary', id: 'addIngredientButton' %> - - -

Steps

- -
- <%= f.fields_for :recipe_steps do |rs_form| %> - <%= render partial: 'recipes/editor/step', locals: { f: rs_form } %> - <% end %> -
- -
- - <%= link_to_add_association 'Add Step', f, :recipe_steps, partial: 'recipes/editor/step', :'data-association-insertion-node' => '#step-list', :'data-association-insertion-method' => 'append', class: 'btn btn-primary', id: 'addStepButton' %> + <%= render partial: 'editor', locals: {f: f} %>

<%= f.submit class: 'btn btn-primary' %>
<% end %> - -<%= render partial: 'recipes/editor/bulk_ingredient_dialog' %> -<%= render partial: 'recipes/editor/bulk_step_dialog' %> - - \ No newline at end of file diff --git a/app/views/recipes/index.html.erb b/app/views/recipes/index.html.erb index 924cee9..a38ca59 100644 --- a/app/views/recipes/index.html.erb +++ b/app/views/recipes/index.html.erb @@ -32,6 +32,9 @@ <%= timestamp(recipe.created_at) %> <% if current_user? %> + <%= link_to new_recipe_log_path(recipe), class: 'btn btn-sm btn-primary' do %> + + <% end %> <%= link_to edit_recipe_path(recipe), class: 'btn btn-sm btn-primary' do %> <% end %> diff --git a/app/views/recipes/new.html.erb b/app/views/recipes/new.html.erb index df5c075..ba2bb67 100644 --- a/app/views/recipes/new.html.erb +++ b/app/views/recipes/new.html.erb @@ -1,7 +1,8 @@
- -

New Recipe

+ <%= render 'form' %> diff --git a/db/migrate/20160711170912_add_is_log_to_recipe.rb b/db/migrate/20160711170912_add_is_log_to_recipe.rb new file mode 100644 index 0000000..15301c5 --- /dev/null +++ b/db/migrate/20160711170912_add_is_log_to_recipe.rb @@ -0,0 +1,5 @@ +class AddIsLogToRecipe < ActiveRecord::Migration[5.0] + def change + add_column :recipes, :is_log, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index 9ae8359..cb1f171 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,16 +10,13 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160707011314) do - - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" +ActiveRecord::Schema.define(version: 20160711170912) do create_table "ingredient_units", force: :cascade do |t| t.integer "ingredient_id", null: false t.string "name", null: false t.decimal "gram_weight", precision: 10, scale: 2, null: false - t.index ["ingredient_id"], name: "index_ingredient_units_on_ingredient_id", using: :btree + t.index ["ingredient_id"], name: "index_ingredient_units_on_ingredient_id" end create_table "ingredients", force: :cascade do |t| @@ -77,7 +74,7 @@ ActiveRecord::Schema.define(version: 20160707011314) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.text "preparation" - t.index ["recipe_id"], name: "index_recipe_ingredients_on_recipe_id", using: :btree + t.index ["recipe_id"], name: "index_recipe_ingredients_on_recipe_id" end create_table "recipe_steps", force: :cascade do |t| @@ -86,7 +83,7 @@ ActiveRecord::Schema.define(version: 20160707011314) do t.text "step" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["recipe_id"], name: "index_recipe_steps_on_recipe_id", using: :btree + t.index ["recipe_id"], name: "index_recipe_steps_on_recipe_id" end create_table "recipes", force: :cascade do |t| @@ -100,6 +97,7 @@ ActiveRecord::Schema.define(version: 20160707011314) do t.datetime "updated_at", null: false t.boolean "deleted" t.integer "user_id" + t.boolean "is_log" end create_table "usda_food_weights", force: :cascade do |t| @@ -109,7 +107,7 @@ ActiveRecord::Schema.define(version: 20160707011314) do t.decimal "gram_weight", precision: 7, scale: 1 t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["usda_food_id"], name: "index_usda_food_weights_on_usda_food_id", using: :btree + t.index ["usda_food_id"], name: "index_usda_food_weights_on_usda_food_id" end create_table "usda_foods", force: :cascade do |t| @@ -150,8 +148,8 @@ ActiveRecord::Schema.define(version: 20160707011314) do t.decimal "vit_d", precision: 10, scale: 1 t.decimal "vit_k", precision: 10, scale: 1 t.decimal "cholesterol", precision: 10, scale: 3 - t.index ["long_description"], name: "index_usda_foods_on_long_description", using: :btree - t.index ["ndbn"], name: "index_usda_foods_on_ndbn", using: :btree + t.index ["long_description"], name: "index_usda_foods_on_long_description" + t.index ["ndbn"], name: "index_usda_foods_on_ndbn" end create_table "users", force: :cascade do |t|