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.
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