icss-activesupport-4 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.rspec +3 -0
  4. data/.watchr +52 -0
  5. data/CHANGELOG.md +38 -0
  6. data/Gemfile +22 -0
  7. data/LICENSE.textile +20 -0
  8. data/README.md +298 -0
  9. data/Rakefile +39 -0
  10. data/TODO.md +44 -0
  11. data/VERSION +1 -0
  12. data/examples/avro_examples/BulkData.avpr +21 -0
  13. data/examples/avro_examples/complicated.icss.yaml +159 -0
  14. data/examples/avro_examples/interop.avsc +32 -0
  15. data/examples/avro_examples/mail.avpr +20 -0
  16. data/examples/avro_examples/namespace.avpr +28 -0
  17. data/examples/avro_examples/org/apache/avro/ipc/HandshakeRequest.avsc +11 -0
  18. data/examples/avro_examples/org/apache/avro/ipc/HandshakeResponse.avsc +15 -0
  19. data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avdl +64 -0
  20. data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avpr +82 -0
  21. data/examples/avro_examples/org/apache/avro/mapred/tether/InputProtocol.avpr +59 -0
  22. data/examples/avro_examples/org/apache/avro/mapred/tether/OutputProtocol.avpr +75 -0
  23. data/examples/avro_examples/simple.avpr +70 -0
  24. data/examples/avro_examples/weather.avsc +9 -0
  25. data/examples/bnc.icss.yaml +70 -0
  26. data/examples/chronic.icss.yaml +115 -0
  27. data/examples/license.icss.yaml +7 -0
  28. data/examples/source1.icss.yaml +4 -0
  29. data/examples/source2.icss.yaml +4 -0
  30. data/examples/test_icss.yaml +67 -0
  31. data/icss.gemspec +168 -0
  32. data/icss_specification.textile +393 -0
  33. data/lib/icss.rb +53 -0
  34. data/lib/icss/core_types.rb +20 -0
  35. data/lib/icss/error.rb +4 -0
  36. data/lib/icss/init.rb +3 -0
  37. data/lib/icss/message.rb +133 -0
  38. data/lib/icss/message/message_sample.rb +144 -0
  39. data/lib/icss/protocol.rb +199 -0
  40. data/lib/icss/protocol/code_asset.rb +18 -0
  41. data/lib/icss/protocol/data_asset.rb +23 -0
  42. data/lib/icss/protocol/license.rb +41 -0
  43. data/lib/icss/protocol/source.rb +37 -0
  44. data/lib/icss/protocol/target.rb +68 -0
  45. data/lib/icss/receiver_model.rb +24 -0
  46. data/lib/icss/receiver_model/active_model_shim.rb +36 -0
  47. data/lib/icss/receiver_model/acts_as_catalog.rb +174 -0
  48. data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
  49. data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
  50. data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
  51. data/lib/icss/receiver_model/locale/en.yml +27 -0
  52. data/lib/icss/receiver_model/to_geo_json.rb +19 -0
  53. data/lib/icss/receiver_model/tree_merge.rb +34 -0
  54. data/lib/icss/receiver_model/validations.rb +31 -0
  55. data/lib/icss/serialization.rb +51 -0
  56. data/lib/icss/serialization/zaml.rb +442 -0
  57. data/lib/icss/type.rb +168 -0
  58. data/lib/icss/type/base_type.rb +0 -0
  59. data/lib/icss/type/named_type.rb +185 -0
  60. data/lib/icss/type/record_field.rb +77 -0
  61. data/lib/icss/type/record_model.rb +49 -0
  62. data/lib/icss/type/record_schema.rb +54 -0
  63. data/lib/icss/type/record_type.rb +325 -0
  64. data/lib/icss/type/simple_types.rb +71 -0
  65. data/lib/icss/type/structured_schema.rb +288 -0
  66. data/lib/icss/type/type_factory.rb +144 -0
  67. data/lib/icss/type/union_schema.rb +41 -0
  68. data/lib/icss/view_helper.rb +65 -0
  69. data/notes/named_array.md +32 -0
  70. data/notes/on_include_vs_extend_etc.rb +176 -0
  71. data/notes/technical_details.md +278 -0
  72. data/spec/core_types_spec.rb +119 -0
  73. data/spec/fixtures/zaml_complex_hash.yaml +35 -0
  74. data/spec/icss_spec.rb +90 -0
  75. data/spec/message/message_sample_spec.rb +4 -0
  76. data/spec/message_spec.rb +139 -0
  77. data/spec/protocol/license_spec.rb +67 -0
  78. data/spec/protocol/protocol_catalog_spec.rb +48 -0
  79. data/spec/protocol/protocol_validations_spec.rb +176 -0
  80. data/spec/protocol/source_spec.rb +65 -0
  81. data/spec/protocol_spec.rb +170 -0
  82. data/spec/receiver_model_spec.rb +115 -0
  83. data/spec/serialization/zaml_spec.rb +82 -0
  84. data/spec/serialization/zaml_test.rb +473 -0
  85. data/spec/serialization_spec.rb +63 -0
  86. data/spec/spec_helper.rb +39 -0
  87. data/spec/support/icss_test_helper.rb +67 -0
  88. data/spec/support/load_example_protocols.rb +17 -0
  89. data/spec/type/base_type_spec.rb +0 -0
  90. data/spec/type/named_type_spec.rb +75 -0
  91. data/spec/type/record_field_spec.rb +44 -0
  92. data/spec/type/record_model_spec.rb +206 -0
  93. data/spec/type/record_schema_spec.rb +161 -0
  94. data/spec/type/record_type_spec.rb +155 -0
  95. data/spec/type/simple_types_spec.rb +121 -0
  96. data/spec/type/structured_schema_spec.rb +300 -0
  97. data/spec/type/type_catalog_spec.rb +44 -0
  98. data/spec/type/type_factory_spec.rb +93 -0
  99. data/spec/type/union_schema_spec.rb +0 -0
  100. data/spec/type_spec.rb +63 -0
  101. metadata +304 -0
