Skip to content

Instantly share code, notes, and snippets.

@ahoward
Created May 13, 2009 15:55
Show Gist options
  • Save ahoward/111099 to your computer and use it in GitHub Desktop.
Save ahoward/111099 to your computer and use it in GitHub Desktop.
# force rails const_missing to preload these classes
#
ActionController
ActionController::Base
ActiveRecord
ActiveRecord::Base
ActionView
ActionView::Base
ActionView::Template
ActionView::Helpers
ActiveSupport::Inflector
ActiveSupport::Inflector::Inflections
# support for using helper methods in controllers/models
#
class Helper < ActionView::Base
attr_accessor 'controller'
def initialize controller = (ActionController.current || ApplicationController.new), *modules
@controller = controller
modules.push nil if modules.empty?
modules.flatten.each do |mod|
case mod
when NilClass, :all, 'all'
extend ::ActionView::Helpers
when Module
extend mod
else
raise ArgumentError, mod.class.name
end
end
extend @controller.master_helper_module if @controller
end
def session
controller.session
end
end
# state for current controller
#
module ActionController
class Base
class << self
def current
@@current if defined?(@@current)
end
def current= controller
@@current = controller
end
end
end
def ActionController.current
ActionController::Base.current
end
def ActionController.current= controller
ActionController::Base.current = controller
end
end
# allow access to the currently rendering template
#
ActionView
ActionView::Template
class ActionView::Template
@@new ||= method(:new)
class << self
attr_accessor 'current'
def new(*a, &b)
template = allocate.instance_eval{ initialize(*a, &b); self }
ensure
ActionView::Template.current = template
end
end
end
class ActionController::Base
protected
def current_template
ActionView::Template.current
end
helper_method 'current_template'
end
class ActionController::Base
#before_filter :setup_current_controller
#after_filter :teardown_current_controller
protected
def setup_current_controller
::ActionController.current = self
end
def teardown_current_controller
::ActionController.current = nil
end
def helper &block
@helper = Helper.new(::ActionController.current || self)
block ? @helper.instance_eval(&block) : @helper
end
def self.helper_import *methods
methods.flatten.compact.each do |method|
code = <<-code
def #{ method } *a, &b
helper{ #{ method }(*a, &b) }
end
protected '#{ method }'
code
eval code
end
end
end
class ActiveRecord::Base
def helper &block
helper = Helper.new(::ActionController.current || ::ActionController::Base.new)
block ? helper.instance_eval(&block) : helper
end
end
# support for immediate (throw/catch) base rendering methods
#
class ActionController::Base
protected
def render! *a, &b
render *a, &b unless a.empty? and b.nil?
throw :render, self
end
def redirect_to! *a, &b
redirect_to *a, &b
ensure
render!
end
def redirect_to_url! *a, &b
redirect_to_url *a, &b
ensure
render!
end
def not_found! options = {}
options = {:inline => options} if String == options
options.to_options!
unless options.has_key?(:inline) or options.has_key?(:text)
options[:inline] = <<-html
<div style='padding:3em;color:#666;text-align:center;font-size:1.2em;'>
<p>
Sorry, but we could not find the page you are looking for.
</p>
<p style='color:#333'>
#{ h helper.url_for(request.request_uri) }
</p>
</div>
html
end
options[:status] ||= 404
options[:layout] ||= 'application' unless options[:layout] == false
render! options
end
def perform_action_without_filters
if action_methods.include?(action_name)
catch(:render){ send(action_name) }
default_render unless performed?
elsif respond_to? :method_missing
catch(:render){ send(:method_missing, action_name) }
default_render unless performed?
else
begin
catch(:render){ default_render }
rescue ::ActionView::MissingTemplate => e
# Was the implicit template missing, or was it another template?
if e.path == default_template_name
raise ::ActionController::UnknownAction, "No action responded to #{action_name}. Actions: #{action_methods.sort.to_sentence(:locale => :en)}", caller
else
raise e
end
end
end
end
end
# support for executing sql on the raw connection, getting back an array of
# results
#
def Rails.db(*a, &b)
connection = ActiveRecord::Base.connection.raw_connection
return connection if a.empty? and b.nil?
adapter = ActiveRecord::Base.configurations[RAILS_ENV]['adapter'].to_s
case adapter
when 'oci', 'oracle'
cursor = connection.exec *a
if b
while row = cursor.fetch;
b.call row
end
else
returning [] do |rows|
while row = cursor.fetch
rows << row
end
end
end
when 'mysql', 'postgresql', 'sqlite', 'sqlite3'
if b
connection.query(*a).each do |row|
b.call row
end
else
returning [] do |rows|
connection.query(*a).each do |row|
rows << row
end
end
end
else
raise ArgumentError, "#{ adapter } not implemented yet"
end
end
# support for class level declarations of ActiveRecord default values for
# *new* records
#
class ActiveRecord::Base
class << self
def defaults *argv, &block
const_set(:Defaults, []) unless const_defined?(:Defaults)
defaults = const_get(:Defaults)
options =
if block
argv.flatten.inject({}){|h,k| h.update k => block}
else
case argv.size
when 2
{ argv.first => argv.last }
else
argv.inject({}){|h,x| h.update x.to_hash}
end
end
options.to_options!
unless options.empty?
options.each{|k,v| defaults << [k,v]}
add_after_initialize_with_defaults! defaults
end
defaults
end
alias_method :default, :defaults
def add_after_initialize_with_defaults! defaults = {}
return if defined?(@add_after_initialize_with_defaults)
after_initialize = instance_method(:after_initialize) rescue nil
define_method(:after_initialize) do |*args|
this = self
after_initialize.bind(self).call(*args) if after_initialize
return unless new_record?
defaults.each do |key, value|
value = instance_eval(&value) if value.respond_to?(:to_proc)
write_attribute key, value
end
end
ensure
@add_after_initialize_with_defaults = true unless $!
end
end
end
# support for indexing operator
#
class ActiveRecord::Base
def self.[](*args, &block)
find(*args, &block)
end
end
# support for using named routes from the console
#
module Kernel
private
def use_named_routes_in_the_console! options = {}
include ActionController::UrlWriter
options.to_options!
options.reverse_merge! :host => 'localhost', :port => 3000
default_url_options.reverse_merge!(options)
end
end
# support for top level transactions, rollbacks, and helper
#
module Kernel
private
begin
method 'transaction'
rescue Object
def transaction(*a, &b)
ActiveRecord::Base.transaction(*a, &b)
end
end
begin
method 'rollback!'
rescue Object
def rollback!(*value)
exception = ActiveRecord::Rollback.new
unless value.empty?
exception.instance_eval do
@value = value.first
attr :value
end
end
raise exception
end
end
def helper &block
helper = Helper.new(::ActionController.current || ::ActionController::Base.new)
block ? helper.instance_eval(&block) : helper
end
end
# support for conditional excution based on rails_env
#
%w( test development production ).each do |rails_env|
eval <<-code
def Rails.#{ rails_env }? &block
if defined?(RAILS_ENV) and RAILS_ENV == '#{ rails_env }'
return( block ? block.call : true )
end
return false
end
code
end
# support ad-hoc scoped model creation
#
module ActiveRecord
def Base.scoped conditions = {}, &block
base = self
scoped =
Class.new(base).module_eval{
base.singleton_class{
define_method(:model_name){
self == base ? super : base.model_name
}
}
default_scope(:conditions => conditions)
self
}
block ? scoped.module_eval(&block) : scoped
end
end
=begin
# add a simple cached object lookup method to AR::Base
#
def Cached key, options = {}, &block
return block.call #unless production?
options.to_options!
options[:expires_in] ||= 15.minutes
return Rails.cache.fetch(key, options, &block)
end
class ActiveRecord::Base
def self.cached *args, &block
options = {}
options[:expires_in] ||= 15.minutes
block.call(options) if block
key = "#{ table_name }/#{ args.inspect.slug }"
key = ActiveSupport::Cache.expand_cache_key(key) rescue key
Cached(key, options){ find(*args) }
end
end
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment