From 7c2c5b7700cc8fc94764f1244ea6308f252757d6 Mon Sep 17 00:00:00 2001 From: Donard97 Date: Thu, 6 Jan 2022 22:49:57 +0100 Subject: [PATCH 1/2] Add associations to recipe models --- app/controllers/recipe_foods_controller.rb | 46 ++++++++++++++++++++++ app/controllers/users_controller.rb | 8 ++++ app/models/recipe.rb | 14 +++++++ app/models/recipe_food.rb | 4 ++ 4 files changed, 72 insertions(+) diff --git a/app/controllers/recipe_foods_controller.rb b/app/controllers/recipe_foods_controller.rb index c792df9..ed655c0 100644 --- a/app/controllers/recipe_foods_controller.rb +++ b/app/controllers/recipe_foods_controller.rb @@ -1,2 +1,48 @@ class RecipeFoodsController < ApplicationController + before_action :set_recipe_food, only: %i[edit update destroy] + before_action :set_foods, only: %i[edit new update] + + def new + @recipe = Recipe.find(params[:recipe_id]) + @recipe_food = @recipe.recipe_foods.new + end + + def edit; end + + def create + @recipe_food = Recipe.Food.new(recipe_food_params) + + respond_to do |format| + if @recipe_food.save + format.html do + redirect_to recipe_path([:recipe_id]), notice: 'Recipe food was successfully created.') + end + else + set_foods + format.html { render :new, status: :unprocessable_entity } + end + end + end + + def destroy + recipe = @recipe_food.recipe + recipe.foods.delete(@recipe_food.food) + respond_to do |format| + format.html { redirect_to recipe_path(recipe), notice: 'Recipe food was successfully deleted.' } + end + end + + private + + def set_foods + @foods = current_user.foods.map { |food| [food.name, food.id] } + end + + def set_recipe_food + @recipe_food = RecipeFood.includes(:recipe, :food).find(params[:id]) + end + + def recipe_food_params + params.fetch(:recipe_food, {}).permit(:quantity, :food_id, :recipe_id) + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 0b39988..fd4ca09 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,4 +2,12 @@ class UsersController < ApplicationController def index @users = User.all end + + def show + @recipe_foods = RecipeFood.joins(:food, :recipe).where(food: { user: current_user }, recipe: { user: current_user }) + @items_count = @recipe_foods.select('food_id').distinct.count + @total_amount = @recipe_foods.sum('quantity * price') + @items = @recipe_foods.group('food.name, price, measurement_unit') + .select('food.name, SUM(quantity) as quantity, (sum(quantity) * price) as price, measurement_unit') + end end diff --git a/app/models/recipe.rb b/app/models/recipe.rb index 69523fd..26ec389 100644 --- a/app/models/recipe.rb +++ b/app/models/recipe.rb @@ -1,2 +1,16 @@ class Recipe < ApplicationRecord + belongs_to :user + has_many :recipe_foods, dependet: :destroy + has_many :foods, through: :recipe_foods, dependent: :destroy + has_many :foods, through: :recipe_foods, dependent: :destroy + + validates :name, :preparation_time, :cooking_time, :description, presence: true + + def total_items + recipe_foods.sum(:quantity) + end + + def total_price + recipe_foods.joins(:recipe, :food).sum('price * quantity') + end end diff --git a/app/models/recipe_food.rb b/app/models/recipe_food.rb index 2e1e62b..9fcb4e6 100644 --- a/app/models/recipe_food.rb +++ b/app/models/recipe_food.rb @@ -1,2 +1,6 @@ class RecipeFood < ApplicationRecord + belongs_to :recipe + belongs_to :food + validates :food_id, presence: true, uniqueness: { scope: :recipe_id } + validates :quantity, presence: true, numericality: { greater_than: 0 } end From 1a8ae9664bb5b30cb1ad7f44cc182241681d4772 Mon Sep 17 00:00:00 2001 From: Donard97 Date: Fri, 7 Jan 2022 00:16:56 +0100 Subject: [PATCH 2/2] Add views for food items and add style to it --- app/assets/stylesheets/application.css | 43 +++++++++++++++++++++- app/controllers/recipe_foods_controller.rb | 4 +- app/models/recipe.rb | 2 +- app/views/recipe_foods/_form.html.erb | 21 +++++++++++ app/views/recipe_foods/_index.html.erb | 30 +++++++++++++++ app/views/recipe_foods/edit.html.erb | 9 +++++ app/views/recipe_foods/index.html.erb | 2 - app/views/recipe_foods/new.html.erb | 29 +++++++++++++++ app/views/recipe_foods/show.html.erb | 2 - app/views/recipes/show.html.erb | 15 ++++---- config/routes.rb | 5 ++- 11 files changed, 145 insertions(+), 17 deletions(-) create mode 100644 app/views/recipe_foods/_form.html.erb create mode 100644 app/views/recipe_foods/_index.html.erb create mode 100644 app/views/recipe_foods/edit.html.erb delete mode 100644 app/views/recipe_foods/index.html.erb create mode 100644 app/views/recipe_foods/new.html.erb delete mode 100644 app/views/recipe_foods/show.html.erb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index a3defa3..9816165 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -14,10 +14,10 @@ *= require_self */ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300&display=swap'); +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300&display=swap"); body { - font-family: 'Inter', sans-serif; + font-family: Inter, sans-serif; } .add-btn { @@ -73,3 +73,42 @@ li { .log-input { width: 140px; } + +.r-btn { + font-weight: 600; +} + +.f-select { + width: 100%; + padding: 7px; +} + +/* stylelint-disable-next-line selector-id-pattern */ +select#recipe_food_food_id { + width: 100%; + padding: 5px; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + appearance: none; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +/* stylelint-disable-next-line selector-id-pattern */ +select#recipe_food_food_id:focus { + color: #212529; + background-color: #fff; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgb(13 110 253 / 25%); +} + +.rf-btn { + margin: auto; + width: fit-content; +} diff --git a/app/controllers/recipe_foods_controller.rb b/app/controllers/recipe_foods_controller.rb index ed655c0..94c113b 100644 --- a/app/controllers/recipe_foods_controller.rb +++ b/app/controllers/recipe_foods_controller.rb @@ -10,12 +10,12 @@ def new def edit; end def create - @recipe_food = Recipe.Food.new(recipe_food_params) + @recipe_food = RecipeFood.new(recipe_food_params) respond_to do |format| if @recipe_food.save format.html do - redirect_to recipe_path([:recipe_id]), notice: 'Recipe food was successfully created.') + redirect_to recipe_path([:recipe_id]), notice: 'Recipe food was successfully created.' end else set_foods diff --git a/app/models/recipe.rb b/app/models/recipe.rb index 26ec389..b6851fe 100644 --- a/app/models/recipe.rb +++ b/app/models/recipe.rb @@ -1,6 +1,6 @@ class Recipe < ApplicationRecord belongs_to :user - has_many :recipe_foods, dependet: :destroy + has_many :recipe_foods, dependent: :destroy has_many :foods, through: :recipe_foods, dependent: :destroy has_many :foods, through: :recipe_foods, dependent: :destroy diff --git a/app/views/recipe_foods/_form.html.erb b/app/views/recipe_foods/_form.html.erb new file mode 100644 index 0000000..c80cf95 --- /dev/null +++ b/app/views/recipe_foods/_form.html.erb @@ -0,0 +1,21 @@ +<%= form_with(model: recipe_food) do |form| %> +
+ <%= form.label :food, class: "label" %> +
+ <%= form.select :food_id, @foods %> +
+
+ +
+ <%= form.label :quantity, class: "label" %> +
+ <%= form.text_field :quantity, class: "input", type: "number", required: true, min: 1 %> +
+
+ + <%= form.hidden_field :recipe_id, value: recipe_food.recipe_id %> + +
+ <%= form.submit class: "button is-success" %> +
+<% end %> \ No newline at end of file diff --git a/app/views/recipe_foods/_index.html.erb b/app/views/recipe_foods/_index.html.erb new file mode 100644 index 0000000..57b2eab --- /dev/null +++ b/app/views/recipe_foods/_index.html.erb @@ -0,0 +1,30 @@ +
+ + + + + + + + + + + + <% recipe_foods.each do |recipe_food| %> + + + + + <% if can? :update, recipe_food.recipe %> + + <% end %> + + <% end %> + +
FoodQuantityValueActions
<%= recipe_food.food.name %><%= pluralize(recipe_food.quantity, recipe_food.food.measurement_unit) %>$<%= recipe_food.quantity * recipe_food.food.price %> +
+ <%= link_to 'Edit', edit_recipe_food_path(recipe_food), class: "button is-small is-success is-light" %> + <%= link_to 'Delete', recipe_food_path(recipe_food), method: :delete, data: { confirm: 'Are you sure?' }, class: "button is-small is-danger is-light" %> +
+
+
\ No newline at end of file diff --git a/app/views/recipe_foods/edit.html.erb b/app/views/recipe_foods/edit.html.erb new file mode 100644 index 0000000..05d7a02 --- /dev/null +++ b/app/views/recipe_foods/edit.html.erb @@ -0,0 +1,9 @@ + +
+
+

