icss-activesupport-4 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.rspec +3 -0
- data/.watchr +52 -0
- data/CHANGELOG.md +38 -0
- data/Gemfile +22 -0
- data/LICENSE.textile +20 -0
- data/README.md +298 -0
- data/Rakefile +39 -0
- data/TODO.md +44 -0
- data/VERSION +1 -0
- data/examples/avro_examples/BulkData.avpr +21 -0
- data/examples/avro_examples/complicated.icss.yaml +159 -0
- data/examples/avro_examples/interop.avsc +32 -0
- data/examples/avro_examples/mail.avpr +20 -0
- data/examples/avro_examples/namespace.avpr +28 -0
- data/examples/avro_examples/org/apache/avro/ipc/HandshakeRequest.avsc +11 -0
- data/examples/avro_examples/org/apache/avro/ipc/HandshakeResponse.avsc +15 -0
- data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avdl +64 -0
- data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avpr +82 -0
- data/examples/avro_examples/org/apache/avro/mapred/tether/InputProtocol.avpr +59 -0
- data/examples/avro_examples/org/apache/avro/mapred/tether/OutputProtocol.avpr +75 -0
- data/examples/avro_examples/simple.avpr +70 -0
- data/examples/avro_examples/weather.avsc +9 -0
- data/examples/bnc.icss.yaml +70 -0
- data/examples/chronic.icss.yaml +115 -0
- data/examples/license.icss.yaml +7 -0
- data/examples/source1.icss.yaml +4 -0
- data/examples/source2.icss.yaml +4 -0
- data/examples/test_icss.yaml +67 -0
- data/icss.gemspec +168 -0
- data/icss_specification.textile +393 -0
- data/lib/icss.rb +53 -0
- data/lib/icss/core_types.rb +20 -0
- data/lib/icss/error.rb +4 -0
- data/lib/icss/init.rb +3 -0
- data/lib/icss/message.rb +133 -0
- data/lib/icss/message/message_sample.rb +144 -0
- data/lib/icss/protocol.rb +199 -0
- data/lib/icss/protocol/code_asset.rb +18 -0
- data/lib/icss/protocol/data_asset.rb +23 -0
- data/lib/icss/protocol/license.rb +41 -0
- data/lib/icss/protocol/source.rb +37 -0
- data/lib/icss/protocol/target.rb +68 -0
- data/lib/icss/receiver_model.rb +24 -0
- data/lib/icss/receiver_model/active_model_shim.rb +36 -0
- data/lib/icss/receiver_model/acts_as_catalog.rb +174 -0
- data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
- data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
- data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
- data/lib/icss/receiver_model/locale/en.yml +27 -0
- data/lib/icss/receiver_model/to_geo_json.rb +19 -0
- data/lib/icss/receiver_model/tree_merge.rb +34 -0
- data/lib/icss/receiver_model/validations.rb +31 -0
- data/lib/icss/serialization.rb +51 -0
- data/lib/icss/serialization/zaml.rb +442 -0
- data/lib/icss/type.rb +168 -0
- data/lib/icss/type/base_type.rb +0 -0
- data/lib/icss/type/named_type.rb +185 -0
- data/lib/icss/type/record_field.rb +77 -0
- data/lib/icss/type/record_model.rb +49 -0
- data/lib/icss/type/record_schema.rb +54 -0
- data/lib/icss/type/record_type.rb +325 -0
- data/lib/icss/type/simple_types.rb +71 -0
- data/lib/icss/type/structured_schema.rb +288 -0
- data/lib/icss/type/type_factory.rb +144 -0
- data/lib/icss/type/union_schema.rb +41 -0
- data/lib/icss/view_helper.rb +65 -0
- data/notes/named_array.md +32 -0
- data/notes/on_include_vs_extend_etc.rb +176 -0
- data/notes/technical_details.md +278 -0
- data/spec/core_types_spec.rb +119 -0
- data/spec/fixtures/zaml_complex_hash.yaml +35 -0
- data/spec/icss_spec.rb +90 -0
- data/spec/message/message_sample_spec.rb +4 -0
- data/spec/message_spec.rb +139 -0
- data/spec/protocol/license_spec.rb +67 -0
- data/spec/protocol/protocol_catalog_spec.rb +48 -0
- data/spec/protocol/protocol_validations_spec.rb +176 -0
- data/spec/protocol/source_spec.rb +65 -0
- data/spec/protocol_spec.rb +170 -0
- data/spec/receiver_model_spec.rb +115 -0
- data/spec/serialization/zaml_spec.rb +82 -0
- data/spec/serialization/zaml_test.rb +473 -0
- data/spec/serialization_spec.rb +63 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/icss_test_helper.rb +67 -0
- data/spec/support/load_example_protocols.rb +17 -0
- data/spec/type/base_type_spec.rb +0 -0
- data/spec/type/named_type_spec.rb +75 -0
- data/spec/type/record_field_spec.rb +44 -0
- data/spec/type/record_model_spec.rb +206 -0
- data/spec/type/record_schema_spec.rb +161 -0
- data/spec/type/record_type_spec.rb +155 -0
- data/spec/type/simple_types_spec.rb +121 -0
- data/spec/type/structured_schema_spec.rb +300 -0
- data/spec/type/type_catalog_spec.rb +44 -0
- data/spec/type/type_factory_spec.rb +93 -0
- data/spec/type/union_schema_spec.rb +0 -0
- data/spec/type_spec.rb +63 -0
- metadata +304 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Icss
|
|
2
|
+
module Meta
|
|
3
|
+
|
|
4
|
+
class RecordSchema < SimpleSchema
|
|
5
|
+
include Icss::Meta::RecordModel
|
|
6
|
+
include Icss::ReceiverModel::ActsAsHash
|
|
7
|
+
include Gorillib::Hashlike
|
|
8
|
+
include Gorillib::Hashlike::Keys
|
|
9
|
+
#
|
|
10
|
+
field :_domain_id_field, String, :default => 'name'
|
|
11
|
+
field :_doc_hints, Hash, :default => {}
|
|
12
|
+
field :fields, Array, :default => []
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
def type() :record ; end
|
|
16
|
+
|
|
17
|
+
def to_hash
|
|
18
|
+
{
|
|
19
|
+
:name => basename,
|
|
20
|
+
:namespace => namespace,
|
|
21
|
+
:type => type,
|
|
22
|
+
:is_a => (respond_to?(:is_a) ? is_a : []),
|
|
23
|
+
:doc => doc,
|
|
24
|
+
:fields => fields.map(&:to_schema),
|
|
25
|
+
}.compact_blank
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def model_klass
|
|
29
|
+
return @model_klass if @model_klass
|
|
30
|
+
super
|
|
31
|
+
@model_klass.class_eval{ include(::Icss::Meta::RecordModel) }
|
|
32
|
+
self.fields.each do |field_schema|
|
|
33
|
+
@model_klass.field(field_schema[:name], field_schema[:type], field_schema)
|
|
34
|
+
end
|
|
35
|
+
@model_klass
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def receive_fields(flds)
|
|
39
|
+
super(flds.map(&:symbolize_keys!))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def attrs_to_inscribe
|
|
43
|
+
[ :doc, :fullname, :is_a, :_domain_id_field, :_doc_hints ]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class ErrorSchema
|
|
48
|
+
include Icss::Meta::RecordType
|
|
49
|
+
end
|
|
50
|
+
module ErrorModel
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
require 'icss/type/type_factory'
|
|
2
|
+
|
|
3
|
+
module Icss
|
|
4
|
+
module Meta
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# RecordType -- class methods for a RecordModel
|
|
8
|
+
#
|
|
9
|
+
# Endows the model class with
|
|
10
|
+
# * klass.field -- adds a field
|
|
11
|
+
# * klass.fields -- list of record_fields
|
|
12
|
+
#
|
|
13
|
+
# * klass.after_receive(&blk) -- blocks to execute after .receive is called
|
|
14
|
+
# * klass.after_receivers -- list of after_receivers
|
|
15
|
+
# * klass.metamodel -- overlay module that actually carries the model's instance methods
|
|
16
|
+
# * klass.to_schema --
|
|
17
|
+
module RecordType
|
|
18
|
+
include Icss::Meta::NamedType
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# Returns a new instance with the given hash used to set all rcvrs.
|
|
22
|
+
#
|
|
23
|
+
# All args up to the last one are passed to the initializer.
|
|
24
|
+
# The last arg must be a hash -- its attributes are set on the newly-created object
|
|
25
|
+
#
|
|
26
|
+
# @param hsh [Hash] attr-value pairs to set on the newly created object.
|
|
27
|
+
# @param *args [Array] arguments to pass to the constructor
|
|
28
|
+
# @return [Object] a new instance
|
|
29
|
+
def receive *args
|
|
30
|
+
hsh = args.pop
|
|
31
|
+
raise ArgumentError, "#{self} can't receive '#{hsh.inspect}' (it isn't hashlike)" unless hsh.respond_to?(:[]) && hsh.respond_to?(:has_key?)
|
|
32
|
+
obj = self.new(*args)
|
|
33
|
+
obj.receive!(hsh)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#
|
|
37
|
+
# Describes a field in a Record object.
|
|
38
|
+
#
|
|
39
|
+
# Each field has the following attributes:
|
|
40
|
+
#
|
|
41
|
+
# @param [Symbol] name -- a string providing the name of the field
|
|
42
|
+
# (required)
|
|
43
|
+
#
|
|
44
|
+
# @param [Class, Icss::Meta::Type] type a schema, or a string or symbol
|
|
45
|
+
# naming a record definition (required)
|
|
46
|
+
#
|
|
47
|
+
# ruby type kind avro type json type example
|
|
48
|
+
# ---------- -------- --------- --------- ---------
|
|
49
|
+
# NilClass simple null null nil
|
|
50
|
+
# Boolean simple boolean boolean true
|
|
51
|
+
# Integer simple int,long integer 1
|
|
52
|
+
# Float simple float,double number 1.1
|
|
53
|
+
# String simple bytes string "\u00FF"
|
|
54
|
+
# String simple string string "foo"
|
|
55
|
+
# RecordModel named record object {"a": 1}
|
|
56
|
+
# Enum named enum string "FOO"
|
|
57
|
+
# Array container array array [1]
|
|
58
|
+
# Hash container map object { "a": 1 }
|
|
59
|
+
# String container fixed string "\u00ff"
|
|
60
|
+
# XxxFactory union union object
|
|
61
|
+
# Time simple time string "2011-01-02T03:04:05Z"
|
|
62
|
+
#
|
|
63
|
+
# @option schema [String] :doc -- description of field for users (optional)
|
|
64
|
+
#
|
|
65
|
+
# @option schema [Object] :default -- a default value for this field, used
|
|
66
|
+
# when reading instances that lack this field (optional).
|
|
67
|
+
# Permitted values depend on the field's schema type, according to the
|
|
68
|
+
# table below. Default values for union fields correspond to the first
|
|
69
|
+
# schema in the union. Default values for bytes and fixed fields are
|
|
70
|
+
# JSON strings, where Unicode code points 0-255 are mapped to unsigned
|
|
71
|
+
# 8-bit byte values 0-255.
|
|
72
|
+
#
|
|
73
|
+
# @option schema [String] :order -- specifies how this field impacts sort
|
|
74
|
+
# ordering of this record (optional).
|
|
75
|
+
# Valid values are "ascending" (the default), "descending", or
|
|
76
|
+
# "ignore". For more details on how this is used, see the the sort
|
|
77
|
+
# order section below.
|
|
78
|
+
#
|
|
79
|
+
# @option schema [Boolean] :required -- same as :validates => :presence
|
|
80
|
+
#
|
|
81
|
+
# @option schema [Hash] :validates -- sends the validation on to
|
|
82
|
+
# Icss::Type::Validations. Uses syntax parallel to ActiveModel's:
|
|
83
|
+
#
|
|
84
|
+
# @option schema [Symbol] :accessor -- with +:none+, no accessor is
|
|
85
|
+
# created. With +:protected+, +:private+, or +:public+, applies
|
|
86
|
+
# corresponding access rule.
|
|
87
|
+
#
|
|
88
|
+
# :presence => true
|
|
89
|
+
# :uniqueness => true
|
|
90
|
+
# :numericality => true
|
|
91
|
+
# :length => { :minimum => 0, maximum => 2000 }
|
|
92
|
+
# :format => { :with => /.*/ }
|
|
93
|
+
# :inclusion => { :in => [1,2,3] }
|
|
94
|
+
# :exclusion => { :in => [1,2,3] }
|
|
95
|
+
#
|
|
96
|
+
def field(field_name, type, schema={})
|
|
97
|
+
field_name = field_name.to_sym
|
|
98
|
+
#
|
|
99
|
+
schema = add_field_schema(field_name, type, schema)
|
|
100
|
+
add_field_accessor(field_name, schema)
|
|
101
|
+
rcvr(field_name, schema)
|
|
102
|
+
add_validator(field_name) if respond_to?(:add_validator)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def field_names
|
|
106
|
+
all_f = []
|
|
107
|
+
call_ancestor_chain(:field_names){|anc_f| all_f = all_f | anc_f }
|
|
108
|
+
all_f
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def fields
|
|
112
|
+
field_schemas.values # _at(*field_names)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def field_named(fn)
|
|
116
|
+
fn = fn.to_sym
|
|
117
|
+
ancestors.each{|anc| hsh = anc.instance_variable_get('@field_schemas') or next ; return(hsh[fn]) if hsh[fn] }
|
|
118
|
+
nil
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def has_field?(fn)
|
|
122
|
+
!! field_schemas.has_key?(fn.to_sym)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
#
|
|
126
|
+
# define a receiver attribute.
|
|
127
|
+
#
|
|
128
|
+
# @param [Symbol] field_name - name of the receiver property
|
|
129
|
+
# @param [Class] type - a
|
|
130
|
+
#
|
|
131
|
+
# @option [Object] :default - After any receive! operation, attribute is set to this value unless attr_set? is true
|
|
132
|
+
# @option [Class] :items - For collections (Array, Hash, etc), the type of the collection's items
|
|
133
|
+
#
|
|
134
|
+
def rcvr(field_name, schema={})
|
|
135
|
+
return if schema[:receiver] == :none
|
|
136
|
+
klass = schema[:type]
|
|
137
|
+
define_metamodel_method("receive_#{field_name}") do |val|
|
|
138
|
+
_set_field_val(field_name, klass.receive(val))
|
|
139
|
+
end
|
|
140
|
+
_register_rcvr_for(field_name, "receive_#{field_name}")
|
|
141
|
+
add_after_receivers(field_name)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def rcvr_alias(fake_attr, field_name)
|
|
145
|
+
_register_rcvr_for(fake_attr, "receive_#{field_name}")
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
#
|
|
149
|
+
def to_schema
|
|
150
|
+
{
|
|
151
|
+
:name => fullname,
|
|
152
|
+
:namespace => namespace,
|
|
153
|
+
:type => :record,
|
|
154
|
+
:is_a => (respond_to?(:is_a) ? is_a : []),
|
|
155
|
+
:doc => doc,
|
|
156
|
+
:fields => fields.map(&:to_hash),
|
|
157
|
+
}.compact_blank
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
#
|
|
161
|
+
# Defines a receiver for attributes sent to receive! that are
|
|
162
|
+
# * not defined as receivers
|
|
163
|
+
# * field's name does not start with '_'
|
|
164
|
+
#
|
|
165
|
+
# @example
|
|
166
|
+
# class Foo ; include RecordModel
|
|
167
|
+
# field :bob, String
|
|
168
|
+
# rcvr_remaining :other_params
|
|
169
|
+
# end
|
|
170
|
+
# foo_obj = Foo.receive(:bob => 'hi, bob", :joe => 'hi, joe')
|
|
171
|
+
# # => <Foo @bob='hi, bob' @other_params={ :joe => 'hi, joe' }>
|
|
172
|
+
def rcvr_remaining(field_name, schema={})
|
|
173
|
+
schema[:values] ||= Object
|
|
174
|
+
field(field_name, Hash, schema)
|
|
175
|
+
after_receive(:rcvr_remaining) do |hsh|
|
|
176
|
+
remaining_vals_hsh = hsh.reject{|k,v| (self.class.has_field?(k)) || (k.to_s =~ /^_/) }
|
|
177
|
+
self.send("receive_#{field_name}", remaining_vals_hsh)
|
|
178
|
+
end
|
|
179
|
+
add_after_receivers(field_name)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# make a block to run after each time .receive! is invoked
|
|
183
|
+
def after_receive(after_hook_name, &after_hook)
|
|
184
|
+
@after_receivers ||= {}
|
|
185
|
+
@after_receivers[after_hook_name] = after_hook
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# after_receive blocks for self and all ancestors
|
|
189
|
+
def after_receivers
|
|
190
|
+
all_f = {} # @after_receivers || {}
|
|
191
|
+
call_ancestor_chain(:after_receivers){|anc_f| all_f.merge!(anc_f) }
|
|
192
|
+
all_f
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
protected
|
|
196
|
+
|
|
197
|
+
#
|
|
198
|
+
# yield, in turn, the given instance variable from each ancestor having
|
|
199
|
+
# that variable. Ancestors are called from parent to great-grandparent
|
|
200
|
+
#
|
|
201
|
+
# So you're asking yourself "Self, why not just call .super?
|
|
202
|
+
#
|
|
203
|
+
# Consider:
|
|
204
|
+
#
|
|
205
|
+
# class Base
|
|
206
|
+
# extend(Icss::Meta::RecordType)
|
|
207
|
+
# field :smurfiness, Integer
|
|
208
|
+
# end
|
|
209
|
+
# class Poppa < Base
|
|
210
|
+
# field :height, Integer
|
|
211
|
+
# end
|
|
212
|
+
#
|
|
213
|
+
# Poppa.field_names calls Icss::Meta::RecordType --
|
|
214
|
+
# it's the first member of its inheritance chain to define the method.
|
|
215
|
+
# We want it to do so for each ancestor that has added fields.
|
|
216
|
+
def call_ancestor_chain(attr)
|
|
217
|
+
# if caller.length > 200
|
|
218
|
+
# puts "\n\n********\n#{self}\n#{attr}\n#{ancestors.inspect}"
|
|
219
|
+
# puts caller.grep(%r{lib/icss})
|
|
220
|
+
# end
|
|
221
|
+
ivar = "@#{attr}"
|
|
222
|
+
self.ancestors.reverse.each do |ancestor|
|
|
223
|
+
yield(ancestor.instance_variable_get(ivar)) if ancestor.instance_variable_defined?(ivar)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def make_field_schema
|
|
228
|
+
Hash.new
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def field_schemas
|
|
232
|
+
all_f = {}
|
|
233
|
+
call_ancestor_chain(:field_schemas){|anc_f| all_f.merge!(anc_f) }
|
|
234
|
+
all_f
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# register the field schema internally.
|
|
238
|
+
# To preserve field order for 1.8.7, we track field names as an array
|
|
239
|
+
def add_field_schema(name, type, schema)
|
|
240
|
+
@field_names ||= [] ; @field_schemas ||= {}
|
|
241
|
+
@field_names = @field_names | [name]
|
|
242
|
+
schema = schema.symbolize_keys.merge({ :name => name })
|
|
243
|
+
#
|
|
244
|
+
# FIXME: this is terrible, especially given what's in TypeFactory anyway.
|
|
245
|
+
#
|
|
246
|
+
schema[:type] =
|
|
247
|
+
case
|
|
248
|
+
when type == Hash && schema.has_key?(:values) then Icss::Meta::TypeFactory.receive({ :type => :hash, :values => schema.delete(:values)})
|
|
249
|
+
when type == Array && schema.has_key?(:items) then Icss::Meta::TypeFactory.receive({ :type => :array, :items => schema.delete(:items) })
|
|
250
|
+
when type == Hash then IdenticalHashFactory
|
|
251
|
+
when type == Array then IdenticalArrayFactory
|
|
252
|
+
else
|
|
253
|
+
Icss::Meta::TypeFactory.receive(type)
|
|
254
|
+
end
|
|
255
|
+
fld = (field_schemas[name] || make_field_schema).merge(schema)
|
|
256
|
+
fld[:parent] = self
|
|
257
|
+
@field_schemas[name] = fld
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def add_field_accessor(field_name, schema)
|
|
261
|
+
visibility = schema[:accessor] || :public
|
|
262
|
+
reader_meth = field_name ; writer_meth = "#{field_name}=" ; attr_name = "@#{field_name}"
|
|
263
|
+
unless (visibility == :none)
|
|
264
|
+
define_metamodel_method(reader_meth, visibility){ instance_variable_get(attr_name) }
|
|
265
|
+
define_metamodel_method(writer_meth, visibility){|v| instance_variable_set(attr_name, v) }
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def _rcvr_methods
|
|
270
|
+
all_f = {}
|
|
271
|
+
call_ancestor_chain(:_rcvr_methods){|anc_f| all_f.merge!(anc_f) }
|
|
272
|
+
all_f
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def _register_rcvr_for(attr_name, rcvr_meth)
|
|
276
|
+
@_rcvr_methods ||= {}
|
|
277
|
+
@_rcvr_methods[attr_name.to_sym] = rcvr_meth.to_sym
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Adds after_receivers to implement some of the options to .field
|
|
281
|
+
#
|
|
282
|
+
# @option schema [Object] :default -- if field is unset by time of
|
|
283
|
+
# after_receive, the field will be set to a copy of this value
|
|
284
|
+
#
|
|
285
|
+
# @option schema [Hash] :replace -- if value is in the hash
|
|
286
|
+
# class Foo < Icss::Thing
|
|
287
|
+
# field :temperature, Integer, :replace => { 9999 => nil }
|
|
288
|
+
# end
|
|
289
|
+
# f = Foo.receive({:temperature => 9999})
|
|
290
|
+
# # #<Foo:0x10156c820 @temperature=nil>
|
|
291
|
+
#
|
|
292
|
+
def add_after_receivers(field_name)
|
|
293
|
+
schema = field_named(field_name)
|
|
294
|
+
set_field_default(field_name, schema[:default]) if schema.has_key?(:default)
|
|
295
|
+
if schema.has_key?(:replace)
|
|
296
|
+
repl = schema[:replace]
|
|
297
|
+
after_receive(:"replace_#{field_name}") do
|
|
298
|
+
val = self.send(field_name)
|
|
299
|
+
if repl.has_key?(val)
|
|
300
|
+
self._set_field_val(field_name, repl[val])
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
# super(field_name) if defined?(super)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def set_field_default(field_name, default_val=nil, &blk)
|
|
309
|
+
blk = default_val if default_val.is_a?(Proc)
|
|
310
|
+
if blk
|
|
311
|
+
after_receive(:"default_#{field_name}") do
|
|
312
|
+
val = instance_exec(&blk)
|
|
313
|
+
self._set_field_val(field_name, val) unless attr_set?(field_name)
|
|
314
|
+
end
|
|
315
|
+
else
|
|
316
|
+
after_receive(:"default_#{field_name}") do
|
|
317
|
+
val = default_val.try_dup
|
|
318
|
+
self._set_field_val(field_name, val) unless attr_set?(field_name)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
end # RecordType
|
|
324
|
+
end
|
|
325
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Icss
|
|
2
|
+
module Meta
|
|
3
|
+
module PrimitiveSchema
|
|
4
|
+
def to_schema() fullname ; end
|
|
5
|
+
def doc() "" end
|
|
6
|
+
def doc=(str)
|
|
7
|
+
singleton_class.class_eval do
|
|
8
|
+
remove_possible_method(:doc)
|
|
9
|
+
define_method(:doc){ str }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module NilClassSchema ; include PrimitiveSchema ; def fullname() :null ; end ; def receive(val=nil) raise(ArgumentError, "#{self} must be initialized with nil, but [#{val}] was given") unless val.nil? ; nil ; end ; end
|
|
15
|
+
module BooleanSchema ; include PrimitiveSchema ; def fullname() :boolean ; end ; def receive(val=nil) case when val.nil? then nil when val.to_s.strip.blank? then false else val.to_s.strip != "false" end ; end ; end
|
|
16
|
+
module IntegerSchema ; include PrimitiveSchema ; def fullname() :int ; end ; def receive(val=nil) val.blank? ? nil : val.to_i ; end ; end
|
|
17
|
+
module LongSchema ; include PrimitiveSchema ; def fullname() :long ; end ; end
|
|
18
|
+
module FloatSchema ; include PrimitiveSchema ; def fullname() :float ; end ; def receive(val=nil) val.blank? ? nil : val.to_f ; end ; end
|
|
19
|
+
module DoubleSchema ; include PrimitiveSchema ; def fullname() :double ; end ; end
|
|
20
|
+
module StringSchema ; include PrimitiveSchema ; def fullname() :string ; end ; def receive(val=nil) self.new(val.to_s) ; end ; end
|
|
21
|
+
module BinarySchema ; include PrimitiveSchema ; def fullname() :bytes ; end ; end
|
|
22
|
+
#
|
|
23
|
+
module NumericSchema ; include PrimitiveSchema ; def fullname() :numeric ; end ; def receive(val=nil) val.blank? ? nil : val.to_f ; end ; end
|
|
24
|
+
module SymbolSchema ; include PrimitiveSchema ; def fullname() :symbol ; end ; def receive(val=nil) val.blank? ? nil : val.to_sym ; end ; end
|
|
25
|
+
module TimeSchema ; include PrimitiveSchema ; def fullname() :time ; end ; def receive(val=nil) val.blank? ? nil : self.parse(val.to_s).utc rescue nil ; end ; end
|
|
26
|
+
module RegexpSchema ; include PrimitiveSchema ; def fullname() :regexp ; end ; def receive(val=nil) val.blank? ? nil : Regexp.new(val.to_s) ; end ; end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class ::NilClass ; self.extend ::Icss::Meta::NilClassSchema ; end
|
|
30
|
+
class ::Boolean < ::BasicObject ; self.extend ::Icss::Meta::BooleanSchema ; end
|
|
31
|
+
class ::Integer ; self.extend ::Icss::Meta::IntegerSchema ; end
|
|
32
|
+
class ::Long < ::Integer ; self.extend ::Icss::Meta::LongSchema ; end
|
|
33
|
+
class ::Float ; self.extend ::Icss::Meta::FloatSchema ; end
|
|
34
|
+
class ::Double < ::Float ; self.extend ::Icss::Meta::DoubleSchema ; end
|
|
35
|
+
class ::String ; self.extend ::Icss::Meta::StringSchema ; end
|
|
36
|
+
class ::Binary < ::String ; self.extend ::Icss::Meta::BinarySchema ; end
|
|
37
|
+
#
|
|
38
|
+
class ::Numeric ; self.extend ::Icss::Meta::NumericSchema ; end
|
|
39
|
+
class ::Symbol ; self.extend ::Icss::Meta::SymbolSchema ; end
|
|
40
|
+
class ::Time ; self.extend ::Icss::Meta::TimeSchema ; end
|
|
41
|
+
class ::Regexp ; self.extend ::Icss::Meta::RegexpSchema ; end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class ::Boolean < BasicObject
|
|
46
|
+
attr_accessor :val
|
|
47
|
+
def initialize(val=nil)
|
|
48
|
+
self.val = val
|
|
49
|
+
end
|
|
50
|
+
def self.methods() ::TrueClass.methods | ::Icss::Meta::BooleanSchema.instance_methods ; end
|
|
51
|
+
def method_missing(meth, *args)
|
|
52
|
+
val.send(meth, *args)
|
|
53
|
+
end
|
|
54
|
+
def respond_to?(meth)
|
|
55
|
+
super(meth) || val.respond_to?(meth)
|
|
56
|
+
end
|
|
57
|
+
def inspect()
|
|
58
|
+
"<Boolean #{val.inspect}>"
|
|
59
|
+
end
|
|
60
|
+
def class() ::Boolean ; end
|
|
61
|
+
def !() (not val) ; end
|
|
62
|
+
def ==(other_val) val == other_val ; end
|
|
63
|
+
def !=(other_val) val != other_val ; end
|
|
64
|
+
def try_dup() ::Boolean.new(val) ; end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Datamapper also defines:
|
|
68
|
+
#
|
|
69
|
+
# Apikey BCryptHash URI UUID Slug CommaSeparatedList Csv IpAddress Json Yaml Enum Flag Discriminator
|
|
70
|
+
#
|
|
71
|
+
# maybe someday we will too...
|