Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #13 🎫: Food list and form #19

Merged
merged 12 commits into from
Dec 20, 2023
12 changes: 8 additions & 4 deletions app/controllers/foods_controller.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
class FoodsController < ApplicationController
before_action :authenticate_user!
before_action :set_food, only: %i[show edit update destroy]

# GET /foods or /foods.json
def index
@foods = Food.all
@foods = Food.where(user_id: current_user.id)
end

# GET /foods/1 or /foods/1.json
Expand All @@ -20,10 +21,12 @@ def edit; end
# POST /foods or /foods.json
def create
@food = Food.new(food_params)
@food.user = current_user

respond_to do |format|
if @food.save
format.html { redirect_to food_url(@food), notice: 'Food was successfully created.' }
flash[:success] = 'Food was successfully created.'
format.html { redirect_to foods_path }
format.json { render :show, status: :created, location: @food }
else
format.html { render :new, status: :unprocessable_entity }
Expand All @@ -50,7 +53,8 @@ def destroy
@food.destroy!

respond_to do |format|
format.html { redirect_to foods_url, notice: 'Food was successfully destroyed.' }
flash[:success] = 'Food was successfully destroyed.'
format.html { redirect_to foods_url }
format.json { head :no_content }
end
end
Expand All @@ -64,6 +68,6 @@ def set_food

# Only allow a list of trusted parameters through.
def food_params
params.require(:food).permit(:name, :measurement_unit, :price, :quantity, :user_id)
params.require(:food).permit(:name, :measurement_unit, :price, :quantity)
end
end
9 changes: 9 additions & 0 deletions app/models/food.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@ class Food < ApplicationRecord
belongs_to :user
has_many :recipe_foods
has_many :recipes, through: :recipe_foods

validates :name, presence: true
validates :price, presence: true, numericality: { greater_than: 0 }
validates :measurement_unit, presence: true, inclusion: { in: %w[mg g kg l ml] }
validates :quantity, presence: true, numericality: { greater_than: 0 }

def total_price
(price * quantity).round(2)
end
end
36 changes: 9 additions & 27 deletions app/views/foods/_food.html.erb
Original file line number Diff line number Diff line change
@@ -1,27 +1,9 @@
<div id="<%= dom_id food %>">
<p>
<strong>Name:</strong>
<%= food.name %>
</p>

<p>
<strong>Measurement unit:</strong>
<%= food.measurement_unit %>
</p>

<p>
<strong>Price:</strong>
<%= food.price %>
</p>

<p>
<strong>Quantity:</strong>
<%= food.quantity %>
</p>

<p>
<strong>User:</strong>
<%= food.user_id %>
</p>

</div>
<tr>
<td><%= food.name %></td>
<td><%= food.measurement_unit %></td>
<td><%= "$#{food.price}" %></td>
<td><%= "#{food.quantity}#{food.measurement_unit}" %></td>
<td><%= button_to "Delete", food,
method: :delete,
class: "btn btn-outline-danger px-2 py-1" %></td>
</tr>
40 changes: 24 additions & 16 deletions app/views/foods/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,40 @@
</div>
<% end %>

<div>
<%= form.label :name, style: "display: block" %>
<%= form.text_field :name %>
<div class="field">
<%= form.text_field :name,
placeholder: "Name",
aria: { label: "Food Name" },
class: "form-control mb-2" %>
</div>

<div>
<%= form.label :measurement_unit, style: "display: block" %>
<%= form.text_field :measurement_unit %>
<div class="field">
<%= form.select :measurement_unit,
options_for_select(["mg", "g", "kg", "l", "ml"]),
{ prompt: "Select Measurement Unit" },
aria: { label: "Measurement unit" },
class: "form-control mb-2" %>
</div>

<div>
<%= form.label :price, style: "display: block" %>
<%= form.text_field :price %>
<div class="field">
<%= form.text_field :price,
placeholder: "Unit price",
aria: { label: "Unit price" },
class: "form-control mb-2" %>
</div>

<div>
<%= form.label :quantity, style: "display: block" %>
<%= form.number_field :quantity %>
<div class="field">
<%= form.number_field :quantity,
placeholder: "Quantity",
aria: { label: "Quantity" },
class: "form-control mb-2" %>
</div>

<div>
<%= form.label :user_id, style: "display: block" %>
<%= form.text_field :user_id %>
<%= form.hidden_field :user_id, value: current_user.id %>
</div>

<div>
<%= form.submit %>
<div class="actions">
<%= form.submit "Save", class: "btn btn-success w-100" %>
</div>
<% end %>
40 changes: 29 additions & 11 deletions app/views/foods/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
<p style="color: green"><%= notice %></p>
<main class='container mt-4' style="max-width: 900px;">

