icss-activesupport-4 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.rspec +3 -0
- data/.watchr +52 -0
- data/CHANGELOG.md +38 -0
- data/Gemfile +22 -0
- data/LICENSE.textile +20 -0
- data/README.md +298 -0
- data/Rakefile +39 -0
- data/TODO.md +44 -0
- data/VERSION +1 -0
- data/examples/avro_examples/BulkData.avpr +21 -0
- data/examples/avro_examples/complicated.icss.yaml +159 -0
- data/examples/avro_examples/interop.avsc +32 -0
- data/examples/avro_examples/mail.avpr +20 -0
- data/examples/avro_examples/namespace.avpr +28 -0
- data/examples/avro_examples/org/apache/avro/ipc/HandshakeRequest.avsc +11 -0
- data/examples/avro_examples/org/apache/avro/ipc/HandshakeResponse.avsc +15 -0
- data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avdl +64 -0
- data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avpr +82 -0
- data/examples/avro_examples/org/apache/avro/mapred/tether/InputProtocol.avpr +59 -0
- data/examples/avro_examples/org/apache/avro/mapred/tether/OutputProtocol.avpr +75 -0
- data/examples/avro_examples/simple.avpr +70 -0
- data/examples/avro_examples/weather.avsc +9 -0
- data/examples/bnc.icss.yaml +70 -0
- data/examples/chronic.icss.yaml +115 -0
- data/examples/license.icss.yaml +7 -0
- data/examples/source1.icss.yaml +4 -0
- data/examples/source2.icss.yaml +4 -0
- data/examples/test_icss.yaml +67 -0
- data/icss.gemspec +168 -0
- data/icss_specification.textile +393 -0
- data/lib/icss.rb +53 -0
- data/lib/icss/core_types.rb +20 -0
- data/lib/icss/error.rb +4 -0
- data/lib/icss/init.rb +3 -0
- data/lib/icss/message.rb +133 -0
- data/lib/icss/message/message_sample.rb +144 -0
- data/lib/icss/protocol.rb +199 -0
- data/lib/icss/protocol/code_asset.rb +18 -0
- data/lib/icss/protocol/data_asset.rb +23 -0
- data/lib/icss/protocol/license.rb +41 -0
- data/lib/icss/protocol/source.rb +37 -0
- data/lib/icss/protocol/target.rb +68 -0
- data/lib/icss/receiver_model.rb +24 -0
- data/lib/icss/receiver_model/active_model_shim.rb +36 -0
- data/lib/icss/receiver_model/acts_as_catalog.rb +174 -0
- data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
- data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
- data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
- data/lib/icss/receiver_model/locale/en.yml +27 -0
- data/lib/icss/receiver_model/to_geo_json.rb +19 -0
- data/lib/icss/receiver_model/tree_merge.rb +34 -0
- data/lib/icss/receiver_model/validations.rb +31 -0
- data/lib/icss/serialization.rb +51 -0
- data/lib/icss/serialization/zaml.rb +442 -0
- data/lib/icss/type.rb +168 -0
- data/lib/icss/type/base_type.rb +0 -0
- data/lib/icss/type/named_type.rb +185 -0
- data/lib/icss/type/record_field.rb +77 -0
- data/lib/icss/type/record_model.rb +49 -0
- data/lib/icss/type/record_schema.rb +54 -0
- data/lib/icss/type/record_type.rb +325 -0
- data/lib/icss/type/simple_types.rb +71 -0
- data/lib/icss/type/structured_schema.rb +288 -0
- data/lib/icss/type/type_factory.rb +144 -0
- data/lib/icss/type/union_schema.rb +41 -0
- data/lib/icss/view_helper.rb +65 -0
- data/notes/named_array.md +32 -0
- data/notes/on_include_vs_extend_etc.rb +176 -0
- data/notes/technical_details.md +278 -0
- data/spec/core_types_spec.rb +119 -0
- data/spec/fixtures/zaml_complex_hash.yaml +35 -0
- data/spec/icss_spec.rb +90 -0
- data/spec/message/message_sample_spec.rb +4 -0
- data/spec/message_spec.rb +139 -0
- data/spec/protocol/license_spec.rb +67 -0
- data/spec/protocol/protocol_catalog_spec.rb +48 -0
- data/spec/protocol/protocol_validations_spec.rb +176 -0
- data/spec/protocol/source_spec.rb +65 -0
- data/spec/protocol_spec.rb +170 -0
- data/spec/receiver_model_spec.rb +115 -0
- data/spec/serialization/zaml_spec.rb +82 -0
- data/spec/serialization/zaml_test.rb +473 -0
- data/spec/serialization_spec.rb +63 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/icss_test_helper.rb +67 -0
- data/spec/support/load_example_protocols.rb +17 -0
- data/spec/type/base_type_spec.rb +0 -0
- data/spec/type/named_type_spec.rb +75 -0
- data/spec/type/record_field_spec.rb +44 -0
- data/spec/type/record_model_spec.rb +206 -0
- data/spec/type/record_schema_spec.rb +161 -0
- data/spec/type/record_type_spec.rb +155 -0
- data/spec/type/simple_types_spec.rb +121 -0
- data/spec/type/structured_schema_spec.rb +300 -0
- data/spec/type/type_catalog_spec.rb +44 -0
- data/spec/type/type_factory_spec.rb +93 -0
- data/spec/type/union_schema_spec.rb +0 -0
- data/spec/type_spec.rb +63 -0
- metadata +304 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
require 'time'
|
3
|
+
require 'icss'
|
4
|
+
require ENV.root_path('spec/support/icss_test_helper')
|
5
|
+
include IcssTestHelper
|
6
|
+
|
7
|
+
module Fake
|
8
|
+
class Thing
|
9
|
+
include Icss::ReceiverModel
|
10
|
+
field :name, String
|
11
|
+
field :description, String
|
12
|
+
end
|
13
|
+
|
14
|
+
class GeoCoordinates
|
15
|
+
include Icss::ReceiverModel
|
16
|
+
field :longitude, Float, :validates => { :numericality => { :>= => -180, :<= => 180 } }
|
17
|
+
field :latitude, Float, :validates => { :numericality => { :>= => -90, :<= => 90 } }
|
18
|
+
def coordinates
|
19
|
+
[ longitude, latitude ]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Place < Thing
|
24
|
+
field :geo, GeoCoordinates
|
25
|
+
end
|
26
|
+
|
27
|
+
class MenuItem < Thing
|
28
|
+
field :price, Float, :required => true
|
29
|
+
end
|
30
|
+
|
31
|
+
class TacoTrailer < Place
|
32
|
+
field :menu, Array, :items => MenuItem
|
33
|
+
field :founding_date, Time
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
TORCHYS_HSH = {
|
38
|
+
:name => "Torchy's Taco's",
|
39
|
+
:geo => { :longitude => 30.295, :latitude => -97.745 },
|
40
|
+
:menu => [
|
41
|
+
{ :name => "Dirty Sanchez", :price => 3.50 },
|
42
|
+
{ :name => "Fried Avocado", :price => 2.95 }
|
43
|
+
],
|
44
|
+
:founding_date => '2006-08-01T00:00:00Z',
|
45
|
+
}
|
46
|
+
|
47
|
+
describe Icss::ReceiverModel do
|
48
|
+
let(:torchys) do
|
49
|
+
Fake::TacoTrailer.receive(TORCHYS_HSH)
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'serializations' do
|
53
|
+
|
54
|
+
context '#to_wire' do
|
55
|
+
it 'works on a complex record' do
|
56
|
+
# p torchys
|
57
|
+
# p torchys.to_wire
|
58
|
+
torchys.to_wire.should == TORCHYS_HSH
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spork'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
def ENV.root_path(*args)
|
5
|
+
File.expand_path(File.join(File.dirname(__FILE__), '..', *args))
|
6
|
+
end
|
7
|
+
|
8
|
+
Spork.prefork do # Must restart for changes to config / code from libraries loaded here
|
9
|
+
$LOAD_PATH.unshift(ENV.root_path('lib'))
|
10
|
+
Dir[ENV.root_path('spec/support/matchers/*.rb')].each {|f| require f}
|
11
|
+
|
12
|
+
require 'awesome_print'
|
13
|
+
|
14
|
+
require 'gorillib/object/blank'
|
15
|
+
require 'gorillib/object/try_dup'
|
16
|
+
require 'gorillib/string/inflections'
|
17
|
+
require 'gorillib/string/constantize'
|
18
|
+
require 'gorillib/array/compact_blank'
|
19
|
+
require 'gorillib/array/extract_options'
|
20
|
+
require 'gorillib/hash/compact'
|
21
|
+
require 'gorillib/hash/keys'
|
22
|
+
require 'gorillib/hash/tree_merge'
|
23
|
+
require 'gorillib/metaprogramming/class_attribute'
|
24
|
+
require 'gorillib/hashlike'
|
25
|
+
|
26
|
+
require 'yaml'
|
27
|
+
require 'json' unless defined?(JSON)
|
28
|
+
|
29
|
+
# note: please do NOT include library methods here.
|
30
|
+
# They should be painfully explicity included in your specs.
|
31
|
+
|
32
|
+
# Configure rspec
|
33
|
+
RSpec.configure do |config|
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Spork.each_run do
|
38
|
+
# This code will be run each time you run your specs.
|
39
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module IcssTestHelper
|
2
|
+
FALSE_PARENTS = %w[Boolean Icss::Mu::EpochTime Long Double]
|
3
|
+
|
4
|
+
SIMPLE_TYPES_TO_TEST = {
|
5
|
+
:null => [ ::NilClass, NilClass, nil],
|
6
|
+
:boolean => [ ::Boolean, TrueClass, true],
|
7
|
+
:int => [ ::Integer, Integer, 1],
|
8
|
+
:long => [ ::Long, Integer, 1],
|
9
|
+
:float => [ ::Float, Float, 1.0],
|
10
|
+
:double => [ ::Double, Float, 1.0],
|
11
|
+
:string => [ ::String, String, "hello"],
|
12
|
+
:bytes => [ ::Binary, String, "hello"],
|
13
|
+
:binary => [ ::Binary, String, "hello"],
|
14
|
+
:integer => [ ::Integer, Integer, 1],
|
15
|
+
:regexp => [ ::Regexp, Regexp, /a/],
|
16
|
+
:numeric => [ ::Numeric, ::Numeric, 1.0],
|
17
|
+
:symbol => [ ::Symbol, Symbol, :bob],
|
18
|
+
:time => [ ::Time, Time, Time.now],
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
def remove_icss_constants(*names)
|
23
|
+
['Icss', 'Icss::Meta'].each do |outer_mod|
|
24
|
+
names.each do |name|
|
25
|
+
name_parts = name.to_s.split(/::/)
|
26
|
+
const_name = name_parts.pop
|
27
|
+
parent_mod = ([outer_mod]+name_parts).join('::')
|
28
|
+
['', 'Type', 'Model'].each do |tail|
|
29
|
+
remove_potential_constant(parent_mod, const_name+tail)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def remove_potential_constant(parent_mod, const_name)
|
36
|
+
begin
|
37
|
+
parent_mod = (parent_mod.is_a?(Module) ? parent_mod : parent_mod.to_s.constantize)
|
38
|
+
rescue ; return ; end
|
39
|
+
parent_mod.send(:remove_const, const_name) if parent_mod.const_defined?(const_name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module Icss
|
44
|
+
module This
|
45
|
+
module That
|
46
|
+
class TheOther
|
47
|
+
end
|
48
|
+
end
|
49
|
+
module Blinken ; end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if defined?(Icss::Meta::RecordModel)
|
54
|
+
module Icss
|
55
|
+
class SmurfRecord
|
56
|
+
include Icss::Meta::RecordModel
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if defined?(Icss::ReceiverModel)
|
62
|
+
module Icss
|
63
|
+
class SmurfModel
|
64
|
+
include Icss::ReceiverModel
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Icss
|
2
|
+
module Spec
|
3
|
+
module LoadExampleProtocols
|
4
|
+
|
5
|
+
def load_example_protocols
|
6
|
+
[
|
7
|
+
Dir[ENV.root_path('examples/hackboxen/**/*.icss.yaml')],
|
8
|
+
Dir[ENV.root_path('examples/apeyeye_endpoints/**/*.icss.yaml')],
|
9
|
+
].flatten[0.. -1].each do |icss_filename|
|
10
|
+
next if icss_filename =~ %r{culture/art}
|
11
|
+
Icss::Meta::Protocol.receive_from_file(icss_filename)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
File without changes
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'icss/type'
|
3
|
+
require 'icss/type/simple_types'
|
4
|
+
require 'icss/type/named_type'
|
5
|
+
|
6
|
+
describe Icss::Meta::NamedType do
|
7
|
+
|
8
|
+
module Icss
|
9
|
+
module This
|
10
|
+
module That
|
11
|
+
class TheOther
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
Blinken = 7
|
16
|
+
end
|
17
|
+
#
|
18
|
+
# modules defined outside of Icss with the same names will cause problems
|
19
|
+
# unless const_defined? and const_get are used correctly
|
20
|
+
#
|
21
|
+
module Nod
|
22
|
+
end
|
23
|
+
module Wears
|
24
|
+
end
|
25
|
+
|
26
|
+
context '.make' do
|
27
|
+
it 'succeeds when the class already exists' do
|
28
|
+
klass, klass_metamodel = Icss::Meta::NamedType.make('this.that.the_other', Object)
|
29
|
+
klass.should be_a(Class)
|
30
|
+
klass.name.should == 'Icss::This::That::TheOther'
|
31
|
+
klass_metamodel.should be_a(Module)
|
32
|
+
klass_metamodel.name.should == 'Icss::Meta::This::That::TheOtherModel'
|
33
|
+
end
|
34
|
+
it 'succeeds when the class does not already exist' do
|
35
|
+
Icss.should_not be_const_defined(:YourMom)
|
36
|
+
klass, klass_metamodel = Icss::Meta::NamedType.make('your_mom.wears.combat_boots', Hash)
|
37
|
+
klass.name.should == 'Icss::YourMom::Wears::CombatBoots'
|
38
|
+
klass.should < Hash
|
39
|
+
Icss::Meta::YourMom::Wears::CombatBootsModel.class.should == Module
|
40
|
+
Icss::Meta::YourMom::Wears.class.should == Module
|
41
|
+
Icss::YourMom::Wears::CombatBoots.class.should == Class
|
42
|
+
Icss::YourMom::Wears.class.should == Module
|
43
|
+
Icss::Meta.send(:remove_const, :YourMom)
|
44
|
+
Icss.send(:remove_const, :YourMom)
|
45
|
+
end
|
46
|
+
it 'creates a klass which inherits (includes) its metatype' do
|
47
|
+
klass, klass_metamodel = Icss::Meta::NamedType.make('this.that.the_other', Object)
|
48
|
+
klass.metamodel.should == Icss::Meta::This::That::TheOtherModel
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context '.get_nested_module' do
|
53
|
+
it 'adds a new child when parents exist' do
|
54
|
+
Icss::This::That.should_not be_const_defined(:AlsoThis)
|
55
|
+
new_module = Icss::Meta::NamedType.get_nested_module(%w[Icss This That AlsoThis])
|
56
|
+
new_module.name.should == 'Icss::This::That::AlsoThis'
|
57
|
+
Icss::This::That::AlsoThis.class.should == Module
|
58
|
+
Icss::This::That.send(:remove_const, :AlsoThis)
|
59
|
+
end
|
60
|
+
it 'adds parents as necessary' do
|
61
|
+
Icss.should_not be_const_defined(:Winken)
|
62
|
+
new_module = Icss::Meta::NamedType.get_nested_module(%w[Icss Winken Blinken Nod])
|
63
|
+
new_module.name.should == 'Icss::Winken::Blinken::Nod'
|
64
|
+
Icss::Winken::Blinken::Nod.class.should == Module
|
65
|
+
Icss::Winken::Blinken.class.should == Module
|
66
|
+
Icss::Winken.class.should == Module
|
67
|
+
Icss.send(:remove_const, :Winken)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context '.define_metamodel_method' do
|
72
|
+
it 'does not overwrite an existing method'
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'icss'
|
3
|
+
require ENV.root_path('spec/support/icss_test_helper')
|
4
|
+
include IcssTestHelper
|
5
|
+
|
6
|
+
describe Icss::Meta::RecordType do
|
7
|
+
before do
|
8
|
+
IcssTestHelper.remove_icss_constants('Handy')
|
9
|
+
class Icss::Handy < Icss::SmurfRecord ; end
|
10
|
+
end
|
11
|
+
|
12
|
+
context '.field' do
|
13
|
+
it 'with record_field loaded, adds RecordFields not hashes' do
|
14
|
+
Icss::Handy.field :foo, Integer
|
15
|
+
Icss::Handy.field_named(:foo).should be_a(Icss::Meta::RecordField)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'allows sloppy complex types when I use Hash' do
|
19
|
+
Icss::Handy.field :foo, Hash, :values => Integer
|
20
|
+
fld = Icss::Handy.field_named(:foo)
|
21
|
+
fld.type.to_s.should == 'Icss::HashOfInteger'
|
22
|
+
fld.type.values == Integer
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'allows sloppy complex types when I use Array' do
|
26
|
+
Icss::Handy.field :foo, Array, :items => Integer
|
27
|
+
fld = Icss::Handy.field_named(:foo)
|
28
|
+
fld.type.to_s.should == 'Icss::ArrayOfInteger'
|
29
|
+
fld.type.items == Integer
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'does not allow sloppy complex types when I use :hash' do
|
33
|
+
lambda{ Icss::Handy.field :bar, :hash, :values => Integer }.should raise_error
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'handles complex fields in line' do
|
37
|
+
Icss::Handy.field :foo, { :type => :hash, :values => Integer }
|
38
|
+
fld = Icss::Handy.field_named(:foo)
|
39
|
+
fld.type.to_s.should == 'Icss::HashOfInteger'
|
40
|
+
fld.type.values == Integer
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'gorillib/object/try_dup'
|
3
|
+
require 'icss/receiver_model/acts_as_hash'
|
4
|
+
require 'icss/receiver_model/active_model_shim'
|
5
|
+
require 'icss/type' #
|
6
|
+
require 'icss/type/simple_types' # Boolean, Integer, ...
|
7
|
+
require 'icss/type/named_type' # class methods for a named type: .metamodel .doc, .fullname, &c
|
8
|
+
require 'icss/type/record_type' # class methods for a record model: .field, .receive,
|
9
|
+
require 'icss/type/record_model' # instance methods for a record model
|
10
|
+
#
|
11
|
+
require 'icss/type/type_factory' #
|
12
|
+
require 'icss/type/structured_schema'
|
13
|
+
require 'icss/type/record_schema'
|
14
|
+
require 'icss/type/record_field'
|
15
|
+
|
16
|
+
require ENV.root_path('spec/support/icss_test_helper')
|
17
|
+
include IcssTestHelper
|
18
|
+
|
19
|
+
describe Icss::Meta::RecordModel do
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
IcssTestHelper.remove_icss_constants('Poppa', 'Brainy', 'Smurfette', 'Hefty', 'Glad')
|
23
|
+
module Icss
|
24
|
+
class Poppa < Icss::SmurfRecord
|
25
|
+
field :smurfiness, Integer
|
26
|
+
end
|
27
|
+
module Brainy
|
28
|
+
include Icss::Meta::RecordModel
|
29
|
+
field :has_glasses, Boolean
|
30
|
+
end
|
31
|
+
class Smurfette < Poppa
|
32
|
+
include Brainy
|
33
|
+
field :blondness, Integer
|
34
|
+
end
|
35
|
+
class Hefty < Icss::SmurfRecord
|
36
|
+
end
|
37
|
+
class Glad < Hefty
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:poppa ){ Icss::Poppa.new() }
|
43
|
+
let(:smurfette ){ Icss::Smurfette.new() }
|
44
|
+
|
45
|
+
context '#receive!' do
|
46
|
+
it 'sets values' do
|
47
|
+
smurfette.receive!({ :smurfiness => '98', :blondness => 12.7 })
|
48
|
+
smurfette.smurfiness.should == 98
|
49
|
+
smurfette.blondness.should == 12
|
50
|
+
end
|
51
|
+
it 'handles values with #receive_foo methods' do
|
52
|
+
smurfette.should_receive(:receive_smurfiness).with('99')
|
53
|
+
smurfette.receive!({ :smurfiness => '99' })
|
54
|
+
end
|
55
|
+
it 'which goes through _set_field_val' do
|
56
|
+
smurfette.should_receive(:_set_field_val).with(:smurfiness, 100)
|
57
|
+
smurfette.receive!({ :smurfiness => '100' })
|
58
|
+
end
|
59
|
+
it 'sends to field type klass .receive method' do
|
60
|
+
dummy = mock
|
61
|
+
foo_type = Class.new
|
62
|
+
Icss::Poppa.field :foo, foo_type
|
63
|
+
#
|
64
|
+
foo_type.should_receive(:receive).with(dummy)
|
65
|
+
Icss::Poppa.receive({ :foo => dummy })
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'decorates instances' do
|
70
|
+
it 'with accessors and receivers' do
|
71
|
+
[:smurfiness, :has_glasses, :blondness].each do |f|
|
72
|
+
smurfette.should respond_to(f)
|
73
|
+
smurfette.should respond_to("#{f}=")
|
74
|
+
end
|
75
|
+
smurfette.should respond_to(:receive_smurfiness)
|
76
|
+
smurfette.should respond_to(:receive_blondness)
|
77
|
+
smurfette.blondness.should == nil
|
78
|
+
smurfette.blondness = 77
|
79
|
+
smurfette.blondness.should == 77
|
80
|
+
smurfette.receive_blondness(99)
|
81
|
+
smurfette.blondness.should == 99
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context '.after_receive' do
|
86
|
+
it 'adds an after_receiver' do
|
87
|
+
blk = lambda{ 1 }
|
88
|
+
Icss::Poppa.after_receive(:foo, &blk)
|
89
|
+
Icss::Poppa.after_receivers[:foo].should == blk
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context '.after_receivers' do
|
94
|
+
it 'is run after receive' do
|
95
|
+
dummy = mock ; hsh = { :smurfiness => 9 }
|
96
|
+
Icss::Poppa.after_receive(:howdy){|hsh| dummy.hello("hello!", smurfiness) }
|
97
|
+
dummy.should_receive(:hello).with("hello!", 9)
|
98
|
+
Icss::Poppa.receive(hsh)
|
99
|
+
end
|
100
|
+
it 'gets received hash as args' do
|
101
|
+
dummy = mock ; hsh = { :smurfiness => 10 }
|
102
|
+
Icss::Poppa.after_receive(:howdy){|hsh| dummy.hello("hello!", hsh) }
|
103
|
+
dummy.should_receive(:hello).with("hello!", hsh)
|
104
|
+
Icss::Poppa.receive(hsh)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context '.rcvr_remaining' do
|
109
|
+
it 'adds a new field' do
|
110
|
+
Icss::Poppa.rcvr_remaining(:bob)
|
111
|
+
Icss::Poppa.field_names.should == [:smurfiness, :bob]
|
112
|
+
Icss::Poppa.field_named(:bob)[:type].to_s.should == 'Icss::HashOfMetaDotIdenticalFactory'
|
113
|
+
end
|
114
|
+
it 'receives leftover attrs' do
|
115
|
+
Icss::Poppa.rcvr_remaining(:bob)
|
116
|
+
obj = Icss::Poppa.receive(:smurfiness => 12, :bogosity => 97)
|
117
|
+
obj.bob.should == {:bogosity => 97}
|
118
|
+
end
|
119
|
+
it 'applies schema to leftover attrs' do
|
120
|
+
Icss::Poppa.rcvr_remaining(:bob, :values => :int)
|
121
|
+
obj = Icss::Poppa.receive({:smurfiness => 12, :bogosity => "11", :converts => 31.2})
|
122
|
+
obj.bob.should == {:bogosity => 11, :converts => 31}
|
123
|
+
end
|
124
|
+
it 'is {} when no leftover attrs' do
|
125
|
+
Icss::Poppa.rcvr_remaining(:bob)
|
126
|
+
obj = Icss::Poppa.receive({:smurfiness => 12})
|
127
|
+
obj.bob.should == {}
|
128
|
+
obj = Icss::Poppa.receive({})
|
129
|
+
obj.bob.should == {}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context ':default =>' do
|
134
|
+
before do
|
135
|
+
Icss::Hefty.field :tool, Symbol, :default => :smurfwrench
|
136
|
+
Icss::Hefty.field :weapon, Symbol, :default => :smurfthrower
|
137
|
+
Icss::Hefty.field :no_default, Symbol
|
138
|
+
end
|
139
|
+
let(:hefty_smurf){ Icss::Hefty.receive({ :tool => :smurfwrench }) }
|
140
|
+
let(:glad_smurf ){ Icss::Glad.receive({ :tool => :smurfwrench }) }
|
141
|
+
|
142
|
+
it 'sets default' do
|
143
|
+
hefty_smurf.tool.should == :smurfwrench
|
144
|
+
hefty_smurf.weapon.should == :smurfthrower
|
145
|
+
hefty_smurf.no_default.should be_nil
|
146
|
+
hefty_smurf.attr_set?(:no_default).should be_false
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'does not set default if explicitly nil' do
|
150
|
+
hefty_smurf = Icss::Hefty.receive({ :tool => :smurfwrench, :weapon => nil })
|
151
|
+
hefty_smurf.weapon.should == nil
|
152
|
+
hefty_smurf.attr_set?(:weapon).should be_true
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'uses an after_receiver with a predictable name' do
|
156
|
+
Icss::Hefty.after_receivers[:default_tool].should be_a(Proc)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'is overridable' do
|
160
|
+
proc_before = Icss::Hefty.after_receivers[:default_weapon]
|
161
|
+
Icss::Hefty.field :weapon, Symbol, :default => :flamesmurf
|
162
|
+
Icss::Hefty.after_receivers[:default_weapon].should_not == proc_before
|
163
|
+
hefty_smurf.weapon.should == :flamesmurf
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'is overridable in subclass without affecting parent' do
|
167
|
+
hefty_proc = Icss::Hefty.after_receivers[:default_weapon]
|
168
|
+
Icss::Glad.field :weapon, Symbol, :default => :flamesmurf
|
169
|
+
Icss::Hefty.after_receivers[:default_weapon].should == hefty_proc
|
170
|
+
Icss::Glad.after_receivers[ :default_weapon].should_not == hefty_proc
|
171
|
+
hefty_smurf.weapon.should == :smurfthrower
|
172
|
+
glad_smurf.weapon.should == :flamesmurf
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'try_dups the object when setting default' do
|
176
|
+
smurfed_cheese = mock
|
177
|
+
Icss::Hefty.field :food, Symbol, :default => smurfed_cheese
|
178
|
+
smurfed_cheese.should_receive(:try_dup).with()
|
179
|
+
hefty_smurf
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'accepts a proc' do
|
183
|
+
dummy = mock
|
184
|
+
Icss::Glad.field :weapon, Symbol, :default => lambda{ [dummy, tool, self] }
|
185
|
+
glad_smurf.weapon.should == [dummy, :smurfwrench, glad_smurf]
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'can also be set with set_field_default' do
|
189
|
+
it 'with a value' do
|
190
|
+
dummy = mock
|
191
|
+
Icss::Glad.class_eval do
|
192
|
+
set_field_default :weapon, :gatlingsmurf
|
193
|
+
end
|
194
|
+
glad_smurf.weapon.should == :gatlingsmurf
|
195
|
+
end
|
196
|
+
it 'with a proc' do
|
197
|
+
dummy = mock
|
198
|
+
Icss::Glad.class_eval do
|
199
|
+
set_field_default :weapon, lambda{ [dummy, tool, self] }
|
200
|
+
end
|
201
|
+
glad_smurf.weapon.should == [dummy, :smurfwrench, glad_smurf]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|