data/lib/icss/type.rb ADDED
@@ -0,0 +1,168 @@
1
+ module Icss
2
+ module Meta
3
+ module Type
4
+ include Icss::ReceiverModel::ActsAsCatalog
5
+ def self.catalog_sections
6
+ ::Icss::Meta::Protocol.catalog_sections
7
+ end
8
+ def self.receive(hsh)
9
+ ::Icss::Meta::Protocol.receive(hsh)
10
+ end
11
+ end
12
+ end
13
+
14
+ #
15
+ # Predefining the namespaces here makes inclusion-order less brittle.
16
+ #
17
+
18
+ # full definitions in type/simple_types.rb
19
+ class ::Boolean < ::BasicObject ; end
20
+ class ::Long < ::Integer ; end
21
+ class ::Double < ::Float ; end
22
+ class ::Binary < ::String ; end
23
+
24
+ # patron saint of Simple Types (Structured Text)
25
+ module St ; end
26
+ # pasture wherein graze MeasurementUnits
27
+ module Mu ; end
28
+ # stand in the place where you are
29
+ module Business ; end
30
+ #
31
+ module Culture ; end
32
+ # we gots the whhole worl innour hans
33
+ module Encyclopedic ; end
34
+ # Eventfully, Tom phoned the caterer.
35
+ module Ev ; end
36
+ #
37
+ module Geo ; end
38
+ # Relatively speaking, this is where links and relations go
39
+ module Rel ; end
40
+ # I don't want to sell anything, buy anything, or process anything as a career.
41
+ # I don't want to sell anything bought or processed, or buy anything sold or processed, or process
42
+ # anything sold, bought, or processed, or repair anything sold, bought, or processed.
43
+ # You know, as a career, I don't want to do that.
44
+ module Prod ; end
45
+ #
46
+ module Social ; end
47
+ # Oh what a tangled web we weave when first we practice to receive
48
+ module Web ; end
49
+ # Raw records, for use by data mungers
50
+ module Raw ; end
51
+
52
+ # Buffalo Buffalo buffalo Buffalo Buffalo Buffalo buffalo.
53
+ module Meta
54
+ # full definitions in type/structured_schema.rb and type/union_schema.rb
55
+ class NamedSchema ; end
56
+ class SimpleSchema < NamedSchema ; end
57
+ class UnionSchema < NamedSchema ; end
58
+ class RecordSchema < SimpleSchema ; end
59
+ class ErrorSchema < RecordSchema ; end
60
+ #
61
+ class StructuredSchema < NamedSchema ; end
62
+ class HashSchema < StructuredSchema ; end
63
+ class ArraySchema < StructuredSchema ; end
64
+ class FixedSchema < StructuredSchema ; end
65
+ class EnumSchema < StructuredSchema ; end
66
+ end
67
+
68
+ ::Icss::SIMPLE_TYPES = {} unless defined?( ::Icss::SIMPLE_TYPES )
69
+ ::Icss::FACTORY_TYPES = {} unless defined?( ::Icss::FACTORY_TYPES )
70
+ ::Icss::STRUCTURED_SCHEMAS = {} unless defined?( ::Icss::STRUCTURED_SCHEMAS )
71
+ ::Icss::UNION_SCHEMAS = {} unless defined?( ::Icss::UNION_SCHEMAS )
72
+
73
+ unless defined?(::Icss::AVRO_TYPES)
74
+ ::Icss::AVRO_TYPES = {
75
+ :null => ::NilClass,
76
+ :boolean => ::Boolean,
77
+ :int => ::Integer,
78
+ :long => ::Long,
79
+ :float => ::Float,
80
+ :double => ::Double,
81
+ :string => ::String,
82
+ :bytes => ::Binary,
83
+ }.freeze
84
+ end
85
+ ::Icss::SIMPLE_TYPES.merge!(::Icss::AVRO_TYPES)
86
+
87
+ ::Icss::SIMPLE_TYPES.merge!({
88
+ :binary => ::Binary,
89
+ :symbol => ::Symbol,
90
+ :time => ::Time,
91
+ :integer => ::Integer,
92
+ :numeric => ::Numeric,
93
+ :regexp => ::Regexp,
94
+ })
95
+
96
+ ::Icss::STRUCTURED_SCHEMAS.merge!({
97
+ :simple => Icss::Meta::SimpleSchema,
98
+ :record => Icss::Meta::RecordSchema,
99
+ :error => Icss::Meta::ErrorSchema,
100
+ :map => Icss::Meta::HashSchema,
101
+ :hash => Icss::Meta::HashSchema,
102
+ Hash => Icss::Meta::HashSchema,
103
+ :array => Icss::Meta::ArraySchema,
104
+ Array => Icss::Meta::ArraySchema,
105
+ :fixed => Icss::Meta::FixedSchema,
106
+ :enum => Icss::Meta::EnumSchema,
107
+ })
108
+ ::Icss::UNION_SCHEMAS.merge!({
109
+ :union => Icss::Meta::UnionSchema,
110
+ })
111
+
112
+ module Meta
113
+ module Type
114
+ #:nodoc:
115
+ NORMAL_NAMED_CONSTANT_RE = /\A[\w\:\.]+\z/ unless defined?(NORMAL_NAMED_CONSTANT_RE)
116
+
117
+ # Turns a type name into its dotted (avro-style) name, regardless of its
118
+ # current form.
119
+ #
120
+ # @example
121
+ # Icss::Meta::Type.fullname_for(Icss::This::That::TheOther) # 'this.that.the_other'
122
+ # Icss::Meta::Type.fullname_for("Icss::This::That::TheOther") # 'this.that.the_other'
123
+ # Icss::Meta::Type.fullname_for('this.that.the_other') # 'this.that.the_other'
124
+ #
125
+ def self.fullname_for(klass_name)
126
+ return nil unless klass_name.present? && (klass_name.to_s =~ NORMAL_NAMED_CONSTANT_RE)
127
+ klass_name.to_s.gsub(/^:*Icss::/, '').underscore.gsub(%r{/},".")
128
+ end
129
+
130
+ # Converts a type name to its ruby (camel-cased) form. Works on class,
131
+ # name of class, or dotted (avro-style) namespace.name. Names will have
132
+ # an 'Icss::' prefix.
133
+ #
134
+ # @example
135
+ # Icss::Meta::Type.fullname_for('this.that.the_other') # "Icss::This::That::TheOther"
136
+ # Icss::Meta::Type.fullname_for(Icss::This::That::TheOther) # "Icss::This::That::TheOther"
137
+ # Icss::Meta::Type.fullname_for("Icss::This::That::TheOther") # "Icss::This::That::TheOther"
138
+ #
139
+ def self.klassname_for(obj)
140
+ return nil unless obj.present? && (obj.to_s =~ NORMAL_NAMED_CONSTANT_RE)
141
+ nm = obj.to_s.gsub(/^:*Icss:+/, '').
142
+ gsub(%r{::},'.').
143
+ split('.').map(&:camelize).join('::')
144
+ "::Icss::#{nm}"
145
+ end
146
+
147
+ def self.schema_for(obj)
148
+ case
149
+ when obj.respond_to?(:to_schema) then obj.to_schema
150
+ when str = fullname_for(obj) then str.to_sym
151
+ else nil ; end
152
+ end
153
+
154
+ # true if class is among the defined primitive types:
155
+ # null boolean integer long float double string binary
156
+ # and so forth
157
+ #
158
+ # note this takes no account of inheritance -- only the types specifically
159
+ # listed in Icss::SIMPLE_TYPES are simple
160
+ def self.simple?(tt) ::Icss::SIMPLE_TYPES.has_value?(tt) ; end
161
+
162
+ def self.union?(tt) false ; end
163
+
164
+ def self.record?(tt) false ; end
165
+
166
+ end
167
+ end
168
+ end
File without changes
@@ -0,0 +1,185 @@
1
+ module Icss
2
+ module Meta
3
+
4
+ #
5
+ # Record, Error, Enum and Fixed are named types. Each has a fullname that is
6
+ # composed of two parts; a name and a namespace. Equality of names is
7
+ # defined on the fullname.
8
+ #
9
+ # The name portion of a fullname, and record field names, must:
10
+ #
11
+ # * start with [A-Za-z_]
12
+ # * subsequently contain only [A-Za-z0-9_]
13
+ # * A namespace is a dot-separated sequence of such names.
14
+ #
15
+ # References to previously defined names are as in the latter two cases above:
16
+ # if they contain a dot they are a fullname, if they do not contain a dot, the
17
+ # namespace is the namespace of the enclosing definition.
18
+ #
19
+ # Simple type names have no namespace and their names may not be defined in
20
+ # any namespace. A schema may only contain multiple definitions of a
21
+ # fullname if the definitions are equivalent.
22
+ #
23
+ module NamedType
24
+ def doc() "" end
25
+ def doc=(str)
26
+ singleton_class.class_eval do
27
+ remove_possible_method(:doc)
28
+ define_method(:doc){ str }
29
+ end
30
+ end
31
+ #
32
+ def fullname
33
+ ::Icss::Meta::Type.fullname_for(self.name)
34
+ end
35
+ def basename
36
+ @basename ||= fullname.to_s.gsub(/.*[\.]/, "")
37
+ end
38
+ def namespace
39
+ @namespace ||= fullname.to_s.include?('.') ? fullname.to_s.gsub(/\.[^\.]+\z/so, '') : ''
40
+ end
41
+ def pathname
42
+ fullname.to_s.gsub(/\./, '/')
43
+ end
44
+ #
45
+ def to_schema
46
+ if respond_to?(:_schema) then return _schema.to_hash ; end
47
+ {
48
+ :name => fullname,
49
+ # :namespace => namespace,
50
+ :doc => doc,
51
+ }.compact_blank
52
+ end
53
+
54
+ def is_core?
55
+ respond_to?(:_schema) && _schema.is_core?
56
+ end
57
+
58
+ # ---------------------------------------------------------------------------
59
+ #
60
+ # Type Factory methods
61
+ #
62
+
63
+ #
64
+ # Returns the metamodel -- a module extending the type, on which all the
65
+ # accessors and receive methods are inscribed. (This allows you to call
66
+ # +super()+ from within receive_foo)
67
+ #
68
+ def metamodel
69
+ return @metamodel if @metamodel
70
+ @metamodel = Icss::Meta::NamedType.get_meta_module(self.to_s)
71
+ self.class_eval{ include(@metamodel) }
72
+ @metamodel
73
+ end
74
+
75
+ #
76
+ # Manufactures klass and metamodel
77
+ #
78
+ # for type science.astronomy.ufo_sighting, we synthesize
79
+ # * a module, ::Icss::Meta::Science::Astronomy::UfoSightingType
80
+ # * a class, ::Icss::Science::Astronomy::UfoSighting
81
+ #
82
+ # If no superklass is given, Icss::Entity is used.
83
+ def self.make(fullname, superklass)
84
+ klass = get_model_klass(fullname, superklass)
85
+ metamodel = get_meta_module(klass.to_s)
86
+ klass.class_eval{ extend(::Icss::Meta::NamedType) }
87
+ klass.class_eval{ include(metamodel) }
88
+ [klass, metamodel]
89
+ end
90
+
91
+ protected
92
+
93
+ def define_metamodel_method(meth_name, visibility=:public, &blk)
94
+ metamodel.class_eval do
95
+ define_method(meth_name, &blk) unless method_defined?(meth_name)
96
+ case visibility
97
+ when :protected then protected meth_name
98
+ when :private then private meth_name
99
+ when :public then public meth_name
100
+ else raise ArgumentError, "visibility must be :public, :private or :protected"
101
+ end
102
+ end
103
+ end
104
+
105
+ # Returns the klass for the given scope and name, starting with '::Icss'
106
+ # and creating all necessary parents along the way. Note that if the given
107
+ # class or its parent scopes already exist, they're trusted to be correct
108
+ # -- we don't do any error checking as to their type or superclass.
109
+ #
110
+ # @example
111
+ # Icss::Meta::Type.get_model_klass('this.that.the_other')
112
+ # # Icss::This::That::TheOther
113
+ #
114
+ # @param scope_names [Array of String]
115
+ # @param superklass [Class] - the superclass to use if the class doesn't exist.
116
+ def self.get_model_klass(fn, superklass)
117
+ fullname = Icss::Meta::Type.fullname_for(fn)
118
+ return Class.new(superklass) if fullname.nil?
119
+ #
120
+ scope_names = scope_names_for(fullname)
121
+ klass_name = scope_names.pop
122
+ parent_module = get_nested_module(%w[Icss] + scope_names)
123
+
124
+ # const_defined?(klass, inherit), const_get(klass, inherit)
125
+ # inherit = false makes these methods be scoped to parent_module instead of universally
126
+ if parent_module.const_defined?(klass_name, false)
127
+ klass = parent_module.const_get(klass_name, false)
128
+ # #{superklass.object_id}: #{klass.ancestors.map{|o| [o, o.object_id] }}
129
+ unless klass.ancestors.include?(superklass)
130
+ warn "+++++++++++++++++++++++++++++++ Superclass and is_a? mismatch for #{klass.inspect} (doesn't inherit from #{superklass.inspect})"
131
+ # p [klass_name, klass, Icss::Thing.object_id, ::Icss::Thing.object_id, Icss.const_get(:Thing).object_id,]
132
+ # p klass .ancestors.flatten.map{|t| [t, t.object_id]}
133
+ # p Icss::Thing.ancestors.flatten.map{|t| [t, t.object_id]}
134
+ end
135
+ klass
136
+ else
137
+ parent_module.const_set(klass_name, Class.new(superklass))
138
+ end
139
+ end
140
+
141
+ # Returns the meta-module for the given scope and name, starting with
142
+ # '::Icss::Meta' and creating all necessary parents along the way.
143
+ #
144
+ # @example
145
+ # Icss::Meta::TypeFactory.get_meta_module(["This", "That"], "TheOther")
146
+ # # Icss::Meta::This::That::TheOtherModel
147
+ def self.get_meta_module(fullname)
148
+ fullname = Icss::Meta::Type.fullname_for(fullname)
149
+ return Module.new if fullname.nil?
150
+ #
151
+ scope_names = scope_names_for(fullname)
152
+ scope_names[-1] += "Model"
153
+ get_nested_module(%w[Icss Meta] + scope_names)
154
+ end
155
+
156
+ # Turns a dotted namespace.name into camelized rubylike names for a class
157
+ # @example
158
+ # scope_names_for('this.that.the_other')
159
+ # # ["This", "That", "TheOther"]
160
+ def self.scope_names_for(fullname)
161
+ fullname.split('.').map(&:camelize)
162
+ end
163
+
164
+ # Returns a module for the given scope names, rooted always at Object (so
165
+ # implicity with '::').
166
+ # @example
167
+ # get_nested_module(["This", "That", "TheOther"])
168
+ # # This::That::TheOther
169
+ def self.get_nested_module(scope_names)
170
+ scope_names.inject(Object) do |parent_module, module_name|
171
+
172
+ # const_defined?(klass, inherit), const_get(klass, inherit)
173
+ # inherit = false makes these methods be scoped to parent_module instead of universally
174
+ if parent_module.const_defined?(module_name, false)
175
+ parent_module.const_get(module_name, false)
176
+ else
177
+ parent_module.const_set(module_name.to_sym, Module.new)
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+ end
185
+ end
@@ -0,0 +1,77 @@
1
+ module Icss
2
+ module Meta
3
+
4
+ class RecordField
5
+ include Icss::Meta::RecordModel
6
+ include Icss::ReceiverModel::ActsAsHash
7
+ include Gorillib::Hashlike
8
+ include Gorillib::Hashlike::Keys
9
+ include Icss::ReceiverModel
10
+ include Icss::ReceiverModel::ActiveModelShim
11
+ remove_possible_method(:type)
12
+
13
+ ALLOWED_ORDERS = %w[ascending descending ignore].freeze unless defined?(ALLOWED_ORDERS)
14
+
15
+ field :name, Symbol, :required => true
16
+ field :type, Icss::Meta::TypeFactory, :required => true
17
+ field :doc, String
18
+ field :default, Icss::Meta::IdenticalFactory
19
+ field :replace, Hash
20
+ field :required, Boolean
21
+ field :aliases, Array, :items => Symbol
22
+ field :order, String, :validates => { :inclusion => { :in => ALLOWED_ORDERS } }
23
+ field :accessor, Symbol
24
+ field :receiver, Symbol
25
+ field :validates, Hash
26
+ rcvr_remaining :_extra_params
27
+ attr_accessor :parent
28
+
29
+ # FIXME: cruft
30
+ field :indexed_on, Symbol
31
+ field :identifier, Boolean, :doc => 'indicates the field is suitable for use'
32
+
33
+ after_receive(:warnings) do |hsh|
34
+ # warn "Extra params given to field #{self}: #{_extra_params.inspect}" if _extra_params.present?
35
+ warn "Validation failed for field #{self}: #{errors.inspect}" if respond_to?(:errors) && (not valid?)
36
+ end
37
+
38
+ # track recursion of type references
39
+ after_receive(:am_i_a_reference) do |hsh|
40
+ hsh = hsh.symbolize_keys
41
+ nonreference_klasses = [::Icss::Meta::ArrayType, ::Icss::Meta::HashType, ::Icss::Meta::EnumType, ::Icss::Meta::FixedType]
42
+
43
+ @is_reference = (hsh[:type].is_a?(String) || hsh[:type].is_a?(Symbol) || (hsh[:type].is_a?(Class) && nonreference_klasses.none?{|klass| hsh[:type].is_a?(klass) }))
44
+ end
45
+
46
+ # is the field a reference to a named type (true), or an inline schema (false)?
47
+ def is_reference?() @is_reference ; end
48
+
49
+ def to_hash()
50
+ hsh = super
51
+ hsh = hsh.merge({ :type => (is_reference? ? type.fullname : Type.schema_for(type)) })
52
+ hsh.delete(:_extra_params)
53
+ hsh
54
+ end
55
+ def to_schema
56
+ to_hash
57
+ end
58
+
59
+ # Hack hack -- makes it so fields go thru the receiver door when merged in RecordType
60
+ def merge(hsh)
61
+ dup.receive!(hsh)
62
+ end
63
+
64
+ # Order is defined by the avro spec
65
+ def order() @order || 'ascending' ; end
66
+ def order_direction() case order when 'ascending' then 1 when 'descending' then -1 else 0 ; end ; end
67
+ end
68
+
69
+ module RecordType
70
+ protected
71
+ # create new field_schema as a RecordField object, not Hash
72
+ def make_field_schema
73
+ RecordField.new
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,49 @@
1
+ module Icss
2
+ module Meta
3
+
4
+ module RecordModel
5
+ def self.included(base)
6
+ base.extend(Icss::Meta::RecordType)
7
+ base.metamodel
8
+ end
9
+
10
+ #
11
+ # modify object in place with new typecast values.
12
+ #
13
+ def receive!(hsh={})
14
+ raise ArgumentError, "Can't receive (it isn't hashlike): {#{hsh.inspect}}" unless hsh.respond_to?(:[]) && hsh.respond_to?(:has_key?)
15
+ self.class.send(:_rcvr_methods).each do |attr, meth|
16
+ if hsh.has_key?(attr) then val = hsh[attr]
17
+ elsif hsh.has_key?(attr.to_s) then val = hsh[attr.to_s]
18
+ else next ; end
19
+ self.send(meth, val)
20
+ end
21
+ run_after_receivers(hsh)
22
+ self
23
+ end
24
+
25
+ # true if the attr is a receiver variable and it has been set
26
+ def attr_set?(attr)
27
+ self.class.has_field?(attr) && self.instance_variable_defined?("@#{attr}")
28
+ end
29
+
30
+ def unset!(attr)
31
+ self.send(:remove_instance_variable, "@#{attr}") if self.instance_variable_defined?("@#{attr}")
32
+ end
33
+ protected :unset!
34
+
35
+ protected
36
+
37
+ def run_after_receivers(hsh)
38
+ self.class.after_receivers.each do |after_hook_name, after_hook|
39
+ self.instance_exec(hsh, &after_hook)
40
+ end
41
+ end
42
+
43
+ def _set_field_val(field_name, val)
44
+ self.instance_variable_set("@#{field_name}", val)
45
+ end
46
+
47
+ end
48
+ end
49
+ end