Skip to content

Instantly share code, notes, and snippets.

@JAMSUPREME
Last active July 19, 2016 22:27
Show Gist options
  • Save JAMSUPREME/c2e9d9bacab5c940215d802e760b5c03 to your computer and use it in GitHub Desktop.
Save JAMSUPREME/c2e9d9bacab5c940215d802e760b5c03 to your computer and use it in GitHub Desktop.
All the bad things
# This is an example of a controller that is doing too many things.
# It has a lot of code, and as new features get added this controller continues to bloat
class Admin::AdminController < ApplicationController
include ApprovalConcern
before_action :redirect_unless_admin
def index
render 'index'
end
def menu
render 'upload_menu'
end
def upload_menu
new_menu_path = params[:new_menu]
if new_menu_path.respond_to?(:read)
new_menu = new_menu_path.read
elsif new_menu_path.respond_to?(:path)
new_menu = File.read(new_menu_path.path)
else
raise "Bad file!"
end
IO.write(Rails.root + 'app/assets/images/menu.jpg', new_menu, mode: 'w+', encoding: 'ASCII-8BIT')
render 'upload_menu'
end
def approve_events
@proposed_events = events_requiring_approval
render 'approve-events'
end
def review_event
@proposed_event = ProposedEvent.find(params[:id])
render 'review-event'
end
def complete_review_event
if (params[:approve])
proposed_event = ProposedEvent.find(params[:id])
approve_event(proposed_event)
else
ApprovalMailer.reject.deliver_later
end
redirect_to admin_approve_events_path
end
def important_events
render 'important-events'
end
def redirect_unless_admin
redirect_to '/login?forbidden=t' unless session['logged-in'] == true
end
end
# In a stroke of brilliance we attempt to solve all our bloat problems by pulling the code into modules.
# Unfortunately this just makes our controller bloated AND hard to read.
class Admin::AdminController < ApplicationController
include ApprovalConcern
# Glorious new includes
include AdminRedirectConcern
include MenuConcern
include ReviewConcern
include MailerConcern
include TallDarkAndMysteriousConcern
end
<!-- In this case, I've done some formatting directly in the view -->
<table class="table table-striped">
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Tentative date</th>
<th>Desired fee</th>
</tr>
</thead>
<tbody>
<% contiguous_events(@proposed_event).each do |proposed_event| %>
<tr>
<td><%= proposed_event.title %></td>
<td><%= proposed_event.description %></td>
<td><%= proposed_event.tentative_date %></td>
<td><%= currency_format(proposed_event.desired_fee) %></td>
<td><%= number_to_currency(proposed_event.desired_fee, unit: "@", separator: ",", delimiter: " ") %></td>
</tr>
<% end %>
</tbody>
</table>
#
# In concert with the above example of formatting directly in a view,
# I'm also putting some formatting in other spots so I can reuse it!
#
# A helper for proposed events with currency formatting
module ProposedEventsHelper
def currency_format(currency)
number_to_currency(currency, unit: "@", separator: ",", delimiter: " ")
end
end
# I've added front-end formatting into my model, as well
class Event < ActiveRecord::Base
include ActionView::Helpers::NumberHelper
def ticket_cost_enUS
number_to_currency(desired_fee, unit: "$", separator: ".", delimiter: ",")
end
def ticket_cost_enGB
number_to_currency(desired_fee, unit: "€", separator: ".", delimiter: " ")
end
end
#
# Here we explore several ways to obfuscate your code by placing retrieval helpers in many different locations.
# These are all "valid", and thus at a glance none of them may look out of place or wrong
#
class ProposedEvent < ActiveRecord::Base
# Several scopes
scope :unapproved, -> { where(approved_date: nil) }
scope :expensive, -> { where('desired_fee > 1000') }
scope :more_expensive_than, ->(cost) { where('desired_fee > ?', cost) }
# helper to get only January events
def jan_events
where("strftime('%m', tentative_date) = 01")
end
end
# This is a controller specific to "approval" things, but it will also want to retrieve events in special ways
# It may also have lots of unrelated things in it
module ApprovalConcern
extend ActiveSupport::Concern
def events_requiring_approval
ProposedEvent.all.where(approved_date: nil)
end
def expensive_events
ProposedEvent.expensive
end
# sqlite specific syntax here
def upcoming_events
ProposedEvent.all.where(approved_date: !nil).where("julianday(tentative_date) - julianday('now') BETWEEN 0 AND 10")
end
def other_stuff()
# other stuff and methods would go here
end
end
# Who needs a helper when I can just put everything in the mighty controller!?
class ProposedEventsController < ApplicationController
# Use the model directly
def index
@events = ProposedEvent.where(approved_date: !nil)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment