Class: Module
- Defined in:
- lib/monetra/active_support/dependencies.rb,
lib/monetra/active_support/core_ext/module/loading.rb,
lib/monetra/active_support/core_ext/module/aliasing.rb,
lib/monetra/active_support/core_ext/module/inclusion.rb,
lib/monetra/active_support/core_ext/module/delegation.rb,
lib/monetra/active_support/core_ext/module/attr_internal.rb,
lib/monetra/active_support/core_ext/module/introspection.rb,
lib/monetra/active_support/core_ext/module/attribute_accessors.rb
Overview
Extends the module object with module and instance accessors for class attributes, just like the native attr* accessors for instance attributes.
Instance Method Summary collapse
-
#alias_attribute(new_name, old_name) ⇒ Object
Allows you to make aliases for attributes, which includes getter, setter, and query methods.
-
#alias_method_chain(target, feature) ⇒ Object
Encapsulates the common pattern of:.
- #as_load_path ⇒ Object
-
#attr_internal_accessor(*attrs) ⇒ Object
(also: #attr_internal)
Declare attributes backed by ‘internal’ instance variables names.
-
#attr_internal_reader(*attrs) ⇒ Object
Declare an attribute reader backed by an internally-named instance variable.
-
#attr_internal_writer(*attrs) ⇒ Object
Declare an attribute writer backed by an internally-named instance variable.
-
#const_missing(class_id) ⇒ Object
Use const_missing to autoload associations so we don’t have to require_association when using single-table inheritance.
-
#delegate(*methods) ⇒ Object
Provides a delegate class method to easily expose contained objects’ methods as your own.
- #included_in_classes ⇒ Object
- #mattr_accessor(*syms) ⇒ Object
-
#mattr_reader(*syms) ⇒ Object
:nodoc:.
- #mattr_writer(*syms) ⇒ Object
-
#parent ⇒ Object
Return the module which contains this one; if this is a root module, such as
::MyModule
, then Object is returned. -
#parents ⇒ Object
Return all the parents of this module, ordered from nested outwards.
-
#rails_original_const_missing ⇒ Object
Rename the original handler so we can chain it to the new one.
Instance Method Details
#alias_attribute(new_name, old_name) ⇒ Object
Allows you to make aliases for attributes, which includes getter, setter, and query methods.
Example:
class Content < ActiveRecord::Base
# has a title attribute
end
class Email < ActiveRecord::Base
alias_attribute :subject, :title
end
e = Email.find(1)
e.title # => "Superstars"
e.subject # => "Superstars"
e.subject? # => true
e.subject = "Megastars"
e.title # => "Megastars"
50 51 52 53 54 55 56 |
# File 'lib/monetra/active_support/core_ext/module/aliasing.rb', line 50 def alias_attribute(new_name, old_name) module_eval <<-STR, __FILE__, __LINE__+1 def #{new_name}; #{old_name}; end def #{new_name}?; #{old_name}?; end def #{new_name}=(v); self.#{old_name} = v; end STR end |
#alias_method_chain(target, feature) ⇒ Object
Encapsulates the common pattern of:
alias_method :foo_without_feature, :foo
alias_method :foo, :foo_with_feature
With this, you simply do:
alias_method_chain :foo, :feature
And both aliases are set up for you.
Query and bang methods (foo?, foo!) keep the same punctuation:
alias_method_chain :foo?, :feature
is equivalent to
alias_method :foo_without_feature?, :foo?
alias_method :foo?, :foo_with_feature?
so you can safely chain foo, foo?, and foo! with the same feature.
23 24 25 26 27 28 29 |
# File 'lib/monetra/active_support/core_ext/module/aliasing.rb', line 23 def alias_method_chain(target, feature) # Strip out punctuation on predicates or bang methods since # e.g. target?_without_feature is not a valid method name. aliased_target, punctuation = target.to_s.sub(/([?!])$/, ''), $1 alias_method "#{aliased_target}_without_#{feature}#{punctuation}", target alias_method target, "#{aliased_target}_with_#{feature}#{punctuation}" end |
#as_load_path ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 |
# File 'lib/monetra/active_support/core_ext/module/loading.rb', line 2 def as_load_path if self == Object || self == Kernel '' elsif is_a? Class parent == self ? '' : parent.as_load_path else name.split('::').collect do |word| word.underscore end * '/' end end |
#attr_internal_accessor(*attrs) ⇒ Object Also known as: attr_internal
Declare attributes backed by ‘internal’ instance variables names.
17 18 19 20 |
# File 'lib/monetra/active_support/core_ext/module/attr_internal.rb', line 17 def attr_internal_accessor(*attrs) attr_internal_reader *attrs attr_internal_writer *attrs end |
#attr_internal_reader(*attrs) ⇒ Object
Declare an attribute reader backed by an internally-named instance variable.
3 4 5 6 7 |
# File 'lib/monetra/active_support/core_ext/module/attr_internal.rb', line 3 def attr_internal_reader(*attrs) attrs.each do |attr| module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end" end end |
#attr_internal_writer(*attrs) ⇒ Object
Declare an attribute writer backed by an internally-named instance variable.
10 11 12 13 14 |
# File 'lib/monetra/active_support/core_ext/module/attr_internal.rb', line 10 def attr_internal_writer(*attrs) attrs.each do |attr| module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end" end end |
#const_missing(class_id) ⇒ Object
Use const_missing to autoload associations so we don’t have to require_association when using single-table inheritance.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/monetra/active_support/dependencies.rb', line 99 def const_missing(class_id) file_name = class_id.to_s.demodulize.underscore file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}" begin require_dependency(file_path) brief_name = self == Object ? '' : "#{name}::" raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id) return const_get(class_id) rescue MissingSourceFile => e # Re-raise the error if it does not concern the file we were trying to load. raise unless e.is_missing? file_path # Look for a directory in the load path that we ought to load. if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" } mod = Module.new const_set class_id, mod # Create the new module return mod end # Attempt to access the name from the parent, unless we don't have a valid # parent, or the constant is already defined in the parent. If the latter # is the case, then we are being queried via self::class_id, and we should # avoid returning the constant from the parent if possible. if parent && parent != self && ! parents.any? { |p| p.const_defined?(class_id) } suppress(NameError) do return parent.send(:const_missing, class_id) end end qualified_name = Dependencies.constant_path_for self, class_id raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e) end end |
#delegate(*methods) ⇒ Object
Provides a delegate class method to easily expose contained objects’ methods as your own. Pass one or more methods (specified as symbols or strings) and the name of the target object as the final :to option (also a symbol or string). At least one method and the :to option are required.
Delegation is particularly useful with Active Record associations:
class Greeter < ActiveRecord::Base
def hello() "hello" end
def goodbye() "goodbye" end
end
class Foo < ActiveRecord::Base
belongs_to :greeter
delegate :hello, :to => :greeter
end
Foo.new.hello # => "hello"
Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>
Multiple delegates to the same target are allowed:
class Foo < ActiveRecord::Base
delegate :hello, :goodbye, :to => :greeter
end
Foo.new.goodbye # => "goodbye"
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/monetra/active_support/core_ext/module/delegation.rb', line 27 def delegate(*methods) = methods.pop unless .is_a?(Hash) && to = [:to] raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)." end methods.each do |method| module_eval(<<-EOS, "(__DELEGATION__)", 1) def #{method}(*args, &block) #{to}.__send__(#{method.inspect}, *args, &block) end EOS end end |
#included_in_classes ⇒ Object
2 3 4 5 6 7 8 9 10 |
# File 'lib/monetra/active_support/core_ext/module/inclusion.rb', line 2 def included_in_classes classes = [] ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) } classes.reverse.inject([]) do |unique_classes, klass| unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s) unique_classes end end |
#mattr_accessor(*syms) ⇒ Object
40 41 42 43 |
# File 'lib/monetra/active_support/core_ext/module/attribute_accessors.rb', line 40 def mattr_accessor(*syms) mattr_reader(*syms) mattr_writer(*syms) end |
#mattr_reader(*syms) ⇒ Object
:nodoc:
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/monetra/active_support/core_ext/module/attribute_accessors.rb', line 4 def mattr_reader(*syms) syms.each do |sym| class_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym} @@#{sym} end def #{sym} @@#{sym} end EOS end end |
#mattr_writer(*syms) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/monetra/active_support/core_ext/module/attribute_accessors.rb', line 22 def mattr_writer(*syms) syms.each do |sym| class_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym}=(obj) @@#{sym} = obj end def #{sym}=(obj) @@#{sym} = obj end EOS end end |
#parent ⇒ Object
Return the module which contains this one; if this is a root module, such as ::MyModule
, then Object is returned.
4 5 6 7 |
# File 'lib/monetra/active_support/core_ext/module/introspection.rb', line 4 def parent parent_name = name.split('::')[0..-2] * '::' parent_name.empty? ? Object : parent_name.constantize end |
#parents ⇒ Object
Return all the parents of this module, ordered from nested outwards. The receiver is not contained within the result.
11 12 13 14 15 16 17 18 19 20 |
# File 'lib/monetra/active_support/core_ext/module/introspection.rb', line 11 def parents parents = [] parts = name.split('::')[0..-2] until parts.empty? parents << (parts * '::').constantize parts.pop end parents << Object unless parents.include? Object parents end |
#rails_original_const_missing ⇒ Object
Rename the original handler so we can chain it to the new one
95 |
# File 'lib/monetra/active_support/dependencies.rb', line 95 alias :rails_original_const_missing :const_missing |