icss 0.0.2 → 0.0.4

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.
data/.rspec CHANGED
@@ -1,3 +1 @@
1
1
  --color
2
- --format documentation
3
- --drb
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source "http://rubygems.org"
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
6
  gem 'yajl-ruby', "~> 0.8.2"
7
- gem 'gorillib', "~> 0.0.7"
7
+ gem 'gorillib', "~> 0.0.4"
8
8
 
9
9
  # Add dependencies to develop your gem here.
10
10
  # Include everything needed to run rake, tests, features, etc.
data/Gemfile.lock CHANGED
@@ -26,7 +26,7 @@ PLATFORMS
26
26
 
27
27
  DEPENDENCIES
28
28
  bundler (~> 1.0.0)
29
- gorillib (~> 0.0.7)
29
+ gorillib (~> 0.0.4)
30
30
  jeweler (~> 1.5.2)
31
31
  rcov
32
32
  rspec (~> 2.3.0)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.4
data/icss.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{icss}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Philip (flip) Kromer for Infochimps"]
@@ -19,8 +19,6 @@ Gem::Specification.new do |s|
19
19
  s.files = [
20
20
  ".document",
21
21
  ".rspec",
22
- ".watchr",
23
- "CHANGELOG.textile",
24
22
  "Gemfile",
25
23
  "Gemfile.lock",
26
24
  "LICENSE.textile",
@@ -46,12 +44,16 @@ Gem::Specification.new do |s|
46
44
  "lib/icss.rb",
47
45
  "lib/icss/brevity.rb",
48
46
  "lib/icss/code_asset.rb",
49
- "lib/icss/core_ext.rb",
50
47
  "lib/icss/data_asset.rb",
51
48
  "lib/icss/message.rb",
52
49
  "lib/icss/old.rb",
53
50
  "lib/icss/protocol.rb",
54
51
  "lib/icss/protocol_set.rb",
52
+ "lib/icss/receiver.rb",
53
+ "lib/icss/receiver/acts_as_hash.rb",
54
+ "lib/icss/receiver/acts_as_loadable.rb",
55
+ "lib/icss/receiver/tree_diff.rb",
56
+ "lib/icss/receiver/validations.rb",
55
57
  "lib/icss/sample_message_call.rb",
56
58
  "lib/icss/target.rb",
57
59
  "lib/icss/type.rb",
@@ -64,7 +66,7 @@ Gem::Specification.new do |s|
64
66
  s.homepage = %q{http://github.com/mrflip/icss}
65
67
  s.licenses = ["MIT"]
66
68
  s.require_paths = ["lib"]
67
- s.rubygems_version = %q{1.7.2}
69
+ s.rubygems_version = %q{1.5.0}
68
70
  s.summary = %q{Infochimps Stupid Schema library: an avro-compatible data description standard. ICSS completely describes a collection of data (and associated assets) in a way that is expressive, scalable and sufficient to drive remarkably complex downstream processes.}
69
71
  s.test_files = [
70
72
  "spec/icss_spec.rb",
@@ -76,7 +78,7 @@ Gem::Specification.new do |s|
76
78
 
77
79
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
78
80
  s.add_runtime_dependency(%q<yajl-ruby>, ["~> 0.8.2"])
79
- s.add_runtime_dependency(%q<gorillib>, ["~> 0.0.7"])
81
+ s.add_runtime_dependency(%q<gorillib>, ["~> 0.0.4"])
80
82
  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
81
83
  s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
82
84
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -84,7 +86,7 @@ Gem::Specification.new do |s|
84
86
  s.add_development_dependency(%q<rcov>, [">= 0"])
85
87
  else
86
88
  s.add_dependency(%q<yajl-ruby>, ["~> 0.8.2"])
87
- s.add_dependency(%q<gorillib>, ["~> 0.0.7"])
89
+ s.add_dependency(%q<gorillib>, ["~> 0.0.4"])
88
90
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
89
91
  s.add_dependency(%q<yard>, ["~> 0.6.0"])
90
92
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -93,7 +95,7 @@ Gem::Specification.new do |s|
93
95
  end
94
96
  else
95
97
  s.add_dependency(%q<yajl-ruby>, ["~> 0.8.2"])
96
- s.add_dependency(%q<gorillib>, ["~> 0.0.7"])
98
+ s.add_dependency(%q<gorillib>, ["~> 0.0.4"])
97
99
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
98
100
  s.add_dependency(%q<yard>, ["~> 0.6.0"])
99
101
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
data/lib/icss/protocol.rb CHANGED
@@ -105,7 +105,7 @@ module Icss
105
105
 
106
106
  def receive_targets hsh
107
107
  self.targets = hsh.inject({}) do |target_obj_hsh, (target_name, target_info_list)|
108
- target_obj_hsh[target_name] = TargetListFactory.receive(target_info_list, target_name) # returns an arry of targets
108
+ target_obj_hsh[target_name] = TargetListFactory.receive(target_name, target_info_list) # returns an arry of targets
109
109
  target_obj_hsh
110
110
  end
111
111
  end
@@ -0,0 +1,436 @@
1
+ module Receiver
2
+
3
+ #
4
+ # Makes a Receiver thingie behave mostly like a hash.
5
+ #
6
+ # By default, the hashlike methods iterate over the receiver attributes:
7
+ # instance #keys delegates to self.class.keys which calls
8
+ # receiver_attr_names. If you want to filter our add to the keys list, you
9
+ # can just override the class-level keys method (and call super, or not):
10
+ #
11
+ # def self.keys
12
+ # super + [:firstname, :lastname] - [:fullname]
13
+ # end
14
+ #
15
+ # All methods are defined naturally on [], []= and has_key? -- if you enjoy
16
+ #
17
+ #
18
+ # in addition to the below, by including Enumerable, this also adds
19
+ #
20
+ # #all?, #any?, #chunk, #collect, #collect_concat, #count, #cycle, #detect,
21
+ # #drop, #drop_while, #each_cons, #each_entry, #each_slice,
22
+ # #each_with_index, #each_with_object, #entries, #find, #find_all,
23
+ # #find_index, #first, #flat_map, #grep, #group_by, #inject, #map, #max,
24
+ # #max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition,
25
+ # #reduce, #reverse_each, #slice_before, #sort, #sort_by, #take,
26
+ # #take_while, #zip
27
+ #
28
+ # As opposed to hash, does *not* define
29
+ #
30
+ # default, default=, default_proc, default_proc=, shift
31
+ # length, size, empty?, flatten, replace, keep_if, key(value)
32
+ # compare_by_identity compare_by_identity? rehash, select!
33
+ #
34
+ # assoc rassoc
35
+ #
36
+ module ActsAsHash
37
+
38
+ # Fake hash reader semantics: delegates to self.send(key)
39
+ #
40
+ # Note: indifferent access -- either of :foo or "foo" will work
41
+ #
42
+ def [](name)
43
+ self.send(name) if keys.include?(name.to_sym)
44
+ end
45
+
46
+ # Fake hash writer semantics: delegates to self.send("key=", val)
47
+ #
48
+ # NOTE: this calls self.foo= 5, not self.receive_foo(5)
49
+ # NOTE: indifferent access -- either of :foo or "foo" will work
50
+ #
51
+ def []=(name, val)
52
+ self.send("#{name}=", val) if keys.include?(name)
53
+ end
54
+ alias_method(:store, :[]=)
55
+
56
+ # @param key<Object> The key to check for.
57
+ #
58
+ # @return [Boolean] True if
59
+ # * the attribute is one of this object's keys, and
60
+ # * its value is non-nil OR the corresponding instance_variable is defined.
61
+ #
62
+ # For attributes that are virtual accessors, if its value is explicitly set
63
+ # to nil then has_key? is true.
64
+ #
65
+ # @example
66
+ # class Foo
67
+ # include Receiver
68
+ # include Receiver::ActsAsHash
69
+ # rcvr_accessor :a, Integer
70
+ # rcvr_accessor :b, String
71
+ # end
72
+ # foo = Foo.receive({:a => 1})
73
+ # foo.has_key?(:b) # false
74
+ # foo[:b] # nil
75
+ # foo.b = nil
76
+ # foo.has_key?(:b) # true
77
+ # foo[:b] # nil
78
+ #
79
+ def has_key?(key)
80
+ keys.include?(key) && ((not self[key].nil?) || attr_set?(key))
81
+ end
82
+
83
+ # @param key<Object> The key to remove
84
+ #
85
+ # @return [Object]
86
+ # returns the value of the given attribute, and sets its new value to nil.
87
+ # If there is a corresponding instance_variable, it is subsequently removed.
88
+ def delete(key)
89
+ val = self[key]
90
+ self[key]= nil
91
+ unset!(key)
92
+ val
93
+ end
94
+
95
+ #
96
+ # Convert to a hash
97
+ #
98
+ # Each key in #keys becomes an element in the new array if the value of its
99
+ # attribute is non-nil OR the corresponding instance_variable is defined.
100
+ def to_hash
101
+ keys.inject({}) do |hsh, key|
102
+ val = self[key]
103
+ hsh[key] = val if (val || self.instance_variable_defined?("@#{key}"))
104
+ hsh
105
+ end
106
+ end
107
+
108
+ module ClassMethods
109
+ # By default, the hashlike methods iterate over the receiver attributes.
110
+ # If you want to filter our add to the keys list, override this method
111
+ #
112
+ # @example
113
+ # def self.keys
114
+ # super + [:firstname, :lastname] - [:fullname]
115
+ # end
116
+ #
117
+ def keys
118
+ receiver_attr_names
119
+ end
120
+ end
121
+
122
+ # ===========================================================================
123
+ #
124
+ # The below methods are natural extensions of the above
125
+ #
126
+
127
+ # delegates to the class method. Typically you'll want to override that one,
128
+ # not the instance keys
129
+ def keys
130
+ self.class.keys
131
+ end
132
+
133
+ # Returns an array consisting of the value for each attribute in
134
+ # #keys, guaranteed in same order
135
+ def values
136
+ values_at *keys
137
+ end unless method_defined?(:values)
138
+
139
+ # Returns an array consisting of the value for each attribute in
140
+ # allowed_keys, guaranteed in same order
141
+ def values_at *allowed_keys
142
+ allowed_keys.map do |k|
143
+ self[k]
144
+ end
145
+ end
146
+
147
+ # a nested array of [ key, value ] pairs. Delegates to to_hash.to_a
148
+ def to_a
149
+ to_hash.to_a
150
+ end
151
+
152
+ # @return [Hash] the object as a Hash with symbolized keys.
153
+ def symbolize_keys() to_hash ; end
154
+ # @return [Hash] the object as a Hash with string keys.
155
+ def stringify_keys() to_hash.stringify_keys ; end
156
+
157
+ # Used to provide the same interface as Hash.
158
+ # @return This object unchanged.
159
+ def symbolize_keys!; self end
160
+
161
+ # Used to provide the same interface as Hash.
162
+ # @return This object unchanged.
163
+ def stringify_keys!; self end
164
+
165
+ #
166
+ # Return a Hash containing only values for the given keys where self.has_key?(k)
167
+ #
168
+ def slice *allowed_keys
169
+ allowed_keys.inject({}){|h,k| h[k] = self[k] if self.has_key?(k) ; h }
170
+ end
171
+
172
+ # Calls block once for each key in #keys in order, passing the key and value as parameters.
173
+ def each &block
174
+ keys.each do |key|
175
+ yield(key, self[key])
176
+ end
177
+ end
178
+ alias_method :each_pair, :each
179
+
180
+ # Calls block once for each key in #keys in order, passing the key as parameter.
181
+ def each_key &block
182
+ keys.each(&block)
183
+ end
184
+
185
+ # Calls block once for each key in #keys in order, passing the value as parameter.
186
+ def each_value &block
187
+ keys.each do |key|
188
+ yield self[key]
189
+ end
190
+ end
191
+
192
+ #
193
+ # Analogous to Hash#merge: returns a duplicate of self where for each
194
+ # element of self.keys, adopts the corresponding element of hsh if that key
195
+ # is set in hsh.
196
+ #
197
+ # Returns a duplicate of self, but adopting the corresponding element of hsh
198
+ # if that key is set in hsh. Only keys in self.keys are candidates for merging.
199
+ #
200
+ # With no block parameter, overwrites entries in hsh with duplicate keys
201
+ # with those from other_hash.
202
+ #
203
+ # The block parameter semantics aren't implemented yet. If a block is
204
+ # specified, it is called with each duplicate key and the values from the
205
+ # two hashes. The value returned by the block is stored in the new hash.
206
+ #
207
+ # @example
208
+ # h1 = { "a" => 100, "b" => 200 }
209
+ # h2 = { "b" => 254, "c" => 300 }
210
+ # h1.merge(h2) -> {"a"=>100, "b"=>254, "c"=>300}
211
+ # h1.merge(h2){|k,o,n| o} -> {"a"=>100, "b"=>200, "c"=>300}
212
+ # h1 -> {"a"=>100, "b"=>200}
213
+ #
214
+ def merge *args, &block
215
+ self.dup.merge!(*args, &block)
216
+ end
217
+
218
+ # For all keys that are in self.keys *and* other_hash.has_key?(key),
219
+ # sets the value to that from other_hash
220
+ #
221
+ def update other_hash, &block
222
+ raise "can't handle block arg yet" if block
223
+ keys.each do |key|
224
+ self[key] = other_hash[key] if other_hash.has_key?(key)
225
+ end
226
+ self
227
+ end
228
+ alias_method :merge!, :update
229
+
230
+ # # Returns a new hash with +self+ and +other_hash+ merged recursively.
231
+ # def deep_merge(other_hash)
232
+ # dup.deep_merge!(other_hash)
233
+ # end
234
+
235
+ # Recursively merges using receive
236
+ #
237
+ # Modifies the full receiver chain in-place.
238
+ #
239
+ # For each key in keys,
240
+ # * if self's value is nil, receive the attribute.
241
+ # * if self's attribute is an Array, append to it.
242
+ # * if self's value responds to tree_merge!, tree merge it.
243
+ # * if self's value responds_to merge!, merge! it.
244
+ # * otherwise, receive the value from other_hash
245
+ #
246
+ def tree_merge!(other_hash)
247
+ keys.each do |key|
248
+ # get other's val if any
249
+ if other_hash.has_key?(key.to_sym) then other_val = other_hash[key.to_sym]
250
+ elsif other_hash.has_key?(key.to_s) then other_val = other_hash[key.to_s]
251
+ else next ; end
252
+ #
253
+ self_val = self[key]
254
+ # p ['receiver tree_merge', key, self_val.respond_to?(:tree_merge!), self[key], other_val]
255
+ case
256
+ when other_val.nil? then next
257
+ when (not has_key?(key)) then _receive_attr(key, other_val)
258
+ when receiver_attrs[key][:merge_as] == :hash_of_arrays
259
+ self_val.merge!(other_val) do |k, v1, v2| case when v1.blank? then v2 when v2.blank? then v1 else v1 + v2 end end
260
+ when self_val.is_a?(Array) then self[key] += other_val
261
+ when self_val.respond_to?(:tree_merge!) then self[key] = self_val.tree_merge!(other_val)
262
+ when self_val.respond_to?(:merge!) then self[key] = self_val.merge!(other_val)
263
+ else _receive_attr(key, other_val)
264
+ end
265
+ end
266
+ run_after_receivers(other_hash)
267
+ self
268
+ end
269
+
270
+ # Searches the hash for an entry whose value == value, returning the
271
+ # corresponding key. If multiple entries has this value, the key returned
272
+ # will be that on one of the entries. If not found,returns nil.
273
+ #
274
+ # You are guaranteed that the first matching key in #keys will be the one
275
+ # returned.
276
+ #
277
+ # @example
278
+ # foo = Foo.receive( "a" => 100, "b" => 200, "c" => 100 )
279
+ # foo.index(100) -> "a"
280
+ # foo.index(999) -> nil
281
+ #
282
+ def index val
283
+ keys.find{|key| self[key] == val }
284
+ end
285
+
286
+ # Returns a new hash created by using inverting self.to_hash. If this new
287
+ # hash has duplicate values, the result will contain only one of them as a
288
+ # key -- which one is not predictable.
289
+ def invert
290
+ to_hash.invert
291
+ end
292
+
293
+ # Returns true if the given value is present for some attribute in #keys
294
+ def has_value? val
295
+ !! index(val)
296
+ end
297
+ alias_method :value?, :has_value?
298
+
299
+ # def include? def key? def member?
300
+ alias_method :include?, :has_key?
301
+ alias_method :key?, :has_key?
302
+ alias_method :member?, :has_key?
303
+
304
+ # Deletes every attribute for which block is true.
305
+ # Returns nil if no changes were made, self otherwise.
306
+ def reject!(&block)
307
+ changed = false
308
+ each do |key, val|
309
+ if yield(key, val)
310
+ changed = true
311
+ delete(key)
312
+ end
313
+ end
314
+ changed ? self : nil
315
+ end
316
+
317
+ # Deletes every attribute for which block is true.
318
+ # Similar to reject! but returns self.
319
+ def delete_if(&block)
320
+ reject!(&block)
321
+ self
322
+ end
323
+
324
+ # Deletes every attribute for which block is true.
325
+ # Equivalent to self.dup.delete_if.
326
+ def reject(&block)
327
+ self.dup.delete_if(&block)
328
+ end
329
+
330
+ # deletes all attributes
331
+ def clear
332
+ each_key{|k| delete(k) }
333
+ end
334
+
335
+ # delete all attributes where the value is blank?, and return self. Contrast with compact!
336
+ def compact_blank!
337
+ delete_if{|k,v| v.blank? }
338
+ end
339
+ # delete all attributes where the value is nil?, and return self. Contrast with compact_blank!
340
+ def compact!
341
+ delete_if{|k,v| v.nil? }
342
+ end
343
+ # returns a hash with key/value pairs having nil? values removed
344
+ def compact
345
+ to_hash.delete_if{|k,v| v.nil? }
346
+ end
347
+ # returns a hash with key/value pairs having blank? values removed
348
+ def compact_blank
349
+ to_hash.delete_if{|k,v| v.blank? }
350
+ end
351
+
352
+ def self.included base
353
+ base.class_eval do
354
+ extend ClassMethods
355
+ include Enumerable
356
+ end
357
+ end
358
+
359
+ #
360
+ # Not yet implemented
361
+ #
362
+
363
+ # # Returns true if has_key? is false for all attributes in #keys
364
+ # def empty?
365
+ # keys.all?{|key| not has_key?(key) }
366
+ # end
367
+ #
368
+ # # The number of keys where #has_key is true
369
+ # def length
370
+ # keys.select{|key| has_key?(key) }.length
371
+ # end
372
+ # alias_method :size, :length
373
+
374
+ # # @param key<Object> The key to fetch.
375
+ # # @param *extras<Array> Default value.
376
+ # #
377
+ # # Returns a value for the given key. If the object doesn't has_key?(key),
378
+ # # several options exist:
379
+ # #
380
+ # # * With no other arguments, it will raise an IndexError exception;
381
+ # # * if default is given, then that will be returned;
382
+ # # * if the optional code block is specified, then that will be run and its
383
+ # # result returned.
384
+ # #
385
+ # # fetch does not evaluate any default values supplied when
386
+ # # the hash was created -- it only looks for keys in the hash.
387
+ # #
388
+ # # @return [Object] The value at key or the default value.
389
+ # def fetch(key, default=nil, &block)
390
+ # raise ""
391
+ # end
392
+
393
+
394
+ end
395
+ end
396
+
397
+
398
+ class Hash
399
+
400
+ # Recursively merges using receive
401
+ #
402
+ # Modifies the full receiver chain in-place.
403
+ #
404
+ # For each key in keys,
405
+ # * if self's value is nil, receive the attribute.
406
+ # * if self's attribute is an Array, append to it.
407
+ # * if self's value responds to tree_merge!, deep merge it.
408
+ # * if self's value responds_to merge!, merge! it.
409
+ # * otherwise, receive the value from other_hash
410
+ #
411
+ def tree_merge!(other_hash)
412
+ [self.keys, other_hash.keys].flatten.uniq.each do |key|
413
+ # get other's val if any
414
+ if other_hash.has_key?(key.to_sym) then other_val = other_hash[key.to_sym]
415
+ elsif other_hash.has_key?(key.to_s) then other_val = other_hash[key.to_s]
416
+ else next ; end
417
+ #
418
+ self_val = self[key]
419
+ # p ['hash tree_merge', key, self_val.respond_to?(:tree_merge!), self_val, other_val]
420
+ case
421
+ when other_val.nil? then next
422
+ when (not has_key?(key)) then self[key] = other_val
423
+ when self_val.is_a?(Array) then self[key] += other_val
424
+ when self_val.respond_to?(:tree_merge!) then self[key] = self_val.tree_merge!(other_val)
425
+ when self_val.respond_to?(:merge!) then self[key] = self_val.merge!(other_val)
426
+ else self[key] = other_val
427
+ end
428
+ end
429
+ self
430
+ end
431
+
432
+ def compact_blank!
433
+ reject!{|k,v| v.blank? } ; self
434
+ end
435
+
436
+ end
@@ -0,0 +1,42 @@
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
@@ -0,0 +1,74 @@
1
+ module Receiver
2
+ def tree_diff(other)
3
+ diff_hsh = {}
4
+ other = other.symbolize_keys if other.respond_to?(:symbolize_keys)
5
+ each do |k, v|
6
+ case
7
+ when v.is_a?(Array) && other[k].is_a?(Array)
8
+ val = v.tree_diff(other[k])
9
+ diff_hsh[k] = val unless val.blank?
10
+ when v.respond_to?(:tree_diff) && other[k].respond_to?(:to_hash)
11
+ val = v.tree_diff(other[k])
12
+ diff_hsh[k] = val unless val.blank?
13
+ else
14
+ diff_hsh[k] = v unless v == other[k]
15
+ end
16
+ end
17
+ other_hsh = other.dup.delete_if{|k, v| has_key?(k) }
18
+ diff_hsh.merge!(other_hsh)
19
+ end
20
+
21
+ module ActsAsHash
22
+ def <=>(other)
23
+ return 1 if other.blank?
24
+ each_key do |k|
25
+ if has_key?(k) && other.has_key?(k)
26
+ cmp = self[k] <=> other[k]
27
+ return cmp unless cmp == 0
28
+ end
29
+ end
30
+ 0
31
+ end
32
+ end
33
+ end
34
+
35
+ class Array
36
+ def tree_diff(other)
37
+ arr = dup
38
+ if other.length > arr.length then arr = arr + ([nil] * (other.length - arr.length)) end
39
+ diff_ary = arr.zip(other).map do |arr_el, other_el|
40
+ if arr_el.respond_to?(:tree_diff) && other_el.respond_to?(:to_hash)
41
+ arr_el.tree_diff(other_el)
42
+ else
43
+ (arr_el == other_el) ? nil : [arr_el, other_el]
44
+ end
45
+ end.reject(&:blank?)
46
+ end
47
+ end
48
+
49
+ class Hash
50
+ # Returns a hash that represents the difference between two hashes.
51
+ #
52
+ # Examples:
53
+ #
54
+ # {1 => 2}.tree_diff(1 => 2) # => {}
55
+ # {1 => 2}.tree_diff(1 => 3) # => {1 => 2}
56
+ # {}.tree_diff(1 => 2) # => {1 => 2}
57
+ # {1 => 2, 3 => 4}.tree_diff(1 => 2) # => {3 => 4}
58
+ def tree_diff(other)
59
+ diff_hsh = self.dup
60
+ each do |k, v|
61
+ case
62
+ when v.is_a?(Array) && other[k].is_a?(Array)
63
+ diff_hsh[k] = v.tree_diff(other[k])
64
+ diff_hsh.delete(k) if diff_hsh[k].blank?
65
+ when v.respond_to?(:tree_diff) && other[k].respond_to?(:to_hash)
66
+ diff_hsh[k] = v.tree_diff(other[k])
67
+ diff_hsh.delete(k) if diff_hsh[k].blank?
68
+ else diff_hsh.delete(k) if v == other[k]
69
+ end
70
+ end
71
+ other_hsh = other.dup.delete_if{|k, v| has_key?(k) || has_key?(k.to_s) }
72
+ diff_hsh.merge!(other_hsh)
73
+ end
74
+ end
@@ -0,0 +1,30 @@
1
+ module Receiver
2
+
3
+ # An array of strings describing any ways this fails validation
4
+ def validation_errors
5
+ errors = []
6
+ if (ma = missing_attrs).present?
7
+ errors << "Missing values for {#{ma.join(",")}}"
8
+ end
9
+ errors
10
+ end
11
+
12
+ # returns a list of required but missing attributes
13
+ def missing_attrs
14
+ missing = []
15
+ self.class.required_rcvrs.each do |name, info|
16
+ missing << name if (not attr_set?(name))
17
+ end
18
+ missing
19
+ end
20
+
21
+ # methods become class-level
22
+ module ClassMethods
23
+
24
+ # class method gives info for all receiver attributes with required => true
25
+ def required_rcvrs
26
+ receiver_attrs.select{|name, info| info[:required] }
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,289 @@
1
+ require 'active_support/core_ext/class'
2
+ require 'time'
3
+ require 'icss/receiver/validations'
4
+
5
+ # dummy type for receiving True or False
6
+ class Boolean ; end unless defined?(Boolean)
7
+
8
+ # Receiver lets you describe complex (even recursive!) actively-typed data models that
9
+ # * are creatable or assignable from static data structures
10
+ # * perform efficient type conversion when assigning from a data structure,
11
+ # * but with nothing in the way of normal assignment or instantiation
12
+ # * and no requirements on the initializer
13
+ #
14
+ # class Tweet
15
+ # include Receiver
16
+ # rcvr_accessor :id, Integer
17
+ # rcvr_accessor :user_id, Integer
18
+ # rcvr_accessor :created_at, Time
19
+ # end
20
+ # p Tweet.receive(:id => "7", :user_id => 9, :created_at => "20101231010203" )
21
+ # # => #<Tweet @id=7, @user_id=9, @created_at=2010-12-31 07:02:03 UTC>
22
+ #
23
+ # You can override receive behavior in a straightforward and predictable way:
24
+ #
25
+ # class TwitterUser
26
+ # include Receiver
27
+ # rcvr_accessor :id, Integer
28
+ # rcvr_accessor :screen_name, String
29
+ # rcvr_accessor :follower_ids, Array, :of => Integer
30
+ # # accumulate unique follower ids
31
+ # def receive_follower_ids(arr)
32
+ # @follower_ids = (@follower_ids||[]) + arr.map(&:to_i)
33
+ # @follower_ids.uniq!
34
+ # end
35
+ # end
36
+ #
37
+ # The receiver pattern works naturally with inheritance:
38
+ #
39
+ # class TweetWithUser < Tweet
40
+ # rcvr_accessor :user, TwitterUser
41
+ # after_receive do |hsh|
42
+ # self.user_id = self.user.id if self.user
43
+ # end
44
+ # end
45
+ # p TweetWithUser.receive(:id => 8675309, :created_at => "20101231010203", :user => { :id => 24601, :screen_name => 'bob', :follower_ids => [1, 8, 3, 4] })
46
+ # => #<TweetWithUser @id=8675309, @created_at=2010-12-31 07:02:03 UTC, @user=#<TwitterUser @id=24601, @screen_name="bob", @follower_ids=[1, 8, 3, 4]>, @user_id=24601>
47
+ #
48
+ # TweetWithUser was able to add another receiver, applicable only to itself and its subclasses.
49
+ #
50
+ # The receive method works well with sparse data -- you can accumulate
51
+ # attributes without trampling formerly set values:
52
+ #
53
+ # tw = Tweet.receive(:id => "7", :user_id => 9 )
54
+ # p tw
55
+ # # => #<Tweet @id=7, @user_id=9>
56
+ #
57
+ # tw.receive!(:created_at => "20101231010203" )
58
+ # p tw
59
+ # # => #<Tweet @id=7, @user_id=9, @created_at=2010-12-31 07:02:03 UTC>
60
+ #
61
+ # Note the distinction between an explicit nil field and a missing field:
62
+ #
63
+ # tw.receive!(:user_id => nil, :created_at => "20090506070809" )
64
+ # p tw
65
+ # # => #<Tweet @id=7, @user_id=nil, @created_at=2009-05-06 12:08:09 UTC>
66
+ #
67
+ # There are helpers for default and required attributes:
68
+ #
69
+ # class Foo
70
+ # include Receiver
71
+ # rcvr_accessor :is_reqd, String, :required => true
72
+ # rcvr_accessor :also_reqd, String, :required => true
73
+ # rcvr_accessor :has_default, String, :default => 'hello'
74
+ # end
75
+ # foo_obj = Foo.receive(:is_reqd => "hi")
76
+ # # => #<Foo:0x00000100bd9740 @is_reqd="hi" @has_default="hello">
77
+ # foo_obj.missing_attrs
78
+ # # => [:also_reqd]
79
+ #
80
+ module Receiver
81
+
82
+ RECEIVER_BODIES = {} unless defined?(RECEIVER_BODIES)
83
+ RECEIVER_BODIES[Symbol] = %q{ v.nil? ? nil : v.to_sym }
84
+ RECEIVER_BODIES[String] = %q{ v.to_s }
85
+ RECEIVER_BODIES[Integer] = %q{ v.nil? ? nil : v.to_i }
86
+ RECEIVER_BODIES[Float] = %q{ v.nil? ? nil : v.to_f }
87
+ RECEIVER_BODIES[Time] = %q{ v.nil? ? nil : Time.parse(v.to_s).utc }
88
+ RECEIVER_BODIES[Date] = %q{ v.nil? ? nil : Date.parse(v.to_s) }
89
+ RECEIVER_BODIES[Array] = %q{ v.nil? ? nil : v }
90
+ RECEIVER_BODIES[Hash] = %q{ v.nil? ? nil : v }
91
+ RECEIVER_BODIES[Boolean] = %q{ v.nil? ? nil : (v.to_s.strip != "false") }
92
+ RECEIVER_BODIES[NilClass] = %q{ raise "This field must be nil, but #{v} was given" unless (v.nil?) ; nil }
93
+ RECEIVER_BODIES[Object] = %q{ v } # accept and love the object just as it is
94
+ RECEIVER_BODIES.each do |k,b|
95
+ if k.is_a?(Class)
96
+ k.class_eval <<-STR, __FILE__, __LINE__ + 1
97
+ def self.receive(v)
98
+ #{b}
99
+ end
100
+ STR
101
+ end
102
+ end
103
+
104
+ TYPE_ALIASES = {
105
+ :null => NilClass,
106
+ :boolean => Boolean,
107
+ :string => String, :bytes => String,
108
+ :symbol => Symbol,
109
+ :int => Integer, :integer => Integer, :long => Integer,
110
+ :time => Time, :date => Date,
111
+ :float => Float, :double => Float,
112
+ :hash => Hash, :map => Hash,
113
+ :array => Array,
114
+ } unless defined?(TYPE_ALIASES)
115
+
116
+ #
117
+ # modify object in place with new typecast values.
118
+ #
119
+ def receive! hsh
120
+ raise "Can't receive (it isn't hashlike): #{hsh.inspect}" unless hsh.respond_to?(:[])
121
+ self.class.receiver_attr_names.each do |attr|
122
+ if hsh.has_key?(attr.to_sym) then val = hsh[attr.to_sym]
123
+ elsif hsh.has_key?(attr.to_s) then val = hsh[attr.to_s]
124
+ else next ; end
125
+ _receive_attr attr, val
126
+ end
127
+ impose_defaults!(hsh)
128
+ run_after_receivers(hsh)
129
+ self
130
+ end
131
+
132
+ def unset!(attr)
133
+ self.send(:remove_instance_variable, "@#{attr}") if self.instance_variable_defined?("@#{attr}")
134
+ end
135
+
136
+ # true if the attr is a receiver variable and it has been set
137
+ def attr_set?(attr)
138
+ receiver_attrs.has_key?(attr) && self.instance_variable_defined?("@#{attr}")
139
+ end
140
+
141
+ protected
142
+ def _receive_attr attr, val
143
+ self.send("receive_#{attr}", val)
144
+ end
145
+
146
+ def impose_defaults!(hsh)
147
+ self.class.receiver_defaults.each do |attr, val|
148
+ next if attr_set?(attr)
149
+ self.instance_variable_set "@#{attr}", val
150
+ end
151
+ end
152
+
153
+ def run_after_receivers(hsh)
154
+ self.class.after_receivers.each do |after_receiver|
155
+ self.instance_exec(hsh, &after_receiver)
156
+ end
157
+ end
158
+ public
159
+
160
+ module ClassMethods
161
+
162
+ #
163
+ # Returns a new instance with the given hash used to set all rcvrs.
164
+ #
165
+ # All args after the first are passed to the initializer.
166
+ #
167
+ def receive hsh, *args
168
+ hsh ||= {}
169
+ obj = self.new(*args)
170
+ obj.receive!(hsh)
171
+ end
172
+
173
+ #
174
+ # define a receiver attribute.
175
+ # automatically generates an attr_accessor on the class if none exists
176
+ #
177
+ # @option [Boolean] :required - Adds an error on validation if the attribute is never set
178
+ # @option [Object] :default - After any receive! operation, attribute is set to this value unless attr_set? is true
179
+ # @option [Class] :of - For collections (Array, Hash, etc), the type of the collection's items
180
+ #
181
+ def rcvr name, type, info={}
182
+ name = name.to_sym
183
+ type = type_to_klass(type)
184
+ class_eval <<-STR, __FILE__, __LINE__ + 1
185
+ def receive_#{name}(v)
186
+ self.#{name} = #{receiver_body_for(type, info)}
187
+ end
188
+ STR
189
+ receiver_attr_names << name unless receiver_attr_names.include?(name)
190
+ receiver_attrs[name] = info.merge({ :name => name, :type => type })
191
+ end
192
+
193
+ def after_receive &block
194
+ self.after_receivers << block
195
+ end
196
+
197
+ def type_to_klass(type)
198
+ case
199
+ when type.is_a?(Class) then return type
200
+ when TYPE_ALIASES.has_key?(type) then TYPE_ALIASES[type]
201
+ # when (type.is_a?(Symbol) && type.to_s =~ /^[A-Z]/) then type.to_s.constantize
202
+ else raise "Can\'t handle type #{type}: is it a Class or one of the TYPE_ALIASES? "
203
+ end
204
+ end
205
+
206
+ # defines a receiver attribute, an attr_reader and an attr_writer
207
+ # attr_reader is skipped if the getter method is already defined;
208
+ # attr_writer is skipped if the setter method is already defined;
209
+ def rcvr_accessor name, type, info={}
210
+ attr_reader(name) unless method_defined?(name)
211
+ attr_writer(name) unless method_defined?("#{name}=")
212
+ rcvr name, type, info
213
+ end
214
+ # defines a receiver attribute and an attr_reader
215
+ # attr_reader is skipped if the getter method is already defined.
216
+ def rcvr_reader name, type, info={}
217
+ attr_reader(name) unless method_defined?(name)
218
+ rcvr name, type, info
219
+ end
220
+ # defines a receiver attribute and an attr_writer
221
+ # attr_writer is skipped if the setter method is already defined.
222
+ def rcvr_writer name, type, info={}
223
+ attr_writer(name) unless method_defined?("#{name}=")
224
+ rcvr name, type, info
225
+ end
226
+
227
+ #
228
+ # Defines a receiver for attributes sent to receive! that are
229
+ # * not defined as receivers
230
+ # * attribute name does not start with '_'
231
+ #
232
+ # @example
233
+ # class Foo ; include Receiver
234
+ # rcvr_accessor :bob, String
235
+ # rcvr_remaining :other_params
236
+ # end
237
+ # foo_obj = Foo.receive(:bob => 'hi, bob", :joe => 'hi, joe')
238
+ # # => <Foo @bob='hi, bob' @other_params={ :joe => 'hi, joe' }>
239
+ def rcvr_remaining name, info={}
240
+ rcvr_reader name, Hash, info
241
+ after_receive do |hsh|
242
+ remaining_vals_hsh = hsh.except(* keys).reject!{|k,v| k.to_s =~ /^_/}
243
+ self._receive_attr name, remaining_vals_hsh
244
+ end
245
+ end
246
+
247
+ # a hash from attribute names to their default values if given
248
+ def receiver_defaults
249
+ defs = {}
250
+ receiver_attrs.each do |name, info|
251
+ defs[name] = info[:default] if info.has_key?(:default)
252
+ end
253
+ defs
254
+ end
255
+
256
+ private
257
+ def receiver_body_for type, info
258
+ type = type_to_klass(type)
259
+ # Note that Array and Hash only need (and only get) special treatment when
260
+ # they have an :of => SomeType option.
261
+ case
262
+ when info[:of] && (type == Array)
263
+ %Q{ v.nil? ? nil : v.map{|el| #{info[:of]}.receive(el) } }
264
+ when info[:of] && (type == Hash)
265
+ %Q{ v.nil? ? nil : v.inject({}){|h, (el,val)| h[el] = #{info[:of]}.receive(val); h } }
266
+ when Receiver::RECEIVER_BODIES.include?(type)
267
+ Receiver::RECEIVER_BODIES[type]
268
+ when type.is_a?(Class)
269
+ %Q{v.blank? ? nil : #{type}.receive(v) }
270
+ # when (type.is_a?(Symbol) && type.to_s =~ /^[A-Z]/)
271
+ # # a hack so you can use a class not defined yet
272
+ # %Q{v.blank? ? nil : #{type}.receive(v) }
273
+ else
274
+ raise("Can't receive #{type} #{info}")
275
+ end
276
+ end
277
+ end
278
+
279
+ # set up receiver attributes, and bring in methods from the ClassMethods module at class-level
280
+ def self.included base
281
+ base.class_eval do
282
+ class_inheritable_accessor :receiver_attrs, :receiver_attr_names, :after_receivers
283
+ self.receiver_attrs = {} # info about the attr
284
+ self.receiver_attr_names = [] # ordered set of attr names
285
+ self.after_receivers = [] # blocks to execute following receive!
286
+ extend ClassMethods
287
+ end
288
+ end
289
+ end
data/lib/icss/type.rb CHANGED
@@ -128,7 +128,7 @@ module Icss
128
128
  rcvr_accessor :namespace, String
129
129
  attr_accessor :parent
130
130
  # the avro base type name
131
- class_attribute :type
131
+ class_inheritable_accessor :type
132
132
  include Icss::Validations
133
133
 
134
134
  # In named types, the namespace and name are determined in one of the following ways:
@@ -385,8 +385,7 @@ module Icss
385
385
  # (do not confuse with EnumType, which is not an EnumerableType. sigh).
386
386
  #
387
387
  class EnumerableType < Type
388
- class_attribute :type
389
- class_attribute :ruby_klass
388
+ class_inheritable_accessor :type, :ruby_klass
390
389
  def to_hash
391
390
  super.merge( :type => type.to_s )
392
391
  end
@@ -489,7 +488,7 @@ module Icss
489
488
  #
490
489
  class FixedType < NamedType
491
490
  rcvr_accessor :size, Integer, :required => true
492
- class_attribute :ruby_klass
491
+ class_inheritable_accessor :ruby_klass
493
492
  self.type = :fixed
494
493
  self.ruby_klass = String
495
494
 
data/lib/icss.rb CHANGED
@@ -1,12 +1,12 @@
1
- require 'icss/core_ext' unless Object.respond_to?(:class_attribute)
2
-
3
- require 'gorillib/receiver'
4
- require 'gorillib/receiver/acts_as_hash'
5
- require 'gorillib/receiver/acts_as_loadable'
6
- require 'gorillib/receiver/validations'
7
- require 'time' # ain't that always the way
1
+ require 'active_support/inflector' # for classify and constantize
2
+ require 'active_support/core_ext/hash/keys'
3
+ # require 'active_support/core_ext/hash/deep_merge'
8
4
 
9
5
  $: << File.dirname(__FILE__)
6
+ require 'icss/receiver'
7
+ require 'icss/receiver/acts_as_hash'
8
+ require 'icss/receiver/acts_as_loadable'
9
+ #
10
10
  require 'icss/validations'
11
11
  require 'icss/type'
12
12
  require 'icss/message'
data/spec/spec_helper.rb CHANGED
@@ -1,31 +1,12 @@
1
- require 'spork'
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
3
  require 'rspec'
4
+ require 'icss'
3
5
 
4
- Spork.prefork do
5
- # This code is run only once when the spork server is started
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
6
9
 
7
- ENV["RACK_ENV"] ||= 'test'
8
- RACK_ENV = ENV["RACK_ENV"] unless defined?(RACK_ENV)
9
-
10
- require File.join(File.dirname(__FILE__), '../lib/boot')
11
- $LOAD_PATH.unshift(File.dirname(__FILE__))
12
-
13
- require 'goliath'
14
- require 'em-synchrony'
15
- require 'goliath/test_helper'
16
- require 'support/test_helper'
17
-
18
- # Requires custom matchers & macros, etc from files in ./support/ & subdirs
19
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
20
-
21
- # Configure rspec
22
- RSpec.configure do |config|
23
- config.include Goliath::TestHelper, :example_group => {
24
- :file_path => /spec/
25
- }
26
- end
27
- end
28
-
29
- Spork.each_run do
30
- # This code will be run each time you run your specs.
10
+ RSpec.configure do |config|
11
+
31
12
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icss
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
4
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 2
10
- version: 0.0.2
5
+ version: 0.0.4
11
6
  platform: ruby
12
7
  authors:
13
8
  - Philip (flip) Kromer for Infochimps
@@ -15,118 +10,86 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-06-07 00:00:00 Z
13
+ date: 2011-06-07 00:00:00 -07:00
14
+ default_executable:
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
21
- prerelease: false
22
17
  name: yajl-ruby
23
- type: :runtime
24
- version_requirements: &id001 !ruby/object:Gem::Requirement
18
+ requirement: &id001 !ruby/object:Gem::Requirement
25
19
  none: false
26
20
  requirements:
27
21
  - - ~>
28
22
  - !ruby/object:Gem::Version
29
- hash: 59
30
- segments:
31
- - 0
32
- - 8
33
- - 2
34
23
  version: 0.8.2
35
- requirement: *id001
36
- - !ruby/object:Gem::Dependency
24
+ type: :runtime
37
25
  prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
38
28
  name: gorillib
39
- type: :runtime
40
- version_requirements: &id002 !ruby/object:Gem::Requirement
29
+ requirement: &id002 !ruby/object:Gem::Requirement
41
30
  none: false
42
31
  requirements:
43
32
  - - ~>
44
33
  - !ruby/object:Gem::Version
45
- hash: 17
46
- segments:
47
- - 0
48
- - 0
49
- - 7
50
- version: 0.0.7
51
- requirement: *id002
52
- - !ruby/object:Gem::Dependency
34
+ version: 0.0.4
35
+ type: :runtime
53
36
  prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
54
39
  name: rspec
55
- type: :development
56
- version_requirements: &id003 !ruby/object:Gem::Requirement
40
+ requirement: &id003 !ruby/object:Gem::Requirement
57
41
  none: false
58
42
  requirements:
59
43
  - - ~>
60
44
  - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 2
64
- - 3
65
- - 0
66
45
  version: 2.3.0
67
- requirement: *id003
68
- - !ruby/object:Gem::Dependency
46
+ type: :development
69
47
  prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
70
50
  name: yard
71
- type: :development
72
- version_requirements: &id004 !ruby/object:Gem::Requirement
51
+ requirement: &id004 !ruby/object:Gem::Requirement
73
52
  none: false
74
53
  requirements:
75
54
  - - ~>
76
55
  - !ruby/object:Gem::Version
77
- hash: 7
78
- segments:
79
- - 0
80
- - 6
81
- - 0
82
56
  version: 0.6.0
83
- requirement: *id004
84
- - !ruby/object:Gem::Dependency
57
+ type: :development
85
58
  prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
86
61
  name: bundler
87
- type: :development
88
- version_requirements: &id005 !ruby/object:Gem::Requirement
62
+ requirement: &id005 !ruby/object:Gem::Requirement
89
63
  none: false
90
64
  requirements:
91
65
  - - ~>
92
66
  - !ruby/object:Gem::Version
93
- hash: 23
94
- segments:
95
- - 1
96
- - 0
97
- - 0
98
67
  version: 1.0.0
99
- requirement: *id005
100
- - !ruby/object:Gem::Dependency
68
+ type: :development
101
69
  prerelease: false
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
102
72
  name: jeweler
103
- type: :development
104
- version_requirements: &id006 !ruby/object:Gem::Requirement
73
+ requirement: &id006 !ruby/object:Gem::Requirement
105
74
  none: false
106
75
  requirements:
107
76
  - - ~>
108
77
  - !ruby/object:Gem::Version
109
- hash: 7
110
- segments:
111
- - 1
112
- - 5
113
- - 2
114
78
  version: 1.5.2
115
- requirement: *id006
116
- - !ruby/object:Gem::Dependency
79
+ type: :development
117
80
  prerelease: false
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
118
83
  name: rcov
119
- type: :development
120
- version_requirements: &id007 !ruby/object:Gem::Requirement
84
+ requirement: &id007 !ruby/object:Gem::Requirement
121
85
  none: false
122
86
  requirements:
123
87
  - - ">="
124
88
  - !ruby/object:Gem::Version
125
- hash: 3
126
- segments:
127
- - 0
128
89
  version: "0"
129
- requirement: *id007
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: *id007
130
93
  description: "Infochimps Stupid Schema library: an avro-compatible data description standard. ICSS completely describes a collection of data (and associated assets) in a way that is expressive, scalable and sufficient to drive remarkably complex downstream processes."
131
94
  email: coders@infochimps.com
132
95
  executables: []
@@ -139,8 +102,6 @@ extra_rdoc_files:
139
102
  files:
140
103
  - .document
141
104
  - .rspec
142
- - .watchr
143
- - CHANGELOG.textile
144
105
  - Gemfile
145
106
  - Gemfile.lock
146
107
  - LICENSE.textile
@@ -166,12 +127,16 @@ files:
166
127
  - lib/icss.rb
167
128
  - lib/icss/brevity.rb
168
129
  - lib/icss/code_asset.rb
169
- - lib/icss/core_ext.rb
170
130
  - lib/icss/data_asset.rb
171
131
  - lib/icss/message.rb
172
132
  - lib/icss/old.rb
173
133
  - lib/icss/protocol.rb
174
134
  - lib/icss/protocol_set.rb
135
+ - lib/icss/receiver.rb
136
+ - lib/icss/receiver/acts_as_hash.rb
137
+ - lib/icss/receiver/acts_as_loadable.rb
138
+ - lib/icss/receiver/tree_diff.rb
139
+ - lib/icss/receiver/validations.rb
175
140
  - lib/icss/sample_message_call.rb
176
141
  - lib/icss/target.rb
177
142
  - lib/icss/type.rb
@@ -180,6 +145,7 @@ files:
180
145
  - lib/icss/view_helper.rb
181
146
  - spec/icss_spec.rb
182
147
  - spec/spec_helper.rb
148
+ has_rdoc: true
183
149
  homepage: http://github.com/mrflip/icss
184
150
  licenses:
185
151
  - MIT
@@ -193,7 +159,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
159
  requirements:
194
160
  - - ">="
195
161
  - !ruby/object:Gem::Version
196
- hash: 3
162
+ hash: -803655258578775756
197
163
  segments:
198
164
  - 0
199
165
  version: "0"
@@ -202,14 +168,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
168
  requirements:
203
169
  - - ">="
204
170
  - !ruby/object:Gem::Version
205
- hash: 3
206
- segments:
207
- - 0
208
171
  version: "0"
209
172
  requirements: []
210
173
 
211
174
  rubyforge_project:
212
- rubygems_version: 1.7.2
175
+ rubygems_version: 1.5.0
213
176
  signing_key:
214
177
  specification_version: 3
215
178
  summary: "Infochimps Stupid Schema library: an avro-compatible data description standard. ICSS completely describes a collection of data (and associated assets) in a way that is expressive, scalable and sufficient to drive remarkably complex downstream processes."
data/.watchr DELETED
@@ -1,20 +0,0 @@
1
- # -*- ruby -*-
2
-
3
- def run_spec(file)
4
- unless File.exist?(file)
5
- puts "#{file} does not exist"
6
- return
7
- end
8
-
9
- puts "Running #{file}"
10
- system "bundle exec rspec #{file}"
11
- puts
12
- end
13
-
14
- watch("spec/.*/*_spec\.rb") do |match|
15
- run_spec match[0]
16
- end
17
-
18
- watch("app/(.*)\.rb") do |match|
19
- run_spec %{spec/#{match[1]}_spec.rb}
20
- end
data/CHANGELOG.textile DELETED
@@ -1,8 +0,0 @@
1
-
2
-
3
- h3. v0.0.3 May 22ish
4
-
5
- * used gorillib, got rid of active_support, extlib HOORAY
6
- * moved Receiver to gorillib.
7
- * *breaking change*. Gorillib changed the signature of receive() to be @receive(*constructor_args, hsh)@ (formerly, the hsh was first).
8
- *
data/lib/icss/core_ext.rb DELETED
@@ -1,4 +0,0 @@
1
- require 'gorillib/string/inflections'
2
- require 'gorillib/string/constantize'
3
- require 'gorillib/hash/keys'
4
- require 'gorillib/metaprogramming/class_attribute'