icss-activesupport-4 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.rspec +3 -0
  4. data/.watchr +52 -0
  5. data/CHANGELOG.md +38 -0
  6. data/Gemfile +22 -0
  7. data/LICENSE.textile +20 -0
  8. data/README.md +298 -0
  9. data/Rakefile +39 -0
  10. data/TODO.md +44 -0
  11. data/VERSION +1 -0
  12. data/examples/avro_examples/BulkData.avpr +21 -0
  13. data/examples/avro_examples/complicated.icss.yaml +159 -0
  14. data/examples/avro_examples/interop.avsc +32 -0
  15. data/examples/avro_examples/mail.avpr +20 -0
  16. data/examples/avro_examples/namespace.avpr +28 -0
  17. data/examples/avro_examples/org/apache/avro/ipc/HandshakeRequest.avsc +11 -0
  18. data/examples/avro_examples/org/apache/avro/ipc/HandshakeResponse.avsc +15 -0
  19. data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avdl +64 -0
  20. data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avpr +82 -0
  21. data/examples/avro_examples/org/apache/avro/mapred/tether/InputProtocol.avpr +59 -0
  22. data/examples/avro_examples/org/apache/avro/mapred/tether/OutputProtocol.avpr +75 -0
  23. data/examples/avro_examples/simple.avpr +70 -0
  24. data/examples/avro_examples/weather.avsc +9 -0
  25. data/examples/bnc.icss.yaml +70 -0
  26. data/examples/chronic.icss.yaml +115 -0
  27. data/examples/license.icss.yaml +7 -0
  28. data/examples/source1.icss.yaml +4 -0
  29. data/examples/source2.icss.yaml +4 -0
  30. data/examples/test_icss.yaml +67 -0
  31. data/icss.gemspec +168 -0
  32. data/icss_specification.textile +393 -0
  33. data/lib/icss.rb +53 -0
  34. data/lib/icss/core_types.rb +20 -0
  35. data/lib/icss/error.rb +4 -0
  36. data/lib/icss/init.rb +3 -0
  37. data/lib/icss/message.rb +133 -0
  38. data/lib/icss/message/message_sample.rb +144 -0
  39. data/lib/icss/protocol.rb +199 -0
  40. data/lib/icss/protocol/code_asset.rb +18 -0
  41. data/lib/icss/protocol/data_asset.rb +23 -0
  42. data/lib/icss/protocol/license.rb +41 -0
  43. data/lib/icss/protocol/source.rb +37 -0
  44. data/lib/icss/protocol/target.rb +68 -0
  45. data/lib/icss/receiver_model.rb +24 -0
  46. data/lib/icss/receiver_model/active_model_shim.rb +36 -0
  47. data/lib/icss/receiver_model/acts_as_catalog.rb +174 -0
  48. data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
  49. data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
  50. data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
  51. data/lib/icss/receiver_model/locale/en.yml +27 -0
  52. data/lib/icss/receiver_model/to_geo_json.rb +19 -0
  53. data/lib/icss/receiver_model/tree_merge.rb +34 -0
  54. data/lib/icss/receiver_model/validations.rb +31 -0
  55. data/lib/icss/serialization.rb +51 -0
  56. data/lib/icss/serialization/zaml.rb +442 -0
  57. data/lib/icss/type.rb +168 -0
  58. data/lib/icss/type/base_type.rb +0 -0
  59. data/lib/icss/type/named_type.rb +185 -0
  60. data/lib/icss/type/record_field.rb +77 -0
  61. data/lib/icss/type/record_model.rb +49 -0
  62. data/lib/icss/type/record_schema.rb +54 -0
  63. data/lib/icss/type/record_type.rb +325 -0
  64. data/lib/icss/type/simple_types.rb +71 -0
  65. data/lib/icss/type/structured_schema.rb +288 -0
  66. data/lib/icss/type/type_factory.rb +144 -0
  67. data/lib/icss/type/union_schema.rb +41 -0
  68. data/lib/icss/view_helper.rb +65 -0
  69. data/notes/named_array.md +32 -0
  70. data/notes/on_include_vs_extend_etc.rb +176 -0
  71. data/notes/technical_details.md +278 -0
  72. data/spec/core_types_spec.rb +119 -0
  73. data/spec/fixtures/zaml_complex_hash.yaml +35 -0
  74. data/spec/icss_spec.rb +90 -0
  75. data/spec/message/message_sample_spec.rb +4 -0
  76. data/spec/message_spec.rb +139 -0
  77. data/spec/protocol/license_spec.rb +67 -0
  78. data/spec/protocol/protocol_catalog_spec.rb +48 -0
  79. data/spec/protocol/protocol_validations_spec.rb +176 -0
  80. data/spec/protocol/source_spec.rb +65 -0
  81. data/spec/protocol_spec.rb +170 -0
  82. data/spec/receiver_model_spec.rb +115 -0
  83. data/spec/serialization/zaml_spec.rb +82 -0
  84. data/spec/serialization/zaml_test.rb +473 -0
  85. data/spec/serialization_spec.rb +63 -0
  86. data/spec/spec_helper.rb +39 -0
  87. data/spec/support/icss_test_helper.rb +67 -0
  88. data/spec/support/load_example_protocols.rb +17 -0
  89. data/spec/type/base_type_spec.rb +0 -0
  90. data/spec/type/named_type_spec.rb +75 -0
  91. data/spec/type/record_field_spec.rb +44 -0
  92. data/spec/type/record_model_spec.rb +206 -0
  93. data/spec/type/record_schema_spec.rb +161 -0
  94. data/spec/type/record_type_spec.rb +155 -0
  95. data/spec/type/simple_types_spec.rb +121 -0
  96. data/spec/type/structured_schema_spec.rb +300 -0
  97. data/spec/type/type_catalog_spec.rb +44 -0
  98. data/spec/type/type_factory_spec.rb +93 -0
  99. data/spec/type/union_schema_spec.rb +0 -0
  100. data/spec/type_spec.rb +63 -0
  101. metadata +304 -0
@@ -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
@@ -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