<h1>Foods</h1>
<div id="foods">
<div class="p-2" style="text-align: end;">
<%= link_to "New food", new_food_path, class: "btn btn-outline-primary m-1" %>
</div>
<% if @foods.empty? %>
<div class="alert alert-info text-center">
<p class="mb-0">There are no foods in your inventory.</p>
</div>
<% else %>
<table class="table table-hover table-striped border">
<thead>
<tr>
<th>Food</th>
<th>Measurement unit</th>
<th>Unit Price</th>
<th>Quantity</th>
<th>Actions</th>
</tr>
</thead>

<div id="foods">
<% @foods.each do |food| %>
<%= render food %>
<p>
<%= link_to "Show this food", food %>
</p>
<% end %>
</div>
<tbody>
<% @foods.each do |food| %>
<%= render food %>
<% end %>
</tbody>
</table>
<% end %>
</div>
</main>

<%= link_to "New food", new_food_path %>
14 changes: 8 additions & 6 deletions app/views/foods/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<h1>New food</h1>
<h2 class="text-muted text-center mb-4">Add a new item to inventory</h2>
<div style="max-width: 400px; margin: 0 auto;" class="mb-3">

<%= render "form", food: @food %>
<%= render "form", food: @food %>

<br>
<br>

<div>
<%= link_to "Back to foods", foods_path %>
</div>
<div>
<%= link_to "Back to food list", foods_path, class: "btn btn-secondary px-2 py-1" %>
</div>
</div>
39 changes: 23 additions & 16 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,30 @@

<body>

<div class="p-1 text-center">
<% if user_signed_in? %>
<%= button_to("Sign Out", destroy_user_session_path,
method: :delete,
class: "btn btn-outline-success px-2 py-1",
style: "font-size: 0.9rem;") %>
<% else %>
<%= button_to("Sign in", new_user_session_path,
method: :get,
class: "btn btn-outline-success px-2 py-1",
style: "font-size: 0.9rem;") %>
<% end %>
</div>
<div class="p-1 text-center">
<% if user_signed_in? %>
<%= button_to("Sign Out", destroy_user_session_path,
method: :delete,
class: "btn btn-outline-success px-2 py-1",
style: "font-size: 0.9rem;") %>
<% else %>
<%= button_to("Sign in", new_user_session_path,
method: :get,
class: "btn btn-outline-success px-2 py-1",
style: "font-size: 0.9rem;") %>
<% end %>
</div>

<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<div class="container mt-1 text-center">
<% flash.each do |key, message| %>
<div class="alert alert-<%= key %> m-2">
<%= message %>
</div>
<% end %>
</div>

<%= yield %>
<main class="container mt-4" style="max-width: 900px; height: 80vh;">
<%= yield %>
</main>
</body>
</html>
10 changes: 6 additions & 4 deletions spec/factories/foods.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
require 'faker'

FactoryBot.define do
factory :food do
name { 'MyString' }
measurement_unit { 'MyString' }
price { '9.99' }
name { Faker::Food.ingredient }
measurement_unit { 'kg' }
price { 1.5 }
quantity { 1 }
user { nil }
user { create(:user) }
end
end
3 changes: 3 additions & 0 deletions spec/factories/users.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
require 'faker'

FactoryBot.define do
factory :user do
name { Faker::Name.name }
email { Faker::Internet.email }
password { '123456' }
password_confirmation { '123456' }
confirmed_at { Time.zone.now }
end
end
67 changes: 66 additions & 1 deletion spec/models/food_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,70 @@
require 'rails_helper'

RSpec.describe Food, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
let(:food) { build(:food) } # ! non persisting object. It's not saved in the database.

describe 'validations' do
context 'object itself' do
it 'should be valid' do
expect(food).to be_valid
end
end

context 'name validations' do
it 'should be valid' do
expect(food.name).to be_present
end

it 'should be invalid' do
food.name = nil
expect(food).to_not be_valid
end
end

context 'measurement_unit validations' do
it 'should be valid' do
expect(food.measurement_unit).to be_present
expect(food.measurement_unit).to be_in(%w[mg g kg l ml])
end

it 'should be invalid' do
food.measurement_unit = nil
expect(food).to_not be_valid
end
end

context 'price validations' do
it 'should be valid' do
expect(food.price).to be_present
expect(food.price).to be_a(BigDecimal)
expect(food.price).to be > 0
end

it 'should be invalid' do
food.price = nil
expect(food).to_not be_valid
end
end

context 'quantity validations' do
it 'should be valid' do
expect(food.quantity).to be_present
expect(food.quantity).to be_a(Integer)
expect(food.quantity).to be > 0
end

it 'should be invalid' do
food.quantity = nil
expect(food).to_not be_valid
end
end

context 'total_price validations' do
it 'should be valid' do
expect(food.total_price).to be_present
expect(food.total_price).to be_a(BigDecimal)
expect(food.total_price).to be > 0
end
end
end
end
Loading
Loading