api_resource 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec CHANGED
@@ -5,4 +5,5 @@
5
5
  --fail-fast
6
6
  -X
7
7
  --order random
8
- --drb
8
+ --drb
9
+ #--debugger
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- api_resource (0.6.2)
4
+ api_resource (0.6.3)
5
5
  colorize
6
6
  differ
7
7
  json
data/api_resource.gemspec CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |gem|
31
31
  gem.add_development_dependency "flog"
32
32
  gem.add_development_dependency "hash_dealer"
33
33
  gem.add_development_dependency "rb-fsevent"
34
- gem.add_development_dependency "ruby-debug19"
34
+ # gem.add_development_dependency "ruby-debug19"
35
35
  gem.add_development_dependency "simplecov"
36
36
  # stuff that seems like crap
37
37
  gem.add_development_dependency "sqlite3"
@@ -5,7 +5,11 @@ module ApiResource
5
5
  included do
6
6
  class_attribute :association_types
7
7
  # our default association types
8
- self.association_types = {:belongs_to => :single, :has_one => :single, :has_many => :multi}
8
+ self.association_types = {
9
+ :belongs_to => :belongs_to_remote,
10
+ :has_one => :has_one_remote,
11
+ :has_many => :has_many_remote
12
+ }
9
13
  end
10
14
 
11
15
  module ClassMethods
