rubyamf-ouvrages 2.0.0

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