gorillib 0.1.11 → 0.4.0pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +1 -2
- data/.yardopts +9 -0
- data/{CHANGELOG.textile → CHANGELOG.md} +35 -9
- data/Gemfile +21 -14
- data/Guardfile +19 -0
- data/{LICENSE.textile → LICENSE.md} +43 -29
- data/README.md +47 -52
- data/Rakefile +31 -30
- data/TODO.md +32 -0
- data/VERSION +1 -1
- data/examples/builder/ironfan.rb +133 -0
- data/examples/model/simple.rb +17 -0
- data/gorillib.gemspec +106 -86
- data/lib/alt/kernel/call_stack.rb +56 -0
- data/lib/gorillib/array/wrap.rb +53 -0
- data/lib/gorillib/base.rb +3 -3
- data/lib/gorillib/builder/field.rb +5 -0
- data/lib/gorillib/builder.rb +260 -0
- data/lib/gorillib/collection/has_collection.rb +31 -0
- data/lib/gorillib/collection.rb +129 -0
- data/lib/gorillib/configurable.rb +28 -0
- data/lib/gorillib/datetime/{flat.rb → to_flat.rb} +0 -0
- data/lib/gorillib/exception/confidence.rb +17 -0
- data/lib/gorillib/exception/raisers.rb +78 -0
- data/lib/gorillib/hash/mash.rb +202 -0
- data/lib/gorillib/hashlike/slice.rb +53 -19
- data/lib/gorillib/hashlike.rb +5 -3
- data/lib/gorillib/io/system_helpers.rb +30 -0
- data/lib/gorillib/logger/log.rb +18 -0
- data/lib/gorillib/metaprogramming/concern.rb +124 -0
- data/lib/gorillib/model/active_model_conversion.rb +68 -0
- data/lib/gorillib/model/active_model_naming.rb +87 -0
- data/lib/gorillib/model/active_model_shim.rb +33 -0
- data/lib/gorillib/model/base.rb +341 -0
- data/lib/gorillib/model/defaults.rb +71 -0
- data/lib/gorillib/model/errors.rb +14 -0
- data/lib/gorillib/model/factories.rb +372 -0
- data/lib/gorillib/model/field.rb +146 -0
- data/lib/gorillib/model/named_schema.rb +53 -0
- data/lib/gorillib/{struct/hashlike_iteration.rb → model/overlay.rb} +0 -0
- data/lib/gorillib/model/record_schema.rb +9 -0
- data/lib/gorillib/model/serialization.rb +23 -0
- data/lib/gorillib/model/validate.rb +22 -0
- data/lib/gorillib/model.rb +23 -0
- data/lib/gorillib/pathname.rb +78 -0
- data/lib/gorillib/{serialization.rb → serialization/to_wire.rb} +0 -0
- data/lib/gorillib/some.rb +11 -9
- data/lib/gorillib/string/constantize.rb +21 -14
- data/lib/gorillib/string/inflections.rb +6 -76
- data/lib/gorillib/string/inflector.rb +192 -0
- data/lib/gorillib/string/simple_inflector.rb +267 -0
- data/lib/gorillib/type/extended.rb +52 -0
- data/lib/gorillib/utils/capture_output.rb +28 -0
- data/lib/gorillib/utils/console.rb +131 -0
- data/lib/gorillib/utils/nuke_constants.rb +9 -0
- data/lib/gorillib/utils/stub_module.rb +33 -0
- data/spec/examples/builder/ironfan_spec.rb +37 -0
- data/spec/extlib/hash_spec.rb +64 -0
- data/spec/extlib/mash_spec.rb +312 -0
- data/spec/{array → gorillib/array}/compact_blank_spec.rb +2 -2
- data/spec/{array → gorillib/array}/extract_options_spec.rb +2 -2
- data/spec/gorillib/builder_spec.rb +187 -0
- data/spec/gorillib/collection_spec.rb +20 -0
- data/spec/gorillib/configurable_spec.rb +62 -0
- data/spec/{datetime → gorillib/datetime}/parse_spec.rb +3 -3
- data/spec/{datetime/flat_spec.rb → gorillib/datetime/to_flat_spec.rb} +4 -4
- data/spec/{enumerable → gorillib/enumerable}/sum_spec.rb +5 -5
- data/spec/gorillib/exception/raisers_spec.rb +60 -0
- data/spec/{hash → gorillib/hash}/compact_spec.rb +2 -2
- data/spec/{hash → gorillib/hash}/deep_compact_spec.rb +3 -3
- data/spec/{hash → gorillib/hash}/deep_merge_spec.rb +2 -2
- data/spec/{hash → gorillib/hash}/keys_spec.rb +2 -2
- data/spec/{hash → gorillib/hash}/reverse_merge_spec.rb +2 -2
- data/spec/{hash → gorillib/hash}/slice_spec.rb +2 -2
- data/spec/{hash → gorillib/hash}/zip_spec.rb +2 -2
- data/spec/{hashlike → gorillib/hashlike}/behave_same_as_hash_spec.rb +6 -3
- data/spec/{hashlike → gorillib/hashlike}/deep_hash_spec.rb +2 -2
- data/spec/{hashlike → gorillib/hashlike}/hashlike_behavior_spec.rb +32 -30
- data/spec/{hashlike → gorillib/hashlike}/hashlike_via_accessors_spec.rb +3 -3
- data/spec/{hashlike_spec.rb → gorillib/hashlike_spec.rb} +3 -3
- data/spec/{logger → gorillib/logger}/log_spec.rb +2 -2
- data/spec/{metaprogramming → gorillib/metaprogramming}/aliasing_spec.rb +3 -3
- data/spec/{metaprogramming → gorillib/metaprogramming}/class_attribute_spec.rb +3 -3
- data/spec/{metaprogramming → gorillib/metaprogramming}/delegation_spec.rb +3 -3
- data/spec/{metaprogramming → gorillib/metaprogramming}/singleton_class_spec.rb +3 -3
- data/spec/gorillib/model/record/defaults_spec.rb +108 -0
- data/spec/gorillib/model/record/factories_spec.rb +321 -0
- data/spec/gorillib/model/record/overlay_spec.rb +46 -0
- data/spec/gorillib/model/serialization_spec.rb +48 -0
- data/spec/gorillib/model_spec.rb +281 -0
- data/spec/{numeric → gorillib/numeric}/clamp_spec.rb +2 -2
- data/spec/{object → gorillib/object}/blank_spec.rb +2 -2
- data/spec/{object → gorillib/object}/try_dup_spec.rb +2 -2
- data/spec/{object → gorillib/object}/try_spec.rb +3 -2
- data/spec/gorillib/pathname_spec.rb +114 -0
- data/spec/{string → gorillib/string}/constantize_spec.rb +2 -2
- data/spec/{string → gorillib/string}/human_spec.rb +2 -2
- data/spec/{string → gorillib/string}/inflections_spec.rb +4 -3
- data/spec/{string → gorillib/string}/inflector_test_cases.rb +0 -0
- data/spec/{string → gorillib/string}/truncate_spec.rb +4 -10
- data/spec/gorillib/type/extended_spec.rb +120 -0
- data/spec/gorillib/utils/capture_output_spec.rb +71 -0
- data/spec/spec_helper.rb +8 -11
- data/spec/support/gorillib_test_helpers.rb +66 -0
- data/spec/support/hashlike_fuzzing_helper.rb +31 -33
- data/spec/support/hashlike_helper.rb +3 -3
- data/spec/support/model_test_helpers.rb +81 -0
- data/spec/support/shared_examples/included_module.rb +20 -0
- metadata +177 -158
- data/lib/gorillib/array/average.rb +0 -13
- data/lib/gorillib/array/sorted_median.rb +0 -11
- data/lib/gorillib/array/sorted_percentile.rb +0 -11
- data/lib/gorillib/array/sorted_sample.rb +0 -12
- data/lib/gorillib/dsl_object.rb +0 -64
- data/lib/gorillib/hash/indifferent_access.rb +0 -207
- data/lib/gorillib/hash/tree_merge.rb +0 -4
- data/lib/gorillib/hashlike/tree_merge.rb +0 -49
- data/lib/gorillib/metaprogramming/cattr_accessor.rb +0 -79
- data/lib/gorillib/metaprogramming/mattr_accessor.rb +0 -61
- data/lib/gorillib/receiver/active_model_shim.rb +0 -32
- data/lib/gorillib/receiver/acts_as_hash.rb +0 -195
- data/lib/gorillib/receiver/acts_as_loadable.rb +0 -42
- data/lib/gorillib/receiver/locale/en.yml +0 -27
- data/lib/gorillib/receiver/tree_diff.rb +0 -74
- data/lib/gorillib/receiver/validations.rb +0 -30
- data/lib/gorillib/receiver.rb +0 -402
- data/lib/gorillib/receiver_model.rb +0 -21
- data/lib/gorillib/struct/acts_as_hash.rb +0 -108
- data/notes/fancy_hashes_and_receivers.textile +0 -120
- data/notes/hash_rdocs.textile +0 -97
- data/spec/array/average_spec.rb +0 -24
- data/spec/array/sorted_median_spec.rb +0 -18
- data/spec/array/sorted_percentile_spec.rb +0 -24
- data/spec/array/sorted_sample_spec.rb +0 -28
- data/spec/dsl_object_spec.rb +0 -99
- data/spec/hash/indifferent_access_spec.rb +0 -391
- data/spec/metaprogramming/cattr_accessor_spec.rb +0 -43
- data/spec/metaprogramming/mattr_accessor_spec.rb +0 -45
- data/spec/receiver/acts_as_hash_spec.rb +0 -295
- data/spec/receiver_spec.rb +0 -551
- data/spec/struct/acts_as_hash_fuzz_spec.rb +0 -71
- data/spec/struct/acts_as_hash_spec.rb +0 -422
@@ -1,207 +0,0 @@
|
|
1
|
-
require 'gorillib/hash/keys'
|
2
|
-
|
3
|
-
# This class has dubious semantics and we only have it so that
|
4
|
-
# people can write <tt>params[:key]</tt> instead of <tt>params['key']</tt>
|
5
|
-
# and they get the same value for both keys.
|
6
|
-
|
7
|
-
module Gorillib
|
8
|
-
class HashWithIndifferentAccess < Hash
|
9
|
-
def extractable_options?
|
10
|
-
true
|
11
|
-
end
|
12
|
-
|
13
|
-
def with_indifferent_access
|
14
|
-
dup
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(constructor = {})
|
18
|
-
if constructor.is_a?(Hash)
|
19
|
-
super()
|
20
|
-
update(constructor)
|
21
|
-
else
|
22
|
-
super(constructor)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def default(key = nil)
|
27
|
-
if include?(converted = convert_key(key))
|
28
|
-
self[converted]
|
29
|
-
else
|
30
|
-
super
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.new_from_hash_copying_default(hash)
|
35
|
-
new(hash).tap do |new_hash|
|
36
|
-
new_hash.default = hash.default
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
alias_method(:regular_writer, :[]=) unless method_defined?(:regular_writer)
|
41
|
-
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
42
|
-
|
43
|
-
# Assigns a new value to the hash:
|
44
|
-
#
|
45
|
-
# hash = HashWithIndifferentAccess.new
|
46
|
-
# hash[:key] = "value"
|
47
|
-
#
|
48
|
-
def []=(key, value)
|
49
|
-
regular_writer(convert_key(key), convert_value(value))
|
50
|
-
end
|
51
|
-
|
52
|
-
alias_method :store, :[]=
|
53
|
-
|
54
|
-
# Updates the instantized hash with values from the second:
|
55
|
-
#
|
56
|
-
# hash_1 = HashWithIndifferentAccess.new
|
57
|
-
# hash_1[:key] = "value"
|
58
|
-
#
|
59
|
-
# hash_2 = HashWithIndifferentAccess.new
|
60
|
-
# hash_2[:key] = "New Value!"
|
61
|
-
#
|
62
|
-
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
|
63
|
-
#
|
64
|
-
def update(other_hash)
|
65
|
-
raise TypeError, "can't convert #{other_hash.nil? ? 'nil' : other_hash.class} into Hash" unless other_hash.respond_to?(:each_pair)
|
66
|
-
if other_hash.is_a? HashWithIndifferentAccess
|
67
|
-
super(other_hash)
|
68
|
-
else
|
69
|
-
other_hash.each_pair{|key, value| regular_writer(convert_key(key), convert_value(value)) }
|
70
|
-
self
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
alias_method :merge!, :update
|
75
|
-
|
76
|
-
# Checks the hash for a key matching the argument passed in:
|
77
|
-
#
|
78
|
-
# hash = HashWithIndifferentAccess.new
|
79
|
-
# hash["key"] = "value"
|
80
|
-
# hash.key? :key # => true
|
81
|
-
# hash.key? "key" # => true
|
82
|
-
#
|
83
|
-
def key?(key)
|
84
|
-
super(convert_key(key))
|
85
|
-
end
|
86
|
-
|
87
|
-
alias_method :include?, :key?
|
88
|
-
alias_method :has_key?, :key?
|
89
|
-
alias_method :member?, :key?
|
90
|
-
|
91
|
-
# Fetches the value for the specified key, same as doing hash[key]
|
92
|
-
def fetch(key, *extras)
|
93
|
-
super(convert_key(key), *extras)
|
94
|
-
end
|
95
|
-
|
96
|
-
# Returns an array of the values at the specified indices:
|
97
|
-
#
|
98
|
-
# hash = HashWithIndifferentAccess.new
|
99
|
-
# hash[:a] = "x"
|
100
|
-
# hash[:b] = "y"
|
101
|
-
# hash.values_at("a", "b") # => ["x", "y"]
|
102
|
-
#
|
103
|
-
def values_at(*indices)
|
104
|
-
indices.collect {|key| self[convert_key(key)]}
|
105
|
-
end
|
106
|
-
|
107
|
-
# Returns an exact copy of the hash.
|
108
|
-
def dup
|
109
|
-
self.class.new(self).tap do |new_hash|
|
110
|
-
new_hash.default = default
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
|
115
|
-
# Does not overwrite the existing hash.
|
116
|
-
def merge(hash)
|
117
|
-
self.dup.update(hash)
|
118
|
-
end
|
119
|
-
|
120
|
-
# Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
|
121
|
-
# This overloaded definition prevents returning a regular hash, if reverse_merge is called on a <tt>HashWithDifferentAccess</tt>.
|
122
|
-
def reverse_merge(other_hash)
|
123
|
-
super self.class.new_from_hash_copying_default(other_hash)
|
124
|
-
end
|
125
|
-
|
126
|
-
def reverse_merge!(other_hash)
|
127
|
-
replace(reverse_merge( other_hash ))
|
128
|
-
end
|
129
|
-
|
130
|
-
# Removes a specified key from the hash.
|
131
|
-
def delete(key)
|
132
|
-
super(convert_key(key))
|
133
|
-
end
|
134
|
-
|
135
|
-
def stringify_keys!; self end
|
136
|
-
def stringify_keys; dup end
|
137
|
-
undef_method :symbolize_keys! if method_defined?(:symbolize_keys!)
|
138
|
-
def symbolize_keys; to_hash.symbolize_keys end
|
139
|
-
def to_options!; self end
|
140
|
-
|
141
|
-
# Convert to a Hash with String keys.
|
142
|
-
def to_hash
|
143
|
-
Hash.new(default).merge!(self)
|
144
|
-
end
|
145
|
-
|
146
|
-
def assoc key
|
147
|
-
key = convert_key(key)
|
148
|
-
return unless has_key?(key)
|
149
|
-
[key, self[key]]
|
150
|
-
end
|
151
|
-
|
152
|
-
def rassoc val
|
153
|
-
key = key(val) or return
|
154
|
-
[key, self[key]]
|
155
|
-
end
|
156
|
-
|
157
|
-
protected
|
158
|
-
def convert_key(key)
|
159
|
-
key.kind_of?(Symbol) ? key.to_s : key
|
160
|
-
end
|
161
|
-
|
162
|
-
def convert_value(value)
|
163
|
-
if value.is_a? Hash
|
164
|
-
value.nested_under_indifferent_access
|
165
|
-
elsif value.is_a?(Array)
|
166
|
-
value.dup.replace(value.map{|e| convert_value(e) })
|
167
|
-
else
|
168
|
-
value
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
end
|
174
|
-
|
175
|
-
module Gorillib
|
176
|
-
class HashWithIndifferentSymbolKeys < Gorillib::HashWithIndifferentAccess
|
177
|
-
|
178
|
-
def convert_key key
|
179
|
-
return key if key.is_a?(Fixnum)
|
180
|
-
key.respond_to?(:to_sym) ? key.to_sym : key
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
class Hash
|
186
|
-
|
187
|
-
# Returns an +ActiveSupport::HashWithIndifferentAccess+ out of its receiver:
|
188
|
-
#
|
189
|
-
# {:a => 1}.with_indifferent_access["a"] # => 1
|
190
|
-
#
|
191
|
-
def with_indifferent_access
|
192
|
-
Gorillib::HashWithIndifferentAccess.new_from_hash_copying_default(self)
|
193
|
-
end
|
194
|
-
|
195
|
-
# Called when object is nested under an object that receives
|
196
|
-
# #with_indifferent_access. This method with be called on the current object
|
197
|
-
# by the enclosing object and is aliased to #with_indifferent_access by
|
198
|
-
# default. Subclasses of Hash may overwrite this method to return +self+ if
|
199
|
-
# converting to an +ActiveSupport::HashWithIndifferentAccess+ would not be
|
200
|
-
# desirable.
|
201
|
-
#
|
202
|
-
# b = {:b => 1}
|
203
|
-
# {:a => b}.with_indifferent_access["a"] # calls b.nested_under_indifferent_access
|
204
|
-
#
|
205
|
-
alias nested_under_indifferent_access with_indifferent_access
|
206
|
-
end
|
207
|
-
|
@@ -1,49 +0,0 @@
|
|
1
|
-
module Gorillib
|
2
|
-
module Hashlike
|
3
|
-
module TreeMerge
|
4
|
-
|
5
|
-
# Recursively merges hashlike objects
|
6
|
-
#
|
7
|
-
# For each key in keys,
|
8
|
-
# * if block_given? and yield(key,self_val,other_val) returns non-nil, set that
|
9
|
-
# * if self is missing value for key, receive the attribute.
|
10
|
-
# * if self's attribute is an Array, append to it.
|
11
|
-
# * if self's value responds to tree_merge!, deep merge it.
|
12
|
-
# * if self's value responds_to merge!, merge! it.
|
13
|
-
# * otherwise, receive the value from other_hash
|
14
|
-
#
|
15
|
-
def tree_merge!(other_hash)
|
16
|
-
return self if other_hash.blank?
|
17
|
-
[self.keys, other_hash.keys].flatten.uniq.each do |key|
|
18
|
-
# get other's val if any
|
19
|
-
if other_hash.has_key?(key.to_sym) then other_val = other_hash[key.to_sym]
|
20
|
-
elsif other_hash.has_key?(key.to_s) then other_val = other_hash[key.to_s]
|
21
|
-
else next ; end
|
22
|
-
# get self val if any
|
23
|
-
self_val = self[key]
|
24
|
-
# get block resolved result if any
|
25
|
-
if block_given? && yield(key, self_val, other_val)
|
26
|
-
next
|
27
|
-
end
|
28
|
-
# p ['hash tree_merge', key, self_val.respond_to?(:tree_merge!), self_val, '***************', other_val]
|
29
|
-
#
|
30
|
-
case
|
31
|
-
when other_val.nil? then next
|
32
|
-
when (not has_key?(key)) then self[key] = other_val
|
33
|
-
when self_val.is_a?(Array) then self[key] += other_val
|
34
|
-
when self_val.respond_to?(:tree_merge!) then self[key] = self_val.tree_merge!(other_val)
|
35
|
-
when self_val.respond_to?(:merge!) then self[key] = self_val.merge!(other_val)
|
36
|
-
else self[key] = other_val
|
37
|
-
end
|
38
|
-
end
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
class Hash
|
48
|
-
include Gorillib::Hashlike::TreeMerge
|
49
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'gorillib/array/extract_options'
|
2
|
-
|
3
|
-
# Extends the class object with class and instance accessors for class attributes,
|
4
|
-
# just like the native attr* accessors for instance attributes.
|
5
|
-
#
|
6
|
-
# Note that unlike +class_attribute+, if a subclass changes the value then that would
|
7
|
-
# also change the value for parent class. Similarly if parent class changes the value
|
8
|
-
# then that would change the value of subclasses too.
|
9
|
-
#
|
10
|
-
# class Person
|
11
|
-
# cattr_accessor :hair_colors
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# Person.hair_colors = [:brown, :black, :blonde, :red]
|
15
|
-
# Person.hair_colors # => [:brown, :black, :blonde, :red]
|
16
|
-
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
|
17
|
-
#
|
18
|
-
# To opt out of the instance writer method, pass :instance_writer => false.
|
19
|
-
# To opt out of the instance reader method, pass :instance_reader => false.
|
20
|
-
#
|
21
|
-
# class Person
|
22
|
-
# cattr_accessor :hair_colors, :instance_writer => false, :instance_reader => false
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# Person.new.hair_colors = [:brown] # => NoMethodError
|
26
|
-
# Person.new.hair_colors # => NoMethodError
|
27
|
-
class Class
|
28
|
-
def cattr_reader(*syms)
|
29
|
-
options = syms.extract_options!
|
30
|
-
syms.each do |sym|
|
31
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
32
|
-
unless defined? @@#{sym}
|
33
|
-
@@#{sym} = nil
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.#{sym}
|
37
|
-
@@#{sym}
|
38
|
-
end
|
39
|
-
EOS
|
40
|
-
|
41
|
-
unless options[:instance_reader] == false
|
42
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
43
|
-
def #{sym}
|
44
|
-
@@#{sym}
|
45
|
-
end
|
46
|
-
EOS
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end unless method_defined?(:cattr_reader)
|
50
|
-
|
51
|
-
def cattr_writer(*syms)
|
52
|
-
options = syms.extract_options!
|
53
|
-
syms.each do |sym|
|
54
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
55
|
-
unless defined? @@#{sym}
|
56
|
-
@@#{sym} = nil
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.#{sym}=(obj)
|
60
|
-
@@#{sym} = obj
|
61
|
-
end
|
62
|
-
EOS
|
63
|
-
|
64
|
-
unless options[:instance_writer] == false
|
65
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
66
|
-
def #{sym}=(obj)
|
67
|
-
@@#{sym} = obj
|
68
|
-
end
|
69
|
-
EOS
|
70
|
-
end
|
71
|
-
self.send("#{sym}=", yield) if block_given?
|
72
|
-
end
|
73
|
-
end unless method_defined?(:cattr_writer)
|
74
|
-
|
75
|
-
def cattr_accessor(*syms, &blk)
|
76
|
-
cattr_reader(*syms)
|
77
|
-
cattr_writer(*syms, &blk)
|
78
|
-
end unless method_defined?(:cattr_accessor)
|
79
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'gorillib/array/extract_options'
|
2
|
-
|
3
|
-
class Module
|
4
|
-
def mattr_reader(*syms)
|
5
|
-
options = syms.extract_options!
|
6
|
-
syms.each do |sym|
|
7
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
8
|
-
@@#{sym} = nil unless defined? @@#{sym}
|
9
|
-
|
10
|
-
def self.#{sym}
|
11
|
-
@@#{sym}
|
12
|
-
end
|
13
|
-
EOS
|
14
|
-
|
15
|
-
unless options[:instance_reader] == false
|
16
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
17
|
-
def #{sym}
|
18
|
-
@@#{sym}
|
19
|
-
end
|
20
|
-
EOS
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end unless method_defined?(:mattr_reader)
|
24
|
-
|
25
|
-
def mattr_writer(*syms)
|
26
|
-
options = syms.extract_options!
|
27
|
-
syms.each do |sym|
|
28
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
29
|
-
def self.#{sym}=(obj)
|
30
|
-
@@#{sym} = obj
|
31
|
-
end
|
32
|
-
EOS
|
33
|
-
|
34
|
-
unless options[:instance_writer] == false
|
35
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
36
|
-
def #{sym}=(obj)
|
37
|
-
@@#{sym} = obj
|
38
|
-
end
|
39
|
-
EOS
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end unless method_defined?(:mattr_writer)
|
43
|
-
|
44
|
-
# Extends the module object with module and instance accessors for class attributes,
|
45
|
-
# just like the native attr* accessors for instance attributes.
|
46
|
-
#
|
47
|
-
# module AppConfiguration
|
48
|
-
# mattr_accessor :google_api_key
|
49
|
-
# self.google_api_key = "123456789"
|
50
|
-
#
|
51
|
-
# mattr_accessor :paypal_url
|
52
|
-
# self.paypal_url = "www.sandbox.paypal.com"
|
53
|
-
# end
|
54
|
-
#
|
55
|
-
# AppConfiguration.google_api_key = "overriding the api key!"
|
56
|
-
def mattr_accessor(*syms)
|
57
|
-
mattr_reader(*syms)
|
58
|
-
mattr_writer(*syms)
|
59
|
-
end unless method_defined?(:mattr_accessor)
|
60
|
-
|
61
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# require 'active_model'
|
2
|
-
|
3
|
-
require 'active_model/deprecated_error_methods'
|
4
|
-
require 'active_model/errors'
|
5
|
-
require 'active_model/naming'
|
6
|
-
require 'active_model/validator'
|
7
|
-
require 'active_model/translation'
|
8
|
-
require 'active_model/validations'
|
9
|
-
require 'active_support/i18n'
|
10
|
-
I18n.load_path << File.join(File.expand_path(File.dirname(__FILE__)), 'locale/en.yml')
|
11
|
-
|
12
|
-
module Receiver
|
13
|
-
module ActiveModelShim
|
14
|
-
|
15
|
-
def to_model
|
16
|
-
self
|
17
|
-
end
|
18
|
-
|
19
|
-
def new_record?() true end
|
20
|
-
def destroyed?() false end
|
21
|
-
def errors
|
22
|
-
@_errors ||= ActiveModel::Errors.new(self)
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.included(base)
|
26
|
-
base.class_eval do
|
27
|
-
extend ActiveModel::Naming
|
28
|
-
include ActiveModel::Validations
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,195 +0,0 @@
|
|
1
|
-
require 'gorillib/hashlike'
|
2
|
-
|
3
|
-
module Receiver
|
4
|
-
#
|
5
|
-
# Makes a Receiver thingie behave mostly like a hash.
|
6
|
-
#
|
7
|
-
# By default, the hashlike methods iterate over the receiver attributes:
|
8
|
-
# instance #keys delegates to self.class.keys which calls
|
9
|
-
# receiver_attr_names. If you want to filter our add to the keys list, you
|
10
|
-
# can just override the class-level keys method (and call super, or not):
|
11
|
-
#
|
12
|
-
# def self.keys
|
13
|
-
# super + [:firstname, :lastname] - [:fullname]
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# All methods are defined naturally on [], []= and has_key? -- if you enjoy
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# in addition to the below, by including Enumerable, this also adds
|
20
|
-
#
|
21
|
-
# :each_cons, :each_entry, :each_slice, :each_with_index, :each_with_object,
|
22
|
-
# :map, :collect, :collect_concat, :entries, :to_a, :flat_map, :inject, :reduce,
|
23
|
-
# :group_by, :chunk, :cycle, :partition, :reverse_each, :slice_before, :drop,
|
24
|
-
# :drop_while, :take, :take_while, :detect, :find, :find_all, :find_index, :grep,
|
25
|
-
# :all?, :any?, :none?, :one?, :first, :count, :zip :max, :max_by, :min, :min_by,
|
26
|
-
# :minmax, :minmax_by, :sort, :sort_by
|
27
|
-
#
|
28
|
-
# As opposed to hash, does *not* define
|
29
|
-
#
|
30
|
-
# default, default=, default_proc, default_proc=, shift, flatten, compare_by_identity
|
31
|
-
# compare_by_identity? rehash
|
32
|
-
#
|
33
|
-
module ActsAsHash
|
34
|
-
|
35
|
-
module InstanceMethods
|
36
|
-
|
37
|
-
# Hashlike#[]
|
38
|
-
#
|
39
|
-
# Element Reference -- Retrieves the value stored for +key+.
|
40
|
-
#
|
41
|
-
# In a normal hash, a default value can be set; none is provided here.
|
42
|
-
#
|
43
|
-
# Delegates to self.send(key)
|
44
|
-
#
|
45
|
-
# @example
|
46
|
-
# hsh = { :a => 100, :b => 200 }
|
47
|
-
# hsh[:a] # => 100
|
48
|
-
# hsh[:c] # => nil
|
49
|
-
#
|
50
|
-
# @param key [Object] key to retrieve
|
51
|
-
# @return [Object] the value stored for key, nil if missing
|
52
|
-
#
|
53
|
-
def [](key)
|
54
|
-
key = convert_key(key)
|
55
|
-
self.send(key)
|
56
|
-
end
|
57
|
-
|
58
|
-
# Hashlike#[]=
|
59
|
-
# Hashlike#store
|
60
|
-
#
|
61
|
-
# Element Assignment -- Associates the value given by +val+ with the key
|
62
|
-
# given by +key+.
|
63
|
-
#
|
64
|
-
# key should not have its value changed while it is in use as a key. In a
|
65
|
-
# normal hash, a String passed as a key will be duplicated and frozen. No such
|
66
|
-
# guarantee is provided here
|
67
|
-
#
|
68
|
-
# Delegates to self.send("key=", val)
|
69
|
-
#
|
70
|
-
# @example
|
71
|
-
# hsh = { :a => 100, :b => 200 }
|
72
|
-
# hsh[:a] = 9
|
73
|
-
# hsh[:c] = 4
|
74
|
-
# hsh # => { :a => 9, :b => 200, :c => 4 }
|
75
|
-
#
|
76
|
-
# hsh[key] = val -> val
|
77
|
-
# hsh.store(key, val) -> val
|
78
|
-
#
|
79
|
-
# @param key [Object] key to associate
|
80
|
-
# @param val [Object] value to associate it with
|
81
|
-
# @return [Object]
|
82
|
-
#
|
83
|
-
def []=(key, val)
|
84
|
-
key = convert_key(key)
|
85
|
-
self.send("#{key}=", val)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Hashlike#delete
|
89
|
-
#
|
90
|
-
# Deletes and returns the value from +hsh+ whose key is equal to +key+. If the
|
91
|
-
# optional code block is given and the key is not found, pass in the key and
|
92
|
-
# return the result of +block+.
|
93
|
-
#
|
94
|
-
# In a normal hash, a default value can be set; none is provided here.
|
95
|
-
#
|
96
|
-
# @example
|
97
|
-
# hsh = { :a => 100, :b => 200 }
|
98
|
-
# hsh.delete(:a) # => 100
|
99
|
-
# hsh.delete(:z) # => nil
|
100
|
-
# hsh.delete(:z){|el| "#{el} not found" } # => "z not found"
|
101
|
-
#
|
102
|
-
# @overload hsh.delete(key) -> val
|
103
|
-
# @param key [Object] key to remove
|
104
|
-
# @return [Object, Nil] the removed object, nil if missing
|
105
|
-
#
|
106
|
-
# @overload hsh.delete(key){|key| block } -> val
|
107
|
-
# @param key [Object] key to remove
|
108
|
-
# @yield [Object] called (with key) if key is missing
|
109
|
-
# @yieldparam key
|
110
|
-
# @return [Object, Nil] the removed object, or if missing, the return value
|
111
|
-
# of the block
|
112
|
-
#
|
113
|
-
def delete(key, &block)
|
114
|
-
key = convert_key(key)
|
115
|
-
if has_key?(key)
|
116
|
-
val = self[key]
|
117
|
-
self.send(:remove_instance_variable, "@#{key}")
|
118
|
-
val
|
119
|
-
elsif block_given?
|
120
|
-
block.call(key)
|
121
|
-
else
|
122
|
-
nil
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Hashlike#keys
|
127
|
-
#
|
128
|
-
# Returns a new array populated with the keys from this hashlike.
|
129
|
-
#
|
130
|
-
# @see Hashlike#values.
|
131
|
-
#
|
132
|
-
# @example
|
133
|
-
# hsh = { :a => 100, :b => 200, :c => 300, :d => 400 }
|
134
|
-
# hsh.keys # => [:a, :b, :c, :d]
|
135
|
-
#
|
136
|
-
# @return [Array] list of keys
|
137
|
-
#
|
138
|
-
def keys
|
139
|
-
members & instance_variables.map{|s| convert_key(s[1..-1]) }
|
140
|
-
end
|
141
|
-
|
142
|
-
def members
|
143
|
-
self.class.members
|
144
|
-
end
|
145
|
-
|
146
|
-
#
|
147
|
-
# Returns a hash with each key set to its associated value.
|
148
|
-
#
|
149
|
-
# @example
|
150
|
-
# my_hshlike = MyHashlike.new
|
151
|
-
# my_hshlike[:a] = 100; my_hshlike[:b] = 200
|
152
|
-
# my_hshlike.to_hash # => { :a => 100, :b => 200 }
|
153
|
-
#
|
154
|
-
# @return [Hash] a new Hash instance, with each key set to its associated value.
|
155
|
-
#
|
156
|
-
def to_hash
|
157
|
-
{}.tap do |hsh|
|
158
|
-
each_pair do |key, val|
|
159
|
-
hsh[key] = val.respond_to?(:to_hash) ? val.to_hash : val
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
end
|
165
|
-
|
166
|
-
module ClassMethods
|
167
|
-
# By default, the hashlike methods iterate over the receiver attributes.
|
168
|
-
# If you want to filter our add to the keys list, override this method
|
169
|
-
#
|
170
|
-
# @example
|
171
|
-
# def self.keys
|
172
|
-
# super + [:firstname, :lastname] - [:fullname]
|
173
|
-
# end
|
174
|
-
#
|
175
|
-
def keys
|
176
|
-
receiver_attr_names
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
protected
|
181
|
-
|
182
|
-
def convert_key(key)
|
183
|
-
raise ArgumentError, "Keys for #{self.class} must be symbols, strings or respond to #to_sym" unless key.respond_to?(:to_sym)
|
184
|
-
key.to_sym
|
185
|
-
end
|
186
|
-
|
187
|
-
def self.included base
|
188
|
-
base.class_eval do
|
189
|
-
include Gorillib::Hashlike
|
190
|
-
extend ClassMethods
|
191
|
-
include InstanceMethods
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Receiver
|
2
|
-
#
|
3
|
-
# adds methods to load and store from json, yaml or magic
|
4
|
-
#
|
5
|
-
# This will require 'json' UNLESS you have already included something (so if
|
6
|
-
# you want to say require 'yajl' then do that first).
|
7
|
-
#
|
8
|
-
module ActsAsLoadable
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
def receive_json stream
|
12
|
-
receive(JSON.load(stream))
|
13
|
-
end
|
14
|
-
|
15
|
-
def receive_yaml stream
|
16
|
-
receive(YAML.load(stream))
|
17
|
-
end
|
18
|
-
|
19
|
-
#
|
20
|
-
# The file is loaded with
|
21
|
-
# * YAML if the filename ends in .yaml or .yml
|
22
|
-
# * JSON otherwise
|
23
|
-
#
|
24
|
-
def receive_from_file filename
|
25
|
-
stream = File.open(filename)
|
26
|
-
(filename =~ /.ya?ml$/) ? receive_yaml(stream) : receive_json(stream)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def merge_from_file! filename
|
31
|
-
other_obj = self.class.receive_from_file(filename)
|
32
|
-
tree_merge! other_obj
|
33
|
-
end
|
34
|
-
|
35
|
-
# put all the things in ClassMethods at class level
|
36
|
-
def self.included base
|
37
|
-
require 'yaml'
|
38
|
-
require 'json' unless defined?(JSON)
|
39
|
-
base.extend ClassMethods
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
en:
|
2
|
-
errors:
|
3
|
-
# The default format to use in full error messages.
|
4
|
-
format: "%{attribute} %{message}"
|
5
|
-
|
6
|
-
# The values :model, :attribute and :value are always available for interpolation
|
7
|
-
# The value :count is available when applicable. Can be used for pluralization.
|
8
|
-
messages:
|
9
|
-
inclusion: "is not included in the list"
|
10
|
-
exclusion: "is reserved"
|
11
|
-
invalid: "is invalid"
|
12
|
-
confirmation: "doesn't match confirmation"
|
13
|
-
accepted: "must be accepted"
|
14
|
-
empty: "can't be empty"
|
15
|
-
blank: "can't be blank"
|
16
|
-
too_long: "is too long (maximum is %{count} characters)"
|
17
|
-
too_short: "is too short (minimum is %{count} characters)"
|
18
|
-
wrong_length: "is the wrong length (should be %{count} characters)"
|
19
|
-
not_a_number: "is not a number"
|
20
|
-
not_an_integer: "must be an integer"
|
21
|
-
greater_than: "must be greater than %{count}"
|
22
|
-
greater_than_or_equal_to: "must be greater than or equal to %{count}"
|
23
|
-
equal_to: "must be equal to %{count}"
|
24
|
-
less_than: "must be less than %{count}"
|
25
|
-
less_than_or_equal_to: "must be less than or equal to %{count}"
|
26
|
-
odd: "must be odd"
|
27
|
-
even: "must be even"
|