@@ -90,7 +90,7 @@ module ApiResource
90
90
  klass.related_objects = klass.related_objects.merge(:#{assoc} => klass.related_objects[:#{assoc}].merge(arg.to_sym => klass_name))
91
91
  end
92
92
  # We need to define reader and writer methods here
93
- define_association_as_attribute(:#{assoc}, arg)
93
+ define_association_as_attribute(:#{assoc}, arg, options)
94
94
  end
95
95
  end
96
96
 
@@ -184,8 +184,10 @@ module ApiResource
184
184
  self.related_objects[:scopes] = self.related_objects[:scopes].clone
185
185
  end
186
186
 
187
- def define_association_as_attribute(assoc_type, assoc_name)
188
- id_method_name = association_foreign_key_field(assoc_name, assoc_type)
187
+ def define_association_as_attribute(assoc_type, assoc_name, opts)
188
+ id_method_name = association_foreign_key_field(
189
+ assoc_name, assoc_type
190
+ )
189
191
 
190
192
  # set up dirty tracking for associations, but only for ApiResource
191
193
  # these methods are also used for ActiveRecord
@@ -194,59 +196,24 @@ module ApiResource
194
196
  define_attribute_method(assoc_name)
195
197
  define_attribute_method(id_method_name)
196
198
  end
197
- # TODO: Come up with a better implementation for the foreign key thing
198
- # implement the rest of the active record methods, refactor this into something
199
- # a little bit more sensible
200
-
201
- # TODO: This should support saving the ids when they are modified and saving anything
202
- # that is not created, associations need to be their own object
203
- self.class_eval <<-EOE, __FILE__, __LINE__ + 1
204
- def #{assoc_name}
205
- @attributes_cache[:#{assoc_name}] ||= begin
206
- klass = Associations::#{self.association_types[assoc_type.to_sym].to_s.classify}ObjectProxy
207
- instance = klass.new(
208
- self.association_class('#{assoc_name}'), self
209
- )
210
- if @attributes[:#{assoc_name}].present?
211
- instance.internal_object = @attributes[:#{assoc_name}]
212
- end
213
- instance
214
- end
215
- end
216
- def #{assoc_name}=(val, force = true)
217
- if !force
218
- #{assoc_name}_will_change!
219
- elsif self.#{assoc_name}.internal_object != val
220
- #{assoc_name}_will_change!
221
- end
222
- # This should not force a load
223
- self.#{assoc_name}.internal_object = val
224
- end
225
- def #{assoc_name}?
226
- self.#{assoc_name}.internal_object.present?
227
- end
228
-
229
- def #{id_method_name}
230
- @attributes_cache[:#{id_method_name}] ||= begin
231
- if @attributes.has_key?("#{id_method_name}")
232
- @attributes["#{id_method_name}"]
233
- elsif self.#{assoc_name}.collection?
234
- self.#{assoc_name}.collect(&:id)
235
- else
236
- self.#{assoc_name}? ? self.#{assoc_name}.id : nil
237
- end
238
- end
239
- end
199
+
200
+ # a module to contain our generated methods
201
+ cattr_accessor :api_resource_generated_methods
202
+ self.api_resource_generated_methods = Module.new
203
+ # include our anonymous module
204
+ include self.api_resource_generated_methods
240
205
 
241
- def #{id_method_name}=(val, force = false)
242
- unless @attributes_cache[:#{id_method_name}] == val
243
- #{id_method_name}_will_change!
244
- end
245
- @attributes_cache[:#{id_method_name}] = val
246
- write_attribute(:#{id_method_name}, val)
247
- end
206
+ # we let our concrete classes define this behavior
207
+ type = self.association_types[assoc_type.to_sym].to_s.classify
208
+ klass = "::ApiResource::Associations::#{type}ObjectProxy"
209
+ klass = klass.constantize
248
210
 
249
- EOE
211
+ # gives us the namespaced classname
212
+ opts[:class_name] = self.find_namespaced_class_name(
213
+ opts[:class_name] || assoc_name.to_s.classify
214
+ )
215
+
216
+ klass.define_association_as_attribute(self, assoc_name, opts)
250
217
  end
251
218
 
252
219
  def find_namespaced_class_name(klass)
@@ -12,10 +12,63 @@ module ApiResource
12
12
  attr_reader :owner, :klass, :finder_opts
13
13
 
14
14
  # TODO: add the other load forcing methods here for collections
15
- delegate :[], :[]=, :<<, :first, :second, :last, :blank?, :nil?, :include?, :push, :pop,
16
- :+, :concat, :flatten, :flatten!, :compact, :compact!, :empty?, :fetch, :map,
17
- :reject, :reject!, :reverse, :select, :select!, :size, :sort, :sort!, :uniq, :uniq!,
18
- :to_a, :sample, :slice, :slice!, :count, :present?, :to => :internal_object
15
+ delegate :[], :[]=, :<<, :first, :second, :last, :blank?, :nil?,
16
+ :include?, :push, :pop, :+, :concat, :flatten, :flatten!, :compact,
17
+ :compact!, :empty?, :fetch, :map, :reject, :reject!, :reverse,
18
+ :select, :select!, :size, :sort, :sort!, :uniq, :uniq!, :to_a,
19
+ :sample, :slice, :slice!, :count, :present?,
20
+ :to => :internal_object
21
+
22
+ # define association methods on the class
23
+ def self.define_association_as_attribute(klass, assoc_name, opts = {})
24
+
25
+ id_method_name = self.foreign_key_name(assoc_name)
26
+ associated_class = opts[:class_name] || assoc_name.to_s.classify
27
+
28
+ klass.api_resource_generated_methods.module_eval <<-EOE, __FILE__, __LINE__ + 1
29
+ def #{assoc_name}
30
+ @attributes_cache[:#{assoc_name}] ||= begin
31
+ instance = #{self}.new(#{associated_class}, self)
32
+ if @attributes[:#{assoc_name}].present?
33
+ instance.internal_object = @attributes[:#{assoc_name}]
34
+ end
35
+ instance
36
+ end
37
+ end
38
+ def #{assoc_name}=(val, force = true)
39
+ if !force
40
+ #{assoc_name}_will_change!
41
+ elsif self.#{assoc_name}.internal_object != val
42
+ #{assoc_name}_will_change!
43
+ end
44
+ # This should not force a load
45
+ self.#{assoc_name}.internal_object = val
46
+ end
47
+
48
+ def #{assoc_name}?
49
+ self.#{assoc_name}.internal_object.present?
50
+ end
51
+
52
+ # writer is the same for everyone
53
+ def #{id_method_name}=(val, force = false)
54
+ unless @attributes_cache[:#{id_method_name}] == val
55
+ #{id_method_name}_will_change!
56
+ end
57
+ @attributes_cache[:#{id_method_name}] = val
58
+ write_attribute(:#{id_method_name}, val)
59
+ end
60
+
61
+ EOE
62
+ end
63
+
64
+ protected
65
+
66
+ # return a foreign key name from an association
67
+ def self.foreign_key_name(assoc_name)
68
+ assoc_name.to_s.singularize.foreign_key
69
+ end
70
+
71
+ public
19
72
 
20
73
  def initialize(klass, owner, opts = {})
21
74
 
@@ -1,6 +1,7 @@
1
1
  module ApiResource
2
2
  module Associations
3
3
  class BelongsToRemoteObjectProxy < SingleObjectProxy
4
+
4
5
  def initialize(klass, owner)
5
6
  super(klass, owner)
6
7
 
@@ -1,11 +1,44 @@
1
1
  module ApiResource
2
2
  module Associations
3
3
  class HasManyRemoteObjectProxy < MultiObjectProxy
4
- def initialize(klass, owner)
5
- super(klass, owner)
6
- self.remote_path = self.klass.collection_path(
7
- self.owner.class.to_s.foreign_key => self.owner.id
8
- )
4
+
5
+ # defines a method to get the foreign key
6
+ def self.define_association_as_attribute(klass, assoc_name, opts = {})
7
+ id_method_name = self.foreign_key_name(assoc_name)
8
+
9
+ klass.api_resource_generated_methods.module_eval <<-EOE, __FILE__, __LINE__ + 1
10
+
11
+ def #{id_method_name}
12
+ @attributes_cache[:#{id_method_name}] ||= begin
13
+ # check our attributes first, then go to the remote
14
+ @attributes[:#{id_method_name}] || self.#{assoc_name}.collect(
15
+ &:id
16
+ )
17
+ end
18
+ end
19
+ EOE
20
+ super
21
+ end
22
+
23
+ protected
24
+ # gets the foreign key name for a given association
25
+ # e.g. service_ids
26
+ def self.foreign_key_name(assoc_name)
27
+ super(assoc_name).pluralize
28
+ end
29
+
30
+ public
31
+
32
+ def internal_object
33
+ # if we don't have a remote path and we do have and id,
34
+ # we set it before we call the internal object
35
+ # this lets us dynamically generate the correct path
36
+ if self.remote_path.blank? && self.owner.try(:id).present?
37
+ self.remote_path = self.klass.collection_path(
38
+ self.owner.class.to_s.foreign_key => self.owner.id
39
+ )
40
+ end
41
+ super
9
42
  end
10
43
  end
11
44
  end
@@ -2,18 +2,37 @@ module ApiResource
2
2
  module Associations
3
3
  class HasOneRemoteObjectProxy < SingleObjectProxy
4
4
 
5
- def initialize(klass, owner)
6
- super(klass, owner)
7
-
8
- # now if we have an owner and a foreign key, we set the data up to load
9
- self.remote_path = self.klass.collection_path(self.owner.class.to_s.foreign_key => self.owner.id)
5
+ # defines a method to get the id of the associated objecgt
6
+ def self.define_association_as_attribute(klass, assoc_name, opts = {})
7
+ id_method_name = self.foreign_key_name(assoc_name)
8
+
9
+ klass.api_resource_generated_methods.module_eval <<-EOE, __FILE__, __LINE__ + 1
10
+ def #{id_method_name}
11
+ self.#{assoc_name}? ? self.#{assoc_name}.id : nil
12
+ end
13
+ EOE
14
+ super
15
+ end
16
+
17
+ def internal_object
18
+ # if we don't have a remote path and we do have and id,
19
+ # we set it before we call the internal object
20
+ # this lets us dynamically generate the correct path
21
+ if self.remote_path.blank? && self.owner.try(:id).present?
22
+ self.remote_path = self.klass.collection_path(
23
+ self.owner.class.to_s.foreign_key => self.owner.id
24
+ )
25
+ end
26
+ super
10
27
  end
11
28
 
12
29
  protected
13
30
 
14
31
  # because of how this works we use a multi object proxy and return the first element
15
32
  def to_condition
16
- ApiResource::Conditions::MultiObjectAssociationCondition.new(self.klass, self.remote_path)
33
+ ApiResource::Conditions::MultiObjectAssociationCondition.new(
34
+ self.klass, self.remote_path
35
+ )
17
36
  end
18
37
 
19
38
  def load(opts = {})
@@ -25,13 +25,18 @@ module ApiResource
25
25
  end
26
26
 
27
27
  def internal_object
28
- @internal_object ||= begin
29
- if self.remote_path.present?
30
- self.load
31
- else
32
- []
33
- end
28
+
29
+ # if we don't have a remote path or any data so we set it to a
30
+ # blank array
31
+ if self.remote_path.blank? && @internal_object.blank?
32
+ return @internal_object ||= []
34
33
  end
34
+
35
+ # if we aren't loaded and we don't have data added load here
36
+ if !self.loaded? && @internal_object.blank?
37
+ @internal_object = self.load
38
+ end
39
+ @internal_object
35
40
  end
36
41
 
37
42
  def internal_object=(contents)
@@ -52,9 +57,10 @@ module ApiResource
52
57
  return @internal_object = self.klass.instantiate_collection(
53
58
  contents
54
59
  )
55
- # we have only provided the resource definition
60
+ # we have only provided the resource definition - that's the same
61
+ # as a blank array in this case
56
62
  elsif contents.nil?
57
- return @internal_object = nil
63
+ return @internal_object = []
58
64
  else
59
65
  raise ArgumentError.new(
60
66
  "#{contents} must be a #{self.klass}, #{self.class}, " +
@@ -82,7 +88,9 @@ module ApiResource
82
88
  def to_condition
83
89
  obj = nil
84
90
  obj = self.internal_object if self.loaded?
85
- ApiResource::Conditions::MultiObjectAssociationCondition.new(self.klass, self.remote_path, obj)
91
+ ApiResource::Conditions::MultiObjectAssociationCondition.new(
92
+ self.klass, self.remote_path, obj
93
+ )
86
94
  end
87
95
 
88
96
  def load(opts = {})
@@ -558,8 +558,15 @@ module ApiResource
558
558
 
559
559
  # also add in the _id fields that are changed
560
560
  ret = self.association_names.inject(ret) do |accum, assoc_name|
561
+
562
+ # get the id method for the association
561
563
  id_method = self.class.association_foreign_key_field(assoc_name)
562
- if self.changes[id_method].present?
564
+
565
+ # only do this if they are not prefix_attribute_names
566
+ # and we have changes
567
+ if !self.prefix_attribute_names.include?(id_method.to_sym) &&
568
+ self.changes[id_method].present?
569
+
563
570
  accum[id_method] = self.changes[id_method].last
564
571
  end
565
572
  accum
@@ -46,7 +46,7 @@ module ApiResource
46
46
  end
47
47
 
48
48
  def to_hash
49
- self.conditions
49
+ self.conditions.to_hash
50
50
  end
51
51
 
52
52
  def internal_object
@@ -7,7 +7,7 @@ module ApiResource
7
7
  def initialize(klass, service_uri, internal_object= nil)
8
8
  super({}, klass)
9
9
 
10
- @assocaiton = true
10
+ @association = true
11
11
  @remote_path = service_uri
12
12
  @internal_object = internal_object
13
13
  end
@@ -7,7 +7,9 @@ module ApiResource
7
7
  protected
8
8
 
9
9
  def instantiate_finder
10
- ApiResource::Finders::MultiObjectAssociationFinder.new(self.klass, self, @internal_object)
10
+ ApiResource::Finders::MultiObjectAssociationFinder.new(
11
+ self.klass, self, @internal_object
12
+ )
11
13
  end
12
14
 
13
15
  end
@@ -1,3 +1,3 @@
1
1
  module ApiResource
2
- VERSION = "0.6.3"
2
+ VERSION = "0.6.4"
3
3
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module ApiResource
4
+ module Associations
5
+
6
+ describe HasManyRemoteObjectProxy do
7
+
8
+ context "#<<" do
9
+
10
+ it "implements the shift operator" do
11
+ tr = TestResource.new
12
+ tr.has_many_objects << HasManyObject.new
13
+
14
+ tr.has_many_objects.length.should be 1
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -360,17 +360,17 @@ describe "Associations" do
360
360
  end
361
361
 
362
362
  it "should include the foreign_key_id when saving" do
363
- tr = TestResource.new
363
+ tr = TestResource.new.tap do |tr|
364
+ tr.stubs(:id => 123)
365
+ end
364
366
  tr.has_many_object_ids = [4]
365
367
  hsh = tr.serializable_hash
366
368
  hsh[:has_many_object_ids].should eql([4])
367
369
  end
368
370
 
369
- it "should serialize the foreign_key_id when saving if it is updated" do
370
- tr = TestResource.find(1)
371
- tr.has_many_object_ids = [5]
372
- hsh = tr.serializable_hash
373
- hsh[:has_many_object_ids].should eql([5])
371
+ it "should handle loading attributes from the remote" do
372
+ tr = TestResource.instantiate_record({:has_many_object_ids => [3]})
373
+ tr.has_many_object_ids.should eql([3])
374
374
  end
375
375
 
376
376
  it "should not try to load if the foreign key is nil" do
@@ -682,17 +682,38 @@ describe "Associations" do
682
682
  before(:all) do
683
683
  TestResource.has_one(:has_one_object)
684
684
  TestResource.belongs_to(:belongs_to_object)
685
+ HasManyObject.reload_class_attributes
686
+ BelongsToObject.reload_class_attributes
687
+ HasOneObject.reload_class_attributes
685
688
  end
686
689
  after(:all) do
687
690
  TestResource.reload_class_attributes
688
691
  end
689
692
 
690
- it "should assign associations to the correct type on initialization" do
691
- #binding.pry
692
- tr = TestResource.new(:has_one_object => {:name => "Dan"}, :belongs_to_object => {:name => "Dan"})
693
+ it "should assign associations to the correct
694
+ type on initialization" do
695
+
696
+ tr = TestResource.new(
697
+ :has_one_object => {:color => "Blue"},
698
+ :belongs_to_object => {:zip => "11201"},
699
+ :has_many_objects => [{:name => "Dan"}]
700
+ )
701
+
702
+ tr.has_one_object.internal_object.should be_instance_of(
703
+ HasOneObject
704
+ )
705
+ tr.has_one_object.color.should eql("Blue")
706
+
707
+ tr.belongs_to_object.internal_object.should be_instance_of(
708
+ BelongsToObject
709
+ )
710
+ tr.belongs_to_object.zip.should eql("11201")
693
711
 
694
- tr.has_one_object.internal_object.should be_instance_of HasOneObject
695
- tr.belongs_to_object.internal_object.should be_instance_of BelongsToObject
712
+
713
+ tr.has_many_objects.internal_object.first.should be_instance_of(
714
+ HasManyObject
715
+ )
716
+ tr.has_many_objects.first.name.should eql("Dan")
696
717
 
697
718
  end
698
719
 
@@ -706,15 +727,12 @@ describe "Associations" do
706
727
  end
707
728
 
708
729
  it "should be able to reload a single-object association" do
709
- ApiResource::Associations::SingleObjectProxy.any_instance.stubs(:remote_path => "/has_one_objects")
710
- HasOneObject.connection.stubs(:get => nil)
711
-
730
+
712
731
  tr = TestResource.new()
713
-
714
732
  tr.has_one_object = {:color => "Blue"}
715
733
 
716
734
  tr.has_one_object.reload
717
- tr.has_one_object.instance_variable_get(:@internal_object).should be_blank
735
+ tr.has_one_object.should be_nil
718
736
  end
719
737
 
720
738
  end
@@ -740,16 +758,38 @@ describe "Associations" do
740
758
  end
741
759
 
742
760
  it "should be able to reload a multi-object association" do
743
- ApiResource::Associations::MultiObjectProxy.any_instance.stubs(:remote_path => "/has_many_objects")
744
- ApiResource::Connection.any_instance.stubs(:get => [])
761
+
762
+ # do this to load the resource definition
763
+ TestResource.reload_resource_definition
764
+ HasManyObject.reload_resource_definition
745
765
 
746
- tr = TestResource.new(:has_many_objects => [{:color => "blue"}])
766
+ tr = TestResource.new
767
+ tr.has_many_objects = [{:name => "Dan"}]
747
768
 
748
769
  tr.has_many_objects.reload
749
-
750
770
  tr.has_many_objects.should be_blank
751
771
  end
752
772
 
773
+ it "should be able to override service_uri for a
774
+ multi-object association" do
775
+
776
+ tr = TestResource.new
777
+ tr.has_many_objects = [{:service_uri => "/a/b/c"}]
778
+
779
+ tr.has_many_objects.remote_path.should eql("/a/b/c")
780
+
781
+ end
782
+
783
+ it "should be able to override service_uri for a multi-object
784
+ association when loaded with instantiate_record" do
785
+
786
+ tr = TestResource.instantiate_record(
787
+ :has_many_objects => [{:service_uri => "/a/b/c"}]
788
+ )
789
+
790
+ tr.has_many_objects.remote_path.should eql("/a/b/c")
791
+ end
792
+
753
793
  end
754
794
 
755
795
  context "ActiveModel" do
@@ -853,6 +893,7 @@ describe "Associations" do
853
893
  [{"name" => "testing", "id" => 22}]
854
894
  )
855
895
  # load the test resource
896
+ tar.has_many_objects.internal_object
856
897
  tar.has_many_objects.first.name.should eql "testing"
857
898
  tar.has_many_object_ids.should eql([22])
858
899
  end
@@ -61,6 +61,40 @@ describe "Base" do
61
61
 
62
62
  end
63
63
 
64
+
65
+ context "Prefixes" do
66
+
67
+ before(:all) do
68
+ TestResource.prefix = "/belongs_to_objects/:belongs_to_object_id/"
69
+ end
70
+
71
+ after(:all) do
72
+ TestResource.prefix = "/"
73
+ end
74
+
75
+ context "#create" do
76
+
77
+ it "should place prefix data in the URL and remove it from
78
+ the parameters" do
79
+
80
+ TestResource.connection.expects(:post).with(
81
+ "/belongs_to_objects/22/test_resources.json", JSON.unparse(
82
+ :test_resource => {
83
+ :name => "Dan"
84
+ }
85
+ ),
86
+ TestResource.headers
87
+ )
88
+
89
+ TestResource.create(:belongs_to_object_id => 22, :name => "Dan")
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+
64
98
  context "Comparison" do
65
99
 
66
100
  context "&group_by" do
@@ -521,8 +555,17 @@ describe "Base" do
521
555
 
522
556
  it "should include nil attributes when creating if include_nil_attributes_on_create is true" do
523
557
  ApiResource::Connection.any_instance.expects(:post).with(
524
- "/test_resources.json",
525
- "{\"test_resource\":{\"name\":\"Ethan\",\"age\":null,\"is_active\":null,\"bday\":null,\"roles\":[]}}",
558
+ "/test_resources.json", JSON.unparse(
559
+ :test_resource => {
560
+ :name => "Ethan",
561
+ :age => nil,
562
+ :is_active => nil,
563
+ :belongs_to_object_id => nil,
564
+ :custom_name_id => nil,
565
+ :bday => nil,
566
+ :roles => []
567
+ }
568
+ ),
526
569
  TestResource.headers
527
570
  )
528
571
 
@@ -577,16 +620,19 @@ describe "Base" do
577
620
  JSON.unparse({
578
621
  :test_resource => {
579
622
  :name => "Ethan",
580
- :has_many_objects => [{}]
623
+ :has_many_objects => [{:name => "Test"}]
581
624
  }
582
625
  }),
583
626
  TestResource.headers
584
627
  )
585
628
 
586
- tr = TestResource.new(:name => "Ethan")
629
+ tr = TestResource.new(
630
+ :name => "Ethan",
631
+ :has_many_objects => [{:id => 12, :name => "Dan"}]
632
+ )
587
633
  tr.stubs(:id => 1)
588
634
 
589
- tr.has_many_objects = [HasManyObject.new]
635
+ tr.has_many_objects = [HasManyObject.new(:name => "Test")]
590
636
  tr.save
591
637
  end
592
638
 
@@ -603,9 +649,10 @@ describe "Base" do
603
649
  TestResource.headers
604
650
  )
605
651
 
606
- tr = TestResource.new(:name => "Ethan")
652
+ tr = TestResource.new(:name => "Ethan", :has_many_objects => [])
607
653
  tr.stubs(:id => 1)
608
- tr.save(:has_many_objects)
654
+
655
+ tr.save(:include_associations => [:has_many_objects])
609
656
  end
610
657
 
611
658
 
@@ -688,8 +735,17 @@ describe "Base" do
688
735
  it "should include all attributes if include_all_attributes_on_update is true" do
689
736
 
690
737
  ApiResource::Connection.any_instance.expects(:put).with(
691
- "/test_resources/1.json",
692
- "{\"test_resource\":{\"name\":\"Ethan\",\"age\":null,\"is_active\":null,\"bday\":null,\"roles\":[]}}",
738
+ "/test_resources/1.json", JSON.unparse(
739
+ :test_resource => {
740
+ :name => "Ethan",
741
+ :age => nil,
742
+ :is_active => nil,
743
+ :belongs_to_object_id => nil,
744
+ :custom_name_id => nil,
745
+ :bday => nil,
746
+ :roles => []
747
+ }
748
+ ),
693
749
  TestResource.headers
694
750
  )
695
751
  begin
data/spec/spec_helper.rb CHANGED
@@ -14,8 +14,8 @@ Spork.prefork do
14
14
  require 'api_resource'
15
15
  require 'simplecov'
16
16
 
17
- require 'ruby-debug'
18
- Debugger.start
17
+ # require 'ruby-debug'
18
+ # Debugger.start
19
19
 
20
20
 
21
21
  SimpleCov.start do
@@ -39,6 +39,13 @@ Mocks.define do
39
39
  }
40
40
  })
41
41
  end
42
+
43
+ endpoint("/has_one_objects.json") do
44
+ get(
45
+ [HashDealer.roll(:has_one_object)],
46
+ :params => {:test_resource_id => 1}.matcher
47
+ )
48
+ end
42
49
 
43
50
  endpoint("/has_many_objects/new") do
44
51
  get({
@@ -47,6 +54,13 @@ Mocks.define do
47
54
  }
48
55
  })
49
56
  end
57
+
58
+ endpoint("/has_many_objects.json") do
59
+ get(
60
+ [HashDealer.roll(:has_many_object)],
61
+ :params => {:test_resource_id => 1}.matcher
62
+ )
63
+ end
50
64
 
51
65
  endpoint("/belongs_to_objects/new") do
52
66
  get({
@@ -1,7 +1,15 @@
1
1
  HashDealer.define(:new_test_object) do
2
2
  attributes({
3
3
  :protected => [:id, :protected_attr],
4
- :public => [:name, :age, :is_active, [:bday, :date], [:roles, :array]]
4
+ :public => [
5
+ :name,
6
+ :age,
7
+ :is_active,
8
+ :belongs_to_object_id,
9
+ :custom_name_id,
10
+ [:bday, :date],
11
+ [:roles, :array]
12
+ ]
5
13
  })
6
14
  scopes({
7
15
  :active => {},
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-04-12 00:00:00.000000000 Z
14
+ date: 2013-04-16 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rake
@@ -221,22 +221,6 @@ dependencies:
221
221
  - - ! '>='
222
222
  - !ruby/object:Gem::Version
223
223
  version: '0'
224
- - !ruby/object:Gem::Dependency
225
- name: ruby-debug19
226
- requirement: !ruby/object:Gem::Requirement
227
- none: false
228
- requirements:
229
- - - ! '>='
230
- - !ruby/object:Gem::Version
231
- version: '0'
232
- type: :development
233
- prerelease: false
234
- version_requirements: !ruby/object:Gem::Requirement
235
- none: false
236
- requirements:
237
- - - ! '>='
238
- - !ruby/object:Gem::Version
239
- version: '0'
240
224
  - !ruby/object:Gem::Dependency
241
225
  name: simplecov
242
226
  requirement: !ruby/object:Gem::Requirement
@@ -440,6 +424,7 @@ files:
440
424
  - nohup.out
441
425
  - spec/lib/api_resource_spec.rb
442
426
  - spec/lib/associations/association_scope_spec.rb
427
+ - spec/lib/associations/has_many_remote_object_proxy_spec.rb
443
428
  - spec/lib/associations_spec.rb
444
429
  - spec/lib/attributes_spec.rb
445
430
  - spec/lib/base_spec.rb
@@ -500,6 +485,7 @@ summary: ActiveRecord for restful APIs
500
485
  test_files:
501
486
  - spec/lib/api_resource_spec.rb
502
487
  - spec/lib/associations/association_scope_spec.rb
488
+ - spec/lib/associations/has_many_remote_object_proxy_spec.rb
503
489
  - spec/lib/associations_spec.rb
504
490
  - spec/lib/attributes_spec.rb
505
491
  - spec/lib/base_spec.rb