Rails4 User Login - 처음부터
Sep 10, 16
dev
rails
- [Michael Hartl의 Rails tutorial][railstutorial] 에 나온 user login 기능 부분을 정리해 본다.
- User model 생성
rails generate model User name:string email:string
- Validation 추가
class User < ApplicationRecord
before_save { email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
end
- Email에 대해 index 추가
rails generate migration add_index_to_users_email
class AddIndexToUsersEmail < ActiveRecord::Migration[5.0]
def change
add_index :users, :email, unique: true
end
end
- Password 추가(1)
- User 모델에
has_secure_password
추가- method는 hashed password를 password_digest라는 attribute에 저장하도록 해준다.
- password 와 password_confirmation 두 virtual attributes를 사용하게 한다.
authenticate
method로 password가 맞는지 틀린지 알 수 있다.
- User 모델에
class User < ApplicationRecord
.
.
.
has_secure_password
end
- Password 추가(2)
- password_digest attribute 추가
$ rails generate migration add_password_digest_to_users password_digest:string
Gemfile
에 bcrypt 추가has_secure_password
에서bcrypt
hash function을 이용한다.
- password_digest attribute 추가
gem 'bcrypt', '3.1.11'
- Password validation 추가
- 최소 길이 6자
validates :password, presence: true, length: { minimum: 6 }
- 최소 길이 6자
- Route.rb에 routing 추가
resources :users
- User Controller(1)
rails generate controller Users
new
method
def new
@user = User.new
end
- User Controller(2)
new.html.erb
에 form 추가
<%= form_for(@user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
- User Controller(3)
+
strong parameter
추가
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
- User Controller(4)
create
method
def create
@user = User.new(user_params)
if @user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
- User Controller(5)
new.html.erb
에 error message 추가
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages' %>
#_error_messages.html.erb
<% if @user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
- proudction 환경에서 SSL 추가
- Heroku domain(appname.herokuapp.com)에서는 별도의 SSL setting이 필요없음.
Rails.application.configure do
# Force all access to the app over SSL, use Strict-Transport-Security,
# and use secure cookies.
config.force_ssl = true
end
- Session Controller(1)
rails generate controller Sessions new
- Session Controller(2)
- Router에 log-in 관련 routing 추가
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
- Session Controller(3)
/sessions/new.html.erb
에 log-in form 추가
<%= form_for(:session, url: login_path) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>
- Session Controller(4)
create
methodflash.now
는flash
와 다르게 추가적인 reqeust가 있을 시 사라짐.
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
# Log the user in and redirect to the user's show page.
else
flash.now[:danger] = 'Invalid email/password combination' # Not quite right!
render 'new'
end
end
- ApplicationController에 SessionHelper 추가
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
end
app/helpers/sessions_helper.rb
module SessionsHelper
# Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
# Returns the current logged-in user (if any).
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
def logged_in?
!current_user.nil?
end
# Logs out the current user.
def log_out
session.delete(:user_id)
@current_user = nil
end
end
- Session Controller(5)
create
method에 login 추가
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
- Session Controller(6)
destroy
method에 logout 추가
def destroy
log_out
redirect_to root_url
end
+ [railstutorial]: https://www.railstutorial.org/book/_single-page