icss 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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'