Skip to content

Instantly share code, notes, and snippets.

@joemsak
Last active December 16, 2018 02:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joemsak/95bd1b1a2b3f5682de6a9db22ec2aa2f to your computer and use it in GitHub Desktop.
Save joemsak/95bd1b1a2b3f5682de6a9db22ec2aa2f to your computer and use it in GitHub Desktop.
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: -> {
redirect_to root_path, alert: "We couldn't find that list or item on your account"
}
private
def current_user
begin
@current_user ||= User.find_by!(auth_token: session[:user_auth_token])
# I am assuming that the details of storing
# the session are already completed for this usage
rescue ActiveRecord::RecordNotFound
redirect_to signin_path, alert: "You must be signed in to access that action"
end
end
def parse_boolean_in_params(key)
ActiveModel::Type::Boolean.new.cast(params[key])
end
end
class TodoItemCompletionsController < ApplicationController
def update
todo_list = current_user.todo_lists.find(params[:todo_list_id])
todo_item = todo_list.todo_items.find(params[:id])
todo_item.complete!
redirect_to :back
end
end
class TodoListsController < ApplicationController
def index
sort_field = params.fetch(:sort) { 'created_at' }
sort_order = parse_boolean_in_params(:asc) ? :asc : :desc
@lists = current_user.todo_lists
.includes(:todo_items)
.order(sort_field => sort_order)
end
def show
@list = current_user.todo_lists
.includes(:todo_items)
.find(params[:id])
end
def new
@list = TodoList.new
end
def create
@list = current_user.todo_lists.build(todo_list_params)
if @list.save
redirect_to todo_lists_path,
notice: "You created a new todo list!"
else
@errors = @list.errors
redirect_to new_todo_list_path,
alert: "There was a problem saving your list, please check the errors below"
end
end
private
def todo_list_params
params.require(:todo_list).permit(:title)
end
end
class User < ApplicationRecord
has_many :todo_lists
has_secure_token :auth_token
end
class TodoItem < ApplicationRecord
belongs_to :todo_list
validates :title, presence: true
scope :pending, -> { where(completed_at: nil) }
scope :complete, -> { where.not(completed_at: nil) }
def complete!
update_column(:completed_at, Time.current)
end
def complete?
!!completed_at
end
end
class TodoList < ApplicationRecord
has_many :todo_items
belongs_to :user
validates :title, presence: true
def formatted_title
complete? ?
"#{title} (Complete)" :
title
end
def complete?
todo_items.complete.any? && todo_items.pending.none?
end
end
<% if errors.any? %>
<ul class="errors">
<% errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<li>
(
<%= link_to 'mark complete',
todo_list_todo_item_completions_path(todo_item.todo_list, todo_item),
method: :post %>
)
&nbsp;
<%= todo_item.title %>
</li>
<h2><%= todo_list.formatted_title %></h2>
<% unless todo_list.complete? %>
<ul>
<%= render todo_list.todo_items.pending %>
</ul>
<% end %>
<%= render 'errors', errors: @errors %>
<%= render @list %>
Rails.application.routes.draw do
# ...
get :signin, to: 'signins#new', as: :signin
resources :todo_lists, only: [:index, :show, :new, :create] do
resources :todo_item_completions, only: :update
end
# ...
end
class AddCompletedAtToTodoItems < ActiveRecord::Migration[5.2]
def up
add_column :todo_items, :completed_at, :datetime
TodoItem.where(done: true).update_all(completed_at: Time.current)
remove_column :todo_items, :done
end
def down
add_column :todo_items, :done, :boolean
# We wrote scopes, but in the case that
# the developer removed them before rolling back
# migrations, prefer `where()` calls instead
TodoItem.where(completed_at: nil).update_all(done: false)
TodoItem.where.not(completed_at: nil).update_all(done: true)
change_column_null :todo_items, :done, false
change_column_default :todo_items, :done, false
remove_column :todo_items, :completed_at
end
end
class AddAuthTokenToUsers < ActiveRecord::Migration[5.2]
def up
add_column :users, :auth_token, :string
# Saving triggers an automatic callback for
# Rails' `has_secure_token` feature
User.find_each(&:save!)
# Prefering a save-bang here in the case that somehow,
# a user record isn't valid and can't save, we don't
# want to think that this migration finished and all
# users have shiny new auth tokens when they don't
change_column_null :users, :auth_token, false
end
def down
remove_column :users, :auth_token
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment