Last active
October 9, 2015 04:28
-
-
Save bf4/3438213 to your computer and use it in GitHub Desktop.
Failed attempt at a Logical ActiveRecord layer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# modeled off the Physical / Service / Logical layers | |
# advocated by http://enterpriserails.chak.org/full-text/chapter-3-organizing-with-modules | |
module Logical | |
class ARModelName | |
PHYSICAL = ARModel | |
attr_accessor :physical | |
private :physical | |
def initialize(physical) | |
@physical = physical.is_a?(PHYSICAL) ? physical : PHYSICAL.new | |
end | |
# first choice way to delegate attributes to PHYSICAL | |
# require 'forwardable' | |
# extend Forwardable | |
# def_delegators :@physical, :create, :create! | |
# def_delegators :@physical, :email, :email=, :normalized_email, :normalized_email=, :create! | |
# | |
# other possible ways to delegate attributes, for consideration | |
# delegate :email, :email=, :normalized_email, :normalized_email=, :to => @physical #active_support | |
# [:email, :normalized_email].each do |attribute| | |
# define_delegated_attribute(attribute) | |
# end | |
# | |
# Pass along the method to @physical if it responds_to? the method | |
# if so, define the method to avoid another method missing call, and call the method on @physical | |
# delegate :create!, :to => :@physical.class #active_support | |
# delegating specified PHYSICAL class methods | |
class << self | |
# delegate :create!, :to => PHYSICAL | |
[:create!, :create].each do |method| | |
define_method(method) do |*args| | |
result = PHYSICAL.send(method, *args) | |
if result.is_a?(PHYSICAL) | |
new_result = new(result) | |
new_result | |
else | |
result | |
end | |
end | |
end | |
end | |
# delegate all physical attributes, and define methods for them here as needed | |
def method_missing(method, *args, &block) | |
attribute_name = method.to_s[/^[^?!=]+/] | |
if PHYSICAL.column_names.include?(attribute_name) | |
define_delegated_attribute(attribute_name) | |
@physical.send(method, *args, &block) | |
elsif delegated_ar_methods.include?(method) | |
define_ar_method(method) | |
@physical.send(method, *args, &block) | |
else | |
super | |
end | |
end | |
def delegated_ar_methods | |
[:destroy, :save, :save!] | |
end | |
def define_ar_method(method) | |
class_eval do | |
define_method(method) do |*args,&block| | |
@physical.send(method,*args,&block) | |
end | |
end | |
end | |
def define_delegated_attribute(attribute) | |
# accessible attributes | |
unless PHYSICAL.accessible_attributes.include?(attribute.to_s) | |
class_eval do | |
define_method(attribute) do | |
@physical.attribute | |
end | |
end | |
# read only attributes | |
unless PHYSICAL.readonly_attributes.include?(attribute.to_s) | |
attribute_setter = "#{attribute}=".to_sym | |
class_eval do | |
define_method(attribute_setter) do |new_attribute| | |
@physical.send(attribute_setter, new_attribute) | |
end | |
end | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment