icss 0.1.3 → 0.3.2
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/.watchr +35 -3
- data/CHANGELOG.md +38 -0
- data/Gemfile +19 -14
- data/README.md +296 -0
- data/Rakefile +2 -6
- data/TODO.md +13 -0
- data/VERSION +1 -1
- data/examples/avro_examples/complicated.icss.yaml +14 -13
- data/examples/bnc.icss.yaml +70 -0
- data/examples/chronic.icss.yaml +3 -3
- 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 +103 -43
- data/lib/icss.rb +37 -15
- data/lib/icss/core_types.rb +19 -0
- data/lib/icss/error.rb +4 -0
- data/{init.rb → lib/icss/init.rb} +0 -0
- data/lib/icss/message.rb +124 -66
- data/lib/icss/message/message_sample.rb +144 -0
- data/lib/icss/protocol.rb +184 -131
- 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 +170 -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 +443 -0
- data/lib/icss/type.rb +148 -501
- data/lib/icss/type/base_type.rb +0 -0
- data/lib/icss/type/named_type.rb +184 -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 +72 -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 +56 -19
- 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 +86 -23
- 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 +91 -37
- data/spec/receiver_model_spec.rb +111 -0
- data/spec/serialization/zaml_spec.rb +81 -0
- data/spec/serialization/zaml_test.rb +473 -0
- data/spec/serialization_spec.rb +63 -0
- data/spec/spec_helper.rb +24 -7
- 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 +205 -144
- data/CHANGELOG.textile +0 -9
- data/Gemfile.lock +0 -40
- data/README.textile +0 -29
- data/lib/icss/brevity.rb +0 -136
- data/lib/icss/code_asset.rb +0 -16
- data/lib/icss/core_ext.rb +0 -9
- data/lib/icss/data_asset.rb +0 -22
- data/lib/icss/old.rb +0 -96
- data/lib/icss/protocol_set.rb +0 -48
- data/lib/icss/sample_message_call.rb +0 -142
- data/lib/icss/target.rb +0 -72
- data/lib/icss/type/factory.rb +0 -196
- data/lib/icss/validations.rb +0 -16
- data/spec/validations_spec.rb +0 -171
@@ -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
CHANGED
@@ -1,16 +1,33 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'spork'
|
3
2
|
require 'rspec'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
File.join(::ICSS_ROOT_DIR, *paths)
|
4
|
+
def ENV.root_path(*args)
|
5
|
+
File.expand_path(File.join(File.dirname(__FILE__), '..', *args))
|
8
6
|
end
|
9
7
|
|
10
8
|
Spork.prefork do # Must restart for changes to config / code from libraries loaded here
|
11
|
-
$LOAD_PATH.unshift(
|
12
|
-
|
13
|
-
|
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.
|
14
31
|
|
15
32
|
# Configure rspec
|
16
33
|
RSpec.configure do |config|
|
@@ -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
|