Skip to content

Instantly share code, notes, and snippets.

@boof
Created December 14, 2008 08:07
Show Gist options
  • Save boof/35652 to your computer and use it in GitHub Desktop.
Save boof/35652 to your computer and use it in GitHub Desktop.
Polymorphisms for polymorphic resource controllers
class Polymorphism
attr_reader :base, :ctrl, :path
@@polymorph = ''
@@polymorphs = ''
cattr_reader :polymorph, :polymorphs
def self.set_polymorph(polymorph)
@@polymorph = "#{ polymorph }"
@@polymorphs = "#{ polymorph }".pluralize
end
@@namespace = ''
cattr_reader :namespace
def self.set_namespace(namespace)
@@namespace = namespace
end
def self.inherited(base)
if @@polymorph.blank?
basename = base.name.demodulize
# strip "Polymorphism"
basename = basename[0..-13] if basename[-12, 12] == 'Polymorphism'
base.set_polymorph basename.underscore
end
end
def initialize(ctrl)
@ctrl = ctrl
@key = ctrl.params.keys.find { |key| key =~ /(.+)_id$/ }
@base = $~[1]
@path = Path.new self
end
def proxy_target_id
@ctrl.params[:id].to_i
end
def proxy_target_class
@proxy_target_class ||= polymorph.classify.constantize
end
def proxy_owner_id
@ctrl.params[@key].to_i
end
def proxy_owner_class
@proxy_owner_class ||= base.classify.constantize
end
def association_reflection
@association_reflection ||=
proxy_owner_class.reflect_on_association(polymorph.to_sym) ||
proxy_owner_class.reflect_on_association(polymorphs.to_sym)
end
def singular?
association_reflection.macro == :has_one
end
def plural?()
association_reflection.macro == :has_many
end
def proxy_owner
proxy_owner_class.find proxy_owner_id
end
def proxy
proxy_owner.send association_reflection.name
end
def proxy_target
proxy_target_class.find proxy_target_id
end
def proxy_collection
proxy_target_class.find :all, :conditions => {
"#{ association_reflection.as }_type" => proxy_owner_class.base_class.name,
"#{ association_reflection.as }_id" => proxy_owner_id
}
end
class Path
def initialize(polymorphism)
@polymorphism = polymorphism
end
def index
generate nil, polymorphs
rescue
generate nil, polymorph
end
def show(proxy_target = @polymorphism.proxy_target)
generate nil, proxy_target
end
def new
generate :new, proxy_target_class.new
end
def edit(proxy_target = @polymorphism.proxy_target)
generate :edit, proxy_target
end
def collection(action, *args)
prefix = ''
prefix << "#{ action }_" if action
prefix << "#{ namespace }_" if namespace
ctrl.send :"#{ prefix }#{ base }_#{ polymorphs }_path",
proxy_owner, *args
end
def generate(action = nil, *args)
action &&= "#{ action }_"
ctrl.send :"#{ action }polymorphic_path",
[namespace, proxy_owner, *args].compact
end
protected
def base
@polymorphism.base
end
def polymorph
@polymorphism.polymorph
end
def polymorphs
@polymorphism.polymorphs
end
def namespace
@polymorphism.namespace
end
def ctrl
@polymorphism.ctrl
end
def proxy_owner
@polymorphism.proxy_owner
end
def proxy_target_class
@polymorphism.proxy_target_class
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment