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

User Registration Implementation #17

Merged
merged 9 commits into from
Dec 19, 2023
Merged
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ gem 'jbuilder'

# Use Redis adapter to run Action Cable in production
# gem "redis", ">= 4.0.1"

gem 'pg'
# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
# gem "kredis"
gem 'rubocop', '>= 1.0', '< 2.0'
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ GEM
parser (3.2.2.4)
ast (~> 2.4.1)
racc
pg (1.5.4)
psych (5.1.1.1)
stringio
public_suffix (5.0.4)
Expand Down Expand Up @@ -313,6 +314,7 @@ DEPENDENCIES
faker
importmap-rails
jbuilder
pg
puma (>= 5.0)
rails (~> 7.1.2)
rails-controller-testing
Expand Down
7 changes: 7 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?

protected

def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
end
end
69 changes: 69 additions & 0 deletions app/controllers/foods_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class FoodsController < ApplicationController
before_action :set_food, only: %i[show edit update destroy]

# GET /foods or /foods.json
def index
@foods = Food.all
end

# GET /foods/1 or /foods/1.json
def show; end

# GET /foods/new
def new
@food = Food.new
end

# GET /foods/1/edit
def edit; end

# POST /foods or /foods.json
def create
@food = Food.new(food_params)

respond_to do |format|
if @food.save
format.html { redirect_to food_url(@food), notice: 'Food was successfully created.' }
format.json { render :show, status: :created, location: @food }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @food.errors, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /foods/1 or /foods/1.json
def update
respond_to do |format|
if @food.update(food_params)
format.html { redirect_to food_url(@food), notice: 'Food was successfully updated.' }
format.json { render :show, status: :ok, location: @food }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @food.errors, status: :unprocessable_entity }
end
end
end

# DELETE /foods/1 or /foods/1.json
def destroy
@food.destroy!

respond_to do |format|
format.html { redirect_to foods_url, notice: 'Food was successfully destroyed.' }
format.json { head :no_content }
end
end

private

# Use callbacks to share common setup or constraints between actions.
def set_food
@food = Food.find(params[:id])
end

# Only allow a list of trusted parameters through.
def food_params
params.require(:food).permit(:name, :measurement_unit, :price, :quantity, :user_id)
end
end
69 changes: 69 additions & 0 deletions app/controllers/recipes_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class RecipesController < ApplicationController
before_action :set_recipe, only: %i[show edit update destroy]

# GET /recipes or /recipes.json
def index
@recipes = Recipe.all
end

# GET /recipes/1 or /recipes/1.json
def show; end

# GET /recipes/new
def new
@recipe = Recipe.new
end

# GET /recipes/1/edit
def edit; end

# POST /recipes or /recipes.json
def create
@recipe = Recipe.new(recipe_params)

respond_to do |format|
if @recipe.save
format.html { redirect_to recipe_url(@recipe), notice: 'Recipe was successfully created.' }
format.json { render :show, status: :created, location: @recipe }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /recipes/1 or /recipes/1.json
def update
respond_to do |format|
if @recipe.update(recipe_params)
format.html { redirect_to recipe_url(@recipe), notice: 'Recipe was successfully updated.' }
format.json { render :show, status: :ok, location: @recipe }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
end

# DELETE /recipes/1 or /recipes/1.json
def destroy
@recipe.destroy!

respond_to do |format|
format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
format.json { head :no_content }
end
end

private

# Use callbacks to share common setup or constraints between actions.
def set_recipe
@recipe = Recipe.find(params[:id])
end

# Only allow a list of trusted parameters through.
def recipe_params
params.require(:recipe).permit(:name, :preparation_time, :cooking_time, :description, :public, :user_id)
end
end
2 changes: 2 additions & 0 deletions app/helpers/foods_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module FoodsHelper
end
2 changes: 2 additions & 0 deletions app/helpers/recipes_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module RecipesHelper
end
5 changes: 5 additions & 0 deletions app/models/food.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Food < ApplicationRecord
belongs_to :user
has_many :recipe_foods
has_many :recipes, through: :recipe_foods
end
5 changes: 5 additions & 0 deletions app/models/recipe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Recipe < ApplicationRecord
belongs_to :user
has_many :recipe_foods
has_many :foods, through: :recipe_foods
end
10 changes: 10 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable

has_many :recipes

validates :name, presence: true
end
16 changes: 16 additions & 0 deletions app/views/devise/confirmations/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h2>Resend confirmation instructions</h2>

<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>

<div class="actions">
<%= f.submit "Resend confirmation instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
5 changes: 5 additions & 0 deletions app/views/devise/mailer/confirmation_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<p>Welcome <%= @email %>!</p>

<p>You can confirm your account email through the link below:</p>

<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
7 changes: 7 additions & 0 deletions app/views/devise/mailer/email_changed.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<p>Hello <%= @email %>!</p>

<% if @resource.try(:unconfirmed_email?) %>
<p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
<p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
<% end %>
3 changes: 3 additions & 0 deletions app/views/devise/mailer/password_change.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>Hello <%= @resource.email %>!</p>

<p>We're contacting you to notify you that your password has been changed.</p>
8 changes: 8 additions & 0 deletions app/views/devise/mailer/reset_password_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<p>Hello <%= @resource.email %>!</p>

<p>Someone has requested a link to change your password. You can do this through the link below.</p>

<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>

<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
7 changes: 7 additions & 0 deletions app/views/devise/mailer/unlock_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<p>Hello <%= @resource.email %>!</p>

<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>

<p>Click the link below to unlock your account:</p>

<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
25 changes: 25 additions & 0 deletions app/views/devise/passwords/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<h2>Change your password</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<%= f.hidden_field :reset_password_token %>

<div class="field">
<%= f.label :password, "New password" %><br />
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em><br />
<% end %>
<%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
</div>

<div class="field">
<%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>

<div class="actions">
<%= f.submit "Change my password" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
16 changes: 16 additions & 0 deletions app/views/devise/passwords/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h2>Forgot your password?</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

<div class="actions">
<%= f.submit "Send me reset password instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
43 changes: 43 additions & 0 deletions app/views/devise/registrations/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>

<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>

<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>

<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>

<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>

<h3>Cancel my account</h3>

<div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>

<%= link_to "Back", :back %>
40 changes: 40 additions & 0 deletions app/views/devise/registrations/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-4">
<h2 class="text-center mb-4">Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: 'needs-validation', novalidate: true }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', autocomplete: 'name', required: true %>
</div>

<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control', autofocus: true, autocomplete: 'email', required: true %>
</div>

<div class="form-group">
<%= f.label :password %>
<% if @minimum_password_length %>
<small class="text-muted">(<%= @minimum_password_length %> characters minimum)</small>
<% end %>
<%= f.password_field :password, class: 'form-control', autocomplete: 'new-password', required: true %>
</div>

<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control', autocomplete: 'new-password', required: true %>
</div>

<div class="text-center">
<%= f.submit "Sign up", class: 'btn btn-primary' %>
</div>
<% end %>

<%= render "devise/shared/links" %>
</div>
</div>
</div>
Loading
Loading