rubyamf-ouvrages 2.0.0

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.
@@ -0,0 +1,147 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RubyAMF::MappingSet do
4
+ before :each do
5
+ @set = RubyAMF::MappingSet.new
6
+ end
7
+
8
+ it "should have default mappings" do
9
+ @set.get_as_class_name('RocketAMF::Values::RemotingMessage').should == 'flex.messaging.messages.RemotingMessage'
10
+ @set.get_ruby_class_name('flex.messaging.messages.RemotingMessage').should == 'RocketAMF::Values::RemotingMessage'
11
+ end
12
+
13
+ it "should store serialization attributes by scope" do
14
+ @set.map :as => 'A', :ruby => 'R', :default_scope => :scope_a, :except => ['a']
15
+ @set.map :as => 'A', :ruby => 'R', :scope => :scope_b, :except => ['b']
16
+
17
+ @set.serialization_config('R').should == {:except => ['a']}
18
+ @set.serialization_config('R', :scope_b).should == {:except => ['b']}
19
+ end
20
+
21
+ it "should assume default scope if configuring attributes" do
22
+ @set.map :as => 'A', :ruby => 'R', :except => ['a']
23
+
24
+ @set.serialization_config('R').should == {:except => ['a']}
25
+ end
26
+
27
+ it "should update scopes on change" do
28
+ @set.map :as => 'A', :ruby => 'R', :scope => :default, :only => ['a']
29
+ @set.map :as => 'A', :ruby => 'R', :scope => :default, :except => ['b']
30
+
31
+ @set.serialization_config('R').should == {:except => ['b']}
32
+ end
33
+ end
34
+
35
+ class UnmappedClass; end
36
+ class MappingTestClass
37
+ def initialize
38
+ @initialized = true
39
+ end
40
+
41
+ def initialized?
42
+ @initialized
43
+ end
44
+ end
45
+ class MappingModelTestClass < MappingTestClass
46
+ def rubyamf_init; end
47
+ end
48
+
49
+ describe RubyAMF::ClassMapping do
50
+ before :each do
51
+ RubyAMF::ClassMapping.reset
52
+ @set = RubyAMF::ClassMapping.mappings
53
+ @mapper = RubyAMF::ClassMapping.new
54
+ @conf = RubyAMF.configuration = RubyAMF::Configuration.new
55
+ end
56
+
57
+ it "should auto-map class on deserialization correctly" do
58
+ @conf.auto_class_mapping = true
59
+ as_name = "com.test.UnmappedClass"
60
+ @set.get_ruby_class_name(as_name).should == nil
61
+ obj = @mapper.get_ruby_obj as_name
62
+ obj.class.should == UnmappedClass
63
+ @set.get_ruby_class_name(as_name).should == "UnmappedClass"
64
+ end
65
+
66
+ it "should auto-map class on serialization correctly" do
67
+ @conf.auto_class_mapping = true
68
+ name = "UnmappedClass"
69
+ @set.get_as_class_name(name).should == nil
70
+ @mapper.get_as_class_name(UnmappedClass.new).should == name
71
+ @set.get_as_class_name(name).should == name
72
+ end
73
+
74
+ it "should translate property case on deserialization correctly" do
75
+ @conf.translate_case = true
76
+ props = {'aProperty' => "asdf", 'aMoreComplexProperty' => "asdf"}
77
+ dynamic_props = {'aDynamicProperty' => "fdsa"}
78
+ obj = RocketAMF::Values::TypedHash.new("")
79
+ @mapper.populate_ruby_obj obj, props, dynamic_props
80
+ obj.should == {'a_property' => "asdf", 'a_more_complex_property' => "asdf", 'a_dynamic_property' => "fdsa"}
81
+ end
82
+
83
+ it "should translate property case on serialization correctly" do
84
+ @conf.translate_case = true
85
+ obj = {"a_dynamic_property" => "asdf"}
86
+ props = @mapper.props_for_serialization(obj)
87
+ props.should == {"aDynamicProperty" => "asdf"}
88
+ end
89
+
90
+ it "should allow setting hash key type to symbol" do
91
+ @conf.hash_key_access = :symbol
92
+ props = {'asdf' => "asdf", 'fdsa' => "fdsa"}
93
+ obj = RocketAMF::Values::TypedHash.new("")
94
+ @mapper.populate_ruby_obj obj, props
95
+ obj.should == {:asdf => "asdf", :fdsa => "fdsa"}
96
+ end
97
+
98
+ it "should return correct class name for IntermediateObject" do
99
+ obj = RubyAMF::IntermediateObject.new(MappingTestClass.new, {})
100
+ @set.map :as => "MappingTestClass", :ruby => "MappingTestClass"
101
+ @mapper.get_as_class_name(obj).should == "MappingTestClass"
102
+ end
103
+
104
+ it "should extract properties correctly for IntermediateObject" do
105
+ obj = RubyAMF::IntermediateObject.new(MappingTestClass.new, {:only => "asdf"})
106
+ obj.object.should_receive(:rubyamf_hash).with(obj.options).and_return({"asdf" => "fdsa"})
107
+ props = @mapper.props_for_serialization(obj)
108
+ props.should == {"asdf" => "fdsa"}
109
+ end
110
+
111
+ it "should properly extract properties for mapped class" do
112
+ obj = MappingTestClass.new
113
+ @set.map :as => "MappingTestClass", :ruby => "MappingTestClass", :only => "asdf"
114
+ obj.should_receive(:rubyamf_hash).with({:only => "asdf"}).and_return({"asdf" => "fdsa"})
115
+ props = @mapper.props_for_serialization(obj)
116
+ props.should == {"asdf" => "fdsa"}
117
+ end
118
+
119
+ it "should not call initialize on rubyamf_init implementors" do
120
+ @set.map :as => "MappingTestClass", :ruby => "MappingTestClass"
121
+ @set.map :as => "MappingModelTestClass", :ruby => "MappingModelTestClass"
122
+
123
+ obj = @mapper.get_ruby_obj("MappingTestClass")
124
+ obj.initialized?.should == true
125
+
126
+ obj = @mapper.get_ruby_obj("MappingModelTestClass")
127
+ obj.initialized?.should_not == true
128
+ end
129
+
130
+ it "should skip properties on deserialize that are globally ignored" do
131
+ obj = MappingModelTestClass.new
132
+ @conf.ignore_fields = ["asdf"]
133
+ @set.map :as => "MappingModelTestClass", :ruby => "MappingModelTestClass"
134
+
135
+ obj.should_receive(:rubyamf_init).with({:fdsa => "fdsa"}, nil)
136
+ @mapper.populate_ruby_obj(obj, {:asdf => "asdf", :fdsa => "fdsa"})
137
+ end
138
+
139
+ it "should skip properties on deserialize that are configured to be ignored" do
140
+ obj = MappingModelTestClass.new
141
+ @conf.ignore_fields = ["fdsa"]
142
+ @set.map :as => "MappingModelTestClass", :ruby => "MappingModelTestClass", :ignore_fields => "asdf"
143
+
144
+ obj.should_receive(:rubyamf_init).with({:fdsa => "fdsa"}, nil)
145
+ @mapper.populate_ruby_obj(obj, {:asdf => "asdf", :fdsa => "fdsa"})
146
+ end
147
+ end
@@ -0,0 +1,90 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RubyAMF::Configuration do
4
+ before :each do
5
+ RubyAMF::ClassMapping.reset
6
+ @conf = RubyAMF::Configuration.new
7
+ @legacy_path = File.dirname(__FILE__) + '/fixtures/rubyamf_config.rb'
8
+ end
9
+
10
+ it "should read legacy files without errors" do
11
+ @conf.load_legacy(@legacy_path)
12
+ end
13
+
14
+ it "should properly map blank class mapping" do
15
+ @conf.load_legacy(@legacy_path)
16
+ mapset = RubyAMF::ClassMapping.mappings
17
+ mapset.get_ruby_class_name('Blank').should == 'Blank'
18
+ mapset.serialization_config('Blank').should == nil
19
+ end
20
+
21
+ it "should properly map attribute setting" do
22
+ @conf.load_legacy(@legacy_path)
23
+ mapset = RubyAMF::ClassMapping.mappings
24
+ mapset.serialization_config('Attribute').should == {:only => ["prop_a", "prop_b"]}
25
+ end
26
+
27
+ it "should properly map association setting" do
28
+ @conf.load_legacy(@legacy_path)
29
+ mapset = RubyAMF::ClassMapping.mappings
30
+ mapset.serialization_config('Association').should == {:include => ["assoc_a", "assoc_b"]}
31
+ end
32
+
33
+ it "should properly map attribute and association setting" do
34
+ @conf.load_legacy(@legacy_path)
35
+ mapset = RubyAMF::ClassMapping.mappings
36
+ mapset.serialization_config('Both').should == {
37
+ :only => ["prop_a", "prop_b"],
38
+ :include => ["assoc_a", "assoc_b"]
39
+ }
40
+ end
41
+
42
+ it "should properly map methods setting" do
43
+ @conf.load_legacy(@legacy_path)
44
+ mapset = RubyAMF::ClassMapping.mappings
45
+ mapset.serialization_config('Method').should == {:methods => ["meth_a"]}
46
+ end
47
+
48
+ it "should properly map scoped attributes" do
49
+ @conf.load_legacy(@legacy_path)
50
+ mapset = RubyAMF::ClassMapping.mappings
51
+ mapset.serialization_config('Scoped1', :scope_1).should == {:only => ["prop_a", "prop_b"]}
52
+ mapset.serialization_config('Scoped1', "scope_2").should == {:only => ["prop_a"]}
53
+ end
54
+
55
+ it "should properly map scoped associations" do
56
+ @conf.load_legacy(@legacy_path)
57
+ mapset = RubyAMF::ClassMapping.mappings
58
+ mapset.serialization_config('Scoped2', :scope_1).should == {:include => ["assoc_a", "assoc_b"]}
59
+ mapset.serialization_config('Scoped2', :scope_2).should == {:include => ["assoc_a"]}
60
+ end
61
+
62
+ it "should properly map partially scoped settings" do
63
+ @conf.load_legacy(@legacy_path)
64
+ mapset = RubyAMF::ClassMapping.mappings
65
+ mapset.serialization_config('Scoped3', :scope_1).should == {
66
+ :only => ["prop_a", "prop_b"],
67
+ :include => ["assoc_a", "assoc_b"]
68
+ }
69
+ mapset.serialization_config('Scoped3', :scope_2).should == {
70
+ :only => ["prop_a"],
71
+ :include => ["assoc_a", "assoc_b"]
72
+ }
73
+ end
74
+
75
+ it "should properly map both scoped settings" do
76
+ @conf.load_legacy(@legacy_path)
77
+ mapset = RubyAMF::ClassMapping.mappings
78
+ mapset.serialization_config('Scoped4', :scope_1).should == {
79
+ :only => ["prop_a", "prop_b"],
80
+ :include => ["assoc_a", "assoc_b"]
81
+ }
82
+ mapset.serialization_config('Scoped4', :scope_2).should == {:only => ["prop_a"]}
83
+ mapset.serialization_config('Scoped4', :scope_3).should == {:include => ["assoc_a"]}
84
+ end
85
+
86
+ it "should properly store parameter mappings" do
87
+ @conf.load_legacy(@legacy_path)
88
+ @conf.param_mappings["Controller#action"].should == [:param_1, :param_2, nil, :param_4]
89
+ end
90
+ end
@@ -0,0 +1,106 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe RubyAMF::Envelope do
4
+ before :each do
5
+ @envelope = RubyAMF::Envelope.new
6
+ @logger = mock(RubyAMF::Logger)
7
+ @logger.stub!("log_error")
8
+ RubyAMF.configuration = RubyAMF::Configuration.new # Reset configuration
9
+ end
10
+
11
+ def create_envelope fixture
12
+ data = File.open(File.dirname(__FILE__) + '/fixtures/' + fixture).read
13
+ data.force_encoding("ASCII-8BIT") if data.respond_to?(:force_encoding)
14
+ RubyAMF::Envelope.new.populate_from_stream(StringIO.new(data))
15
+ end
16
+
17
+ it "should raise and handle returned exception objects like RubyAMF::Fault" do
18
+ RubyAMF.should_receive("logger").and_return(@logger)
19
+
20
+ res = RubyAMF::Envelope.new
21
+ req = create_envelope('remotingMessage.bin')
22
+ res.each_method_call req do |method, args|
23
+ FaultObject.new('Error in call')
24
+ end
25
+
26
+ res.messages.length.should == 1
27
+ res.messages[0].data.should be_a(RocketAMF::Values::ErrorMessage)
28
+ res.messages[0].data.faultString.should == "Error in call"
29
+ end
30
+
31
+ it "should clear backtrace from raised exceptions before serialization" do
32
+ RubyAMF.should_receive("logger").and_return(@logger)
33
+
34
+ res = RubyAMF::Envelope.new
35
+ req = create_envelope('remotingMessage.bin')
36
+ res.each_method_call req do |method, args|
37
+ raise 'Error in call'
38
+ end
39
+
40
+ res.messages.length.should == 1
41
+ res.messages[0].data.should be_a(RocketAMF::Values::ErrorMessage)
42
+ res.messages[0].data.faultDetail.should == ""
43
+ end
44
+
45
+ it "should log exceptions in each_method_call handler" do
46
+ e = Exception.new('Error in call')
47
+ @logger.should_receive("log_error").with(e).and_return(nil)
48
+ RubyAMF.should_receive("logger").and_return(@logger)
49
+
50
+ res = RubyAMF::Envelope.new
51
+ req = create_envelope('remotingMessage.bin')
52
+ res.each_method_call req do |method, args|
53
+ raise e
54
+ end
55
+ end
56
+
57
+ it "should calculate params hash from configuration" do
58
+ RubyAMF.configuration.map_params "c", "a", ["param1", :param2]
59
+ params = @envelope.params_hash "c", "a", ["asdf", "fdsa"]
60
+ params.should == {"param1" => "asdf", "param2" => "fdsa", 0 => "asdf", 1 => "fdsa"}
61
+ end
62
+
63
+ it "should respect hash_key_access for params hash" do
64
+ RubyAMF.configuration.hash_key_access = :symbol
65
+ RubyAMF.configuration.map_params "c", "a", ["param1", :param2]
66
+ params = @envelope.params_hash "c", "a", ["asdf", "fdsa"]
67
+ params.should == {:param1 => "asdf", :param2 => "fdsa", 0 => "asdf", 1 => "fdsa"}
68
+ end
69
+
70
+ it "should expose credentials set through NetConnection credentials header" do
71
+ req = create_envelope('requestWithOldCredentials.bin')
72
+ req.credentials.should == {'username' => "username", 'password' => "password"}
73
+ end
74
+
75
+ it "should expose credentials set through setRemoteCredentials" do
76
+ req = create_envelope('requestWithNewCredentials.bin')
77
+ req.credentials.should == {'username' => "username", 'password' => "password"}
78
+ end
79
+
80
+ it "should return empty credentials if unset" do
81
+ req = create_envelope('remotingMessage.bin')
82
+ req.credentials.should == {'username' => nil, 'password' => nil}
83
+ end
84
+
85
+ it "should respect hash_key_access config for credentials" do
86
+ RubyAMF.configuration.hash_key_access = :symbol
87
+ req = create_envelope('requestWithOldCredentials.bin')
88
+ req.credentials.should == {:username => "username", :password => "password"}
89
+ req = create_envelope('requestWithNewCredentials.bin')
90
+ req.credentials.should == {:username => "username", :password => "password"}
91
+ req = create_envelope('remotingMessage.bin')
92
+ req.credentials.should == {:username => nil, :password => nil}
93
+ end
94
+
95
+ it "should respect translate_case config for credentials" do
96
+ RubyAMF.configuration.translate_case = true
97
+ req = create_envelope('requestWithOldCredentials.bin')
98
+ req.credentials.should == {'username' => "username", 'password' => "password"}
99
+ req = create_envelope('requestWithNewCredentials.bin')
100
+ req.messages[0].data.messageId.should == "CA4F7056-317E-FC0C-BEDA-DFFC8B3AA791"
101
+ req.credentials.should == {'username' => "username", 'password' => "password"}
102
+ req = create_envelope('remotingMessage.bin')
103
+ req.messages[0].data.messageId.should == "FE4AF2BC-DD3C-5470-05D8-9971D51FF89D"
104
+ req.credentials.should == {'username' => nil, 'password' => nil}
105
+ end
106
+ end
Binary file
@@ -0,0 +1,24 @@
1
+ require 'app/configuration'
2
+ module RubyAMF
3
+ module Configuration
4
+ ClassMappings.ignore_fields = ['changed']
5
+ ClassMappings.translate_case = true
6
+ ClassMappings.hash_key_access = :string
7
+ ClassMappings.assume_types = true
8
+ ClassMappings.use_array_collection = true
9
+ ClassMappings.check_for_associations = false
10
+ ParameterMappings.always_add_to_params = false
11
+
12
+ ClassMappings.register(:actionscript => 'Blank', :ruby => 'Blank', :type => 'active_record')
13
+ ClassMappings.register(:actionscript => 'Attribute', :ruby => 'Attribute', :type => 'active_record', :attributes => ["prop_a", "prop_b"])
14
+ ClassMappings.register(:actionscript => 'Association', :ruby => 'Association', :type => 'active_record', :associations=> ["assoc_a", "assoc_b"])
15
+ ClassMappings.register(:actionscript => 'Both', :ruby => 'Both', :type => 'active_record', :attributes => ["prop_a", "prop_b"], :associations=> ["assoc_a", "assoc_b"])
16
+ ClassMappings.register(:actionscript => 'Method', :ruby => 'Method', :methods => ["meth_a"])
17
+ ClassMappings.register(:actionscript => 'Scoped1', :ruby => 'Scoped1', :attributes => {"scope_1" => ["prop_a", "prop_b"], "scope_2" => ["prop_a"]})
18
+ ClassMappings.register(:actionscript => 'Scoped2', :ruby => 'Scoped2', :associations => {:scope_1 => ["assoc_a", "assoc_b"], :scope_2 => ["assoc_a"]})
19
+ ClassMappings.register(:actionscript => 'Scoped3', :ruby => 'Scoped3', :attributes => {"scope_1" => ["prop_a", "prop_b"], "scope_2" => ["prop_a"]}, :associations => ["assoc_a", "assoc_b"])
20
+ ClassMappings.register(:actionscript => 'Scoped4', :ruby => 'Scoped4', :attributes => {"scope_1" => ["prop_a", "prop_b"], "scope_2" => ["prop_a"]}, :associations => {"scope_1" => ["assoc_a", "assoc_b"], "scope_3" => ["assoc_a"]})
21
+
22
+ ParameterMappings.register(:controller => :Controller, :action => :action, :params => {:param_1 => "[0]", :param_2 => "[1]", :param_4 => "[3]"})
23
+ end
24
+ end
@@ -0,0 +1,281 @@
1
+ require "spec_helper.rb"
2
+
3
+ # Include in ActiveRecord because rails bootstrap not triggered in specs
4
+ require "rubyamf/rails/model"
5
+ ActiveRecord::Base.send(:include, RubyAMF::Rails::Model)
6
+
7
+ describe RubyAMF::Model do
8
+ before :all do
9
+ class SimpleModelTestObject
10
+ include RubyAMF::Model
11
+ attr_accessor :prop_a, :prop_b
12
+ def initialize
13
+ @prop_a = "asdf"
14
+ @prop_b = "fdsa"
15
+ end
16
+ end
17
+
18
+ class ModelTestObject
19
+ include RubyAMF::Model
20
+ attr_accessor :attributes, :settable_method
21
+ def initialize
22
+ @attributes = {"prop_a" => "asdf", "prop_b" => "fdsa"}
23
+ end
24
+ def a_method
25
+ "result"
26
+ end
27
+ end
28
+
29
+ p = Parent.create :name => "parent"
30
+ p.children.create :name => "child 1"
31
+ p.children.create :name => "child 2"
32
+ p.home = Home.create :address => "1234 Main St."
33
+ end
34
+
35
+ before :each do
36
+ RubyAMF::ClassMapper.reset
37
+ RubyAMF.configuration = RubyAMF::Configuration.new
38
+ end
39
+
40
+ describe 'configuration' do
41
+ it "should map ruby class to flash class" do
42
+ ModelTestObject.module_eval do
43
+ as_class "as"
44
+ actionscript_class "actionscript"
45
+ flash_class "flash"
46
+ end
47
+ m = RubyAMF::ClassMapper.mappings
48
+ m.get_as_class_name("ModelTestObject").should == "flash"
49
+ m.get_ruby_class_name("flash").should == "ModelTestObject"
50
+ end
51
+
52
+ it "should save serialization configs to class mapper" do
53
+ ModelTestObject.module_eval do
54
+ as_class "com.test.ASClass"
55
+ map_amf :only => "prop_a"
56
+ map_amf :testing, :only => "prop_b"
57
+ map_amf :default_scope => :asdf, :only => "prop_c"
58
+ end
59
+ m = RubyAMF::ClassMapper.mappings
60
+ m.get_as_class_name("ModelTestObject").should == "com.test.ASClass"
61
+ m.get_ruby_class_name("com.test.ASClass").should == "ModelTestObject"
62
+ m.serialization_config("ModelTestObject", :default).should == {:only => "prop_a"}
63
+ m.serialization_config("ModelTestObject", :testing).should == {:only => "prop_b"}
64
+ m.serialization_config("ModelTestObject", :asdf).should == {:only => "prop_c"}
65
+ end
66
+
67
+ it "should work with RocketAMF class mapper" do
68
+ # Swap out class mapper
69
+ old_mapper = RubyAMF.send(:remove_const, :ClassMapper)
70
+ RubyAMF.const_set(:ClassMapper, RocketAMF::ClassMapping)
71
+
72
+ # Test it
73
+ ModelTestObject.module_eval do
74
+ as_class "com.test.ASClass"
75
+ map_amf :only => "prop_a"
76
+ map_amf :testing, :only => "prop_b"
77
+ map_amf :default_scope => :asdf, :only => "prop_c"
78
+ end
79
+ m = RubyAMF::ClassMapper.mappings
80
+ m.get_as_class_name("ModelTestObject").should == "com.test.ASClass"
81
+ m.get_ruby_class_name("com.test.ASClass").should == "ModelTestObject"
82
+
83
+ # Swap old class mapper back in
84
+ RubyAMF.send(:remove_const, :ClassMapper)
85
+ RubyAMF.const_set(:ClassMapper, old_mapper)
86
+ end
87
+ end
88
+
89
+ describe 'deserialization' do
90
+ it "should populate simple object properly from deserialization" do
91
+ t = SimpleModelTestObject.allocate
92
+ t.rubyamf_init({:prop_a => "seta", :prop_b => "setb"})
93
+ t.prop_a.should == "seta"
94
+ t.prop_b.should == "setb"
95
+ end
96
+
97
+ it "should populate fully-conforming object properly from deserialization" do
98
+ t = ModelTestObject.allocate
99
+ t.rubyamf_init({"prop_a" => "seta"}, {"prop_b" => "setb"}) # classmapper would pass symbolic keys - oh well?
100
+ t.attributes.should == {"prop_a" => "seta", "prop_b" => "setb"}
101
+ end
102
+
103
+ it "should call setters for non-attributes" do
104
+ t = ModelTestObject.allocate
105
+ t.rubyamf_init({"prop_a" => "seta", "settable_method" => "meth"})
106
+ t.attributes.should == {"prop_a" => "seta"}
107
+ t.settable_method.should == "meth"
108
+ end
109
+ end
110
+
111
+ describe 'serialization' do
112
+ it "should return an IntermediateObject when to_amf is called" do
113
+ t = ModelTestObject.new
114
+ obj = t.to_amf({:only => "prop_a"})
115
+ obj.should be_a(RubyAMF::IntermediateObject)
116
+ obj.object.should == t
117
+ obj.options.should == {:only => "prop_a"}
118
+ end
119
+
120
+ it "should convert simple object to serializable hash" do
121
+ t = SimpleModelTestObject.new
122
+ t.rubyamf_hash.should == {"prop_a" => "asdf", "prop_b" => "fdsa"}
123
+ t.rubyamf_hash(:only => "prop_a").should == {"prop_a" => "asdf"}
124
+ t.rubyamf_hash(:except => ["prop_a"]).should == {"prop_b" => "fdsa"}
125
+ end
126
+
127
+ it "should convert fully-conforming object to serializable hash" do
128
+ t = ModelTestObject.new
129
+ t.rubyamf_hash.should == t.attributes
130
+ t.rubyamf_hash(:only => "prop_a").should == {"prop_a" => "asdf"}
131
+ t.rubyamf_hash(:except => ["prop_a"]).should == {"prop_b" => "fdsa"}
132
+ t.rubyamf_hash(:methods => :a_method).should == {"prop_a" => "asdf", "prop_b" => "fdsa", "a_method" => "result"}
133
+ end
134
+
135
+ it "should properly process generic includes" do
136
+ t = ModelTestObject.new
137
+ t.should_receive(:courses).and_return([ModelTestObject.new])
138
+ h = t.rubyamf_hash(:except => "prop_a", :include => :courses)
139
+ h.keys.sort.should == ["courses", "prop_b"]
140
+ h["prop_b"].should == "fdsa"
141
+ h["courses"].length.should == 1
142
+ h["courses"][0].class.should == ModelTestObject
143
+ end
144
+
145
+ it "should convert configured includes to IntermediateObjects" do
146
+ t = ModelTestObject.new
147
+ t.should_receive(:courses).and_return([ModelTestObject.new])
148
+ h = t.rubyamf_hash(:except => "prop_a", :include => {:courses => {:except => "prop_b"}})
149
+ h.keys.sort.should == ["courses", "prop_b"]
150
+ h["prop_b"].should == "fdsa"
151
+ h["courses"].length.should == 1
152
+ h["courses"][0].options.should == {:except => "prop_b"}
153
+ end
154
+ end
155
+
156
+ # Need to run these tests against rails 2.3, 3.0, and 3.1
157
+ describe 'ActiveRecord' do
158
+ describe 'deserialization' do
159
+
160
+ it "should create new records if no id given" do
161
+ c = Child.allocate
162
+ c.rubyamf_init({:name => "Foo Bar"})
163
+ c.name.should == "Foo Bar"
164
+ c.new_record?.should == true
165
+ c.changed.should == ["name"]
166
+ end
167
+
168
+ it "should create new records if id is 'empty'" do
169
+ c = Child.allocate
170
+ c.rubyamf_init({:id => 0, :name => "Foo Bar"})
171
+ c.name.should == "Foo Bar"
172
+ c.new_record?.should == true
173
+ c.changed.should == ["name"]
174
+
175
+ c = Child.allocate
176
+ c.rubyamf_init({:id => nil, :name => "Foo Bar"})
177
+ c.name.should == "Foo Bar"
178
+ c.new_record?.should == true
179
+ c.changed.should == ["name"]
180
+ end
181
+
182
+ it "should determine whether a record is new if composite PK" do
183
+ # Create composite child in DB
184
+ c = CompositeChild.new
185
+ c.id = [10, "blah"]
186
+ c.save
187
+
188
+ # Check it
189
+ c = CompositeChild.allocate
190
+ c.rubyamf_init({:id => 10, :name => "blah"})
191
+ c.id.should == [10, "blah"]
192
+ c.new_record?.should == false
193
+ c.changed.should == []
194
+ end
195
+
196
+ it "should properly initialize 'existing' objects" do
197
+ c = Child.allocate
198
+ c.rubyamf_init({:id => 5, :name => "Bar Foo"})
199
+ c.id.should == 5
200
+ c.name.should == "Bar Foo"
201
+ c.new_record?.should == false
202
+ c.changed.should == ["name"]
203
+ end
204
+
205
+ it "should properly initialize STI objects"
206
+
207
+ context "associations" do
208
+ let(:p) { Parent.allocate }
209
+ let(:c) { Child.allocate }
210
+ let(:p_with_associations) { Parent.allocate }
211
+
212
+ def create_deserialized_parent_with_associations children=nil, home=nil, save_parent=true
213
+ p_with_associations.rubyamf_init({:id => p.id, :name => "parent", :children => children, :home => home})
214
+ p_with_associations.save if save_parent
215
+ end
216
+
217
+ before :each do
218
+ c.rubyamf_init({:name => "Foo Bar"})
219
+ p.rubyamf_init({:name => "parent", :children => [c]})
220
+ p.children.length.should == 1
221
+ p.save
222
+ end
223
+
224
+ it "should deserialize associations" do
225
+ p.children[0].parent_id.should == p.id
226
+ end
227
+
228
+ it "should deserialize and not clear empty associations" do
229
+ create_deserialized_parent_with_associations []
230
+ p_with_associations.children(true).length.should == 1
231
+ end
232
+
233
+ it "should ignore nil associations" do
234
+ create_deserialized_parent_with_associations nil
235
+ p_with_associations.children(true).length.should == 1
236
+ end
237
+
238
+ it "should deserialize and not automatically save associations" do
239
+ c2 = Child.allocate
240
+ c2.rubyamf_init({:name => "Foo Bars"})
241
+ h = Home.allocate
242
+ h.rubyamf_init(:address => "1234 Here")
243
+ create_deserialized_parent_with_associations [c2], h, false
244
+ c2.should be_new_record
245
+ h.should be_new_record
246
+ p_with_associations.save
247
+ c2.should_not be_new_record
248
+ h.should_not be_new_record
249
+ end
250
+ end
251
+ end
252
+
253
+ describe 'serialization' do
254
+ it "should support serializing associations" do
255
+ h = Parent.first.rubyamf_hash(:include => [:children])
256
+ h["children"].length.should == 2
257
+ end
258
+
259
+ it "should support serializing associations with configurations" do
260
+ h = Parent.first.rubyamf_hash(:include => {:children => {:only => "name"}})
261
+ h["children"].length.should == 2
262
+ end
263
+
264
+ it "should support automatically including loaded relations without belongs_to" do
265
+ # No associations pre-loaded
266
+ p = Parent.first
267
+ p.rubyamf_hash.should == {"id" => 1, "name" => "parent"}
268
+
269
+ # Force associations to load
270
+ p.children.to_a
271
+ p.home
272
+
273
+ # Associations should be in hash
274
+ h = p.rubyamf_hash
275
+ h["children"].length.should == 2
276
+ h["children"][0].rubyamf_hash.should == {"id" => 1, "name" => "child 1", "parent_id" => 1}
277
+ h["home"].should == p.home
278
+ end
279
+ end
280
+ end
281
+ end