Edit Ingredient

+ + <%= render 'form', recipe_food: @recipe_food %> + <%= link_to 'Back', url_for(:back), class: "button is-light mt-2" %> +
+
\ No newline at end of file diff --git a/app/views/recipe_foods/index.html.erb b/app/views/recipe_foods/index.html.erb deleted file mode 100644 index 3319ebd..0000000 --- a/app/views/recipe_foods/index.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

RecipeFoods#index

-

Find me in app/views/recipe_foods/index.html.erb

diff --git a/app/views/recipe_foods/new.html.erb b/app/views/recipe_foods/new.html.erb new file mode 100644 index 0000000..4ed2382 --- /dev/null +++ b/app/views/recipe_foods/new.html.erb @@ -0,0 +1,29 @@ +
+ +<%= form_with(model: @recipe_food) do |form| %> +
+
+
+ <%= form.label :food, class: "form-label p-2" %> +
+ <%= form.select :food_id, @foods, class: "form-select" %> +
+
+ +
+ <%= form.label :quantity, class: "label", class: "form-label p-2" %> +
+ <%= form.text_field :quantity, class: "form-control", type: "number", required: true, min: 1 %> +
+
+ + <%= form.hidden_field :recipe_id, value: @recipe_food.recipe_id %> + +
+ <%= form.submit class: "btn btn-primary btn-floating mx-1" %> +
+
+
+<% end %> + +
\ No newline at end of file diff --git a/app/views/recipe_foods/show.html.erb b/app/views/recipe_foods/show.html.erb deleted file mode 100644 index 1ac150d..0000000 --- a/app/views/recipe_foods/show.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

