/
class_methods.rb
124 lines (111 loc) · 3 KB
/
class_methods.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
module Virtus
# Class methods that are added when you include Virtus
module ClassMethods
include Extensions
# Hook called when module is extended
#
# @param [Class] descendant
#
# @return [undefined]
#
# @api private
def self.extended(descendant)
super
descendant.module_eval do
extend DescendantsTracker
virtus_setup_attributes_accessor_module
end
end
private_class_method :extended
# Returns all the attributes defined on a Class
#
# @example
# class User
# include Virtus
#
# attribute :name, String
# attribute :age, Integer
# end
#
# User.attributes # =>
#
# TODO: implement inspect so the output is not cluttered - solnic
#
# @return [AttributeSet]
#
# @api public
def attribute_set
return @attribute_set if defined?(@attribute_set)
superclass = self.superclass
method = __method__
parent = superclass.public_send(method) if superclass.respond_to?(method)
@attribute_set = AttributeSet.new(parent)
end
# @see Virtus::ClassMethods.attribute_set
#
# @deprecated
#
# @api public
def attributes
warn "#{self}.attributes is deprecated. Use #{self}.attribute_set instead: #{caller.first}"
attribute_set
end
protected
# Set up the anonymous module which will host Attribute accessor methods
#
# @return [self]
#
# @api private
def virtus_setup_attributes_accessor_module
@virtus_attributes_accessor_module = AttributesAccessor.new(inspect)
include @virtus_attributes_accessor_module
end
private
# Setup descendants' own Attribute-accessor-method-hosting modules
#
# Descendants inherit Attribute accessor methods via Ruby's inheritance
# mechanism: Attribute accessor methods are defined in a module included
# in a superclass. Attributes defined on descendants add methods to the
# descendant's Attributes accessor module, leaving the superclass's method
# table unaffected.
#
# @param [Class] descendant
#
# @return [undefined]
#
# @api private
def inherited(descendant)
super
descendant.virtus_setup_attributes_accessor_module
end
# Hooks into const missing process to determine types of attributes
#
# @param [String] name
#
# @return [Class]
#
# @api private
def const_missing(name)
Attribute.determine_type(name) or super
end
# Add the attribute to the class' and descendants' attributes
#
# @param [Attribute]
#
# @return [undefined]
#
# @api private
def virtus_add_attribute(attribute)
super
descendants.each { |descendant| descendant.attribute_set.reset }
end
# The list of allowed public methods
#
# @return [Array<String>]
#
# @api private
def allowed_methods
public_instance_methods.map(&:to_s)
end
end # module ClassMethods
end # module Virtus