Skip to content

Commit

Permalink
Merge pull request #19 from demesameneshoa/feature/food-list-and-form
Browse files Browse the repository at this point in the history
Issue #13 🎫: Food list and form
  • Loading branch information
demesameneshoa authored Dec 20, 2023
2 parents 9656ac1 + 5564d15 commit 563637c
Show file tree
Hide file tree
Showing 11 changed files with 220 additions and 112 deletions.
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

0 comments on commit 563637c

Please sign in to comment.