RecipeFoods#show

-

Find me in app/views/recipe_foods/show.html.erb

diff --git a/app/views/recipes/show.html.erb b/app/views/recipes/show.html.erb index 9c83b1b..f3543e6 100644 --- a/app/views/recipes/show.html.erb +++ b/app/views/recipes/show.html.erb @@ -20,13 +20,14 @@
Cooking time: <%= @recipe.preparation_time %> min
Steps go here...
-
-
- <%= link_to "Generate shopping list", recipes_path, data: {disable_with: "Adding..."}, class: "btn btn-primary btn-floating mx-1"%> -
-
- <%= link_to "Add ingredient", recipes_path, data: {disable_with: "Adding..."}, class: "btn btn-primary btn-floating mx-1"%> -
+
+ + <% if can? :update, @recipe %> + <%= link_to 'Add ingredient', new_recipe_recipe_food_path(@recipe), class: "btn btn-primary btn-floating mx-1 r-btn" %> + <% end %>
+
+ <%= render partial: "recipe_foods/index", locals: { recipe_foods: @recipe.recipe_foods } %> +
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 36e0d77..5d54a76 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,7 +2,10 @@ devise_for :users root to: 'foods#index' resources :foods, only: [:index, :new, :create, :destroy] - resources :recipes, only: [:index, :show, :new, :create, :destroy] + resources :recipes, only: [:index, :show, :new, :create, :destroy] do + resources :recipe_foods, only: [:new] + end + resources :recipe_foods, only: [:edit, :update, :destroy, :create] devise_scope :user do authenticated :user do