api_resource 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.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