Skip to content

Instantly share code, notes, and snippets.

View nicholasjhenry's full-sized avatar

Nicholas Henry nicholasjhenry

View GitHub Profile
@nicholasjhenry
nicholasjhenry / 1a_before_model.rb
Created July 3, 2012 14:29
ActiveRecord Refactoring with Scopes
class NewsItem
scope :news_items, where(flag_news: true).order("publish_date DESC")
scope :press_releases, lambda { where(flag_news: false).order("publish_date DESC") }
scope :news_items_homepage, where(flag_news: true, featured: true).order("publish_date DESC")
scope :press_releases_homepage, lambda { where(flag_news: false, featured: true).order("publish_date DESC") }
end
@nicholasjhenry
nicholasjhenry / gist:3548167
Created August 31, 2012 02:34
DCI for a CMS
# Data: Simple classes that encapsulate properties and associations.
# The only valid operations for a data object, is modify properties
# and associations.
class Site
attr_reader :content_items
def initialize
@content = []
end
@nicholasjhenry
nicholasjhenry / gist:3880386
Created October 12, 2012 17:28
An example of using Ruby Events Gem
# Example:
#
# submit_order = SubmitOrder.new(current_user, order)
# submit_order.call
#
# Uses RubyEvents: https://github.com/nathankleyn/ruby_events
# app/use_cases/submit_order.rb
class SubmitOrder
@nicholasjhenry
nicholasjhenry / gist:3884978
Created October 13, 2012 15:23
Thoughts on the birthday greeting kata
# As seen from the example below, you could imagine a Rails application
# "depending" on this application logic. Controllers would act as the 'main'
# instantiating collaborators to inject into the service (aka use case).
# "Note that the collaborators of the birthdayService objects are injected in
# it. Ideally domain code should never use the new operator. The new operator is
# called from outside the domain code, to set up an aggregate of objects that
# collaborate together." - http://matteo.vaccari.name/blog/archives/154
class BirthdayService
@nicholasjhenry
nicholasjhenry / engine.rb
Created November 9, 2012 21:33
Rails Engine Tips
module Refinery
module CustomFeature
class Engine < Rails::Engine
initializer "core.load_app_instance_data" do |app|
app.class.configure do
# Add migrations to the host application's path
config.paths['db/migrate'] += Refinery::Templates::Engine.paths['db/migrate'].existent
end
end
@nicholasjhenry
nicholasjhenry / gist:4070557
Created November 14, 2012 05:56
Deconstructing the Framework (Gary Bernhardt)

Design in the Small

  • Don't design a Model to be coupled to an API
  • Create a Service that talks to both your Model and the API

Service Wrapper Record

  • You have services, stateless objects that talk to the application
  • You have records, objects that talk to the database
  • And you have Wrappers, a thin class for a narrow interface to an API
@nicholasjhenry
nicholasjhenry / application_helper.rb
Created November 16, 2012 23:03
Pass block with partial in helper
module ApplicationHelper
def render_dat(&block)
content_tag(:div, class: 'nav') do
block.call
concat(@context.render('menu', foo: 'bar'))
end
end
end
@nicholasjhenry
nicholasjhenry / query_trace.rb
Created November 29, 2012 00:20
Query Trace
class QueryTrace < ActiveSupport::LogSubscriber
def sql(event)
return unless logger.debug?
debug caller.
select {|stack| stack =~ /\/app\//}.
map {|stack| stack.gsub(/^.*app\//, '')}.
join("\n")
end
@nicholasjhenry
nicholasjhenry / gist:4175484
Created November 30, 2012 12:23
Hexagonal Rails with Responder Objects
class GetItemService < Struct.new( :id, :responder )
def get
item = Item.find( id )
item ? responder.success( item ) : responder.failure( item )
end
end
class GetItemResponder < SimpleDelegator
def success( item )
@item = item
@nicholasjhenry
nicholasjhenry / gist:4175690
Created November 30, 2012 13:16
Dealing with Feature Envy
# Source: https://gist.github.com/4172391#gistcomment-610165
class Order
def complete_purchase(purchase)
purchase.complete(credit_card, amount)
end
def purchase_completed(transaction_reference)
update_attibutes(:transaction_reference => transaction_reference)
end