Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Active Resource Associations #68

Closed
wants to merge 83 commits into from

2 participants

@gramos

Related to this post:
http://groups.google.com/group/rubyonrails-core/browse_thread/thread/15d57967f94c5561

I added a basic first version of associations to Active Resource, it try follow the same behaviour than Active Record, at the moment it support only one-to-one and one-to-many associations, I'll be happy to continue working on this.

Gastón Ramos

gramos added some commits
@gramos gramos - added associations module
- added asociations unit test file
eba7283
@gramos gramos - added first version of ActiveResource has_one associaion method b51021a
@gramos gramos - Active Resrource associations, has one should return the associated…
… resource
0453767
@gramos gramos - fix ActiveResource has_one association
  resource_id column is on the associated resource (belogns_to)
- refactoring association test cases
2d24016
@gramos gramos - remove instance variable warnings 97be04d
@gramos gramos - ActiveResource has_one association
  test_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
a973713
@gramos gramos - Active Resource has_one association
  test_should_assign_a_new_project_manager
baa4749
@gramos gramos - tiny refactoring, remove duplication 78e6aec
@gramos gramos - added belongs_to association to ActiveResource 5c8eb17
@gramos gramos - ActiveResource test_belongs_to_accessor_should_return_the_associate…
…d_project
ceeb095
@gramos gramos - Active Resource
  test_belongs_to_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
505318e
@gramos gramos - Active Resource associations refactoring
  * Added method set_resource_instance_variable(resource)
  * added modules InstanceMethods and ClassMethods
  * include instead of extend in ActiveResource::Base
1adb08e
@gramos gramos - added ActiveResource has_many association 1750410
@gramos gramos - fix missing old way to set resource instance variable b952f78
@gramos gramos - ActiveResource added writter to belongs_to association 1bb8bca
@gramos gramos - ActiveResource associations, added some comments 408d2f4
@gramos gramos - ActiveResource association remove :class_name option
  is not implemented yet
36760ea
@gramos gramos - ActiveResource Associations, better name for hash_options d9cfff5
@gramos gramos - ActiveResource, only constantize the resource class
  when is used it.
74bfd33
@gramos gramos - ActiveResource assocition belongs_to dont save the obj. 0d9dd48
@gramos gramos - ActiveResource added
  test_has_many_accessor_should_return_the_an_array_with_the_associated_milestones
11b8d2c
@gramos gramos - ActiveResource
  test_has_many_accessor_should_return_the_an_empty_array_when_it_does_not_has_milestones
cba1f8b
@gramos gramos - Active Resource associations, refactoring remove some duplication 2a78944
@gramos gramos - ActiveResource associaions
  test_has_many_accessor_should_return_the_an_array_including_the_added_obj
7e367a1
@gramos gramos Active Resource has_many association, change eval by instance_eval 8e013a6
@gramos gramos - Active Resource associations, dont need send with eval c878c23
@gramos gramos - ActiveResoruce association added method delete to has_many
  association
b896b8b
@gramos gramos - ActiveResource added clear method to has_many association 3055242
@gramos gramos - Active Resource Fix has_many association, update resource list
  after some methods
b43fdbe
@gramos gramos - ActiveResource association has_many, added method resource= 145cbf3
@gramos gramos - ActiveResource association has_many fix resource=
  should set an array with the added methods
17fc234
@gramos gramos - added ActiveResoruce::Associations::AssociationCollection
  move all related methods to this new class
147513d
@gramos gramos - ActiveResource::Associosiations::AssociationCollection, added missi…
…ng file
60b71ae
@gramos gramos - some changes about coding style 0b9a978
@gramos gramos - ActiveResource::Associations, simple cache added (like AR)
  project.milestones             # fetches milestones
  project.milestones.size        # uses the milestone cache
  project.milestones(true).size  # fetches milestones
1467e28
@gramos gramos - added documentation for ActiveResource::Associations def16ea
@gramos gramos - added cache doc ActiveResource::Associations 55d3daf
@gramos gramos - ActiveResource::Associations, update doc. b19981c
@gramos gramos - ActiveResource::Associations, fix some typo error in doc
- tiny fix in set_resource_instance_variable
8983092
@gramos gramos - ActiveResource::Associations, added doc for has_one c74a7b8
@gramos gramos - ActiveResource::Associations, Fix doc 266ee6c
@gramos gramos - added associations module
- added asociations unit test file
1457b37
@gramos gramos - added first version of ActiveResource has_one associaion method 2dac210
@gramos gramos - Active Resrource associations, has one should return the associated…
… resource
ef39843
@gramos gramos - fix ActiveResource has_one association
  resource_id column is on the associated resource (belogns_to)
- refactoring association test cases
7d6a21d
@gramos gramos - remove instance variable warnings f196b45
@gramos gramos - ActiveResource has_one association
  test_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
dae96a2
@gramos gramos - Active Resource has_one association
  test_should_assign_a_new_project_manager
72258da
@gramos gramos - tiny refactoring, remove duplication bd82c4f
@gramos gramos - added belongs_to association to ActiveResource 60d3a6b
@gramos gramos - ActiveResource test_belongs_to_accessor_should_return_the_associate…
…d_project
1b20cbe
@gramos gramos - Active Resource
  test_belongs_to_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
9295fb0
@gramos gramos - Active Resource associations refactoring
  * Added method set_resource_instance_variable(resource)
  * added modules InstanceMethods and ClassMethods
  * include instead of extend in ActiveResource::Base
db1573d
@gramos gramos - added ActiveResource has_many association 85f67da
@gramos gramos - fix missing old way to set resource instance variable dd5c268
@gramos gramos - ActiveResource added writter to belongs_to association bfabf7f
@gramos gramos - ActiveResource associations, added some comments 2798f73
@gramos gramos - ActiveResource association remove :class_name option
  is not implemented yet
09f8658
@gramos gramos - ActiveResource Associations, better name for hash_options 2f70641
@gramos gramos - ActiveResource, only constantize the resource class
  when is used it.
0f8669e
@gramos gramos - ActiveResource assocition belongs_to dont save the obj. db7b02c
@gramos gramos - ActiveResource added
  test_has_many_accessor_should_return_the_an_array_with_the_associated_milestones
0328ff7
@gramos gramos - ActiveResource
  test_has_many_accessor_should_return_the_an_empty_array_when_it_does_not_has_milestones
532503c
@gramos gramos - Active Resource associations, refactoring remove some duplication 4c339de
@gramos gramos - ActiveResource associaions
  test_has_many_accessor_should_return_the_an_array_including_the_added_obj
38800d7
@gramos gramos Active Resource has_many association, change eval by instance_eval 8c8a2ab
@gramos gramos - Active Resource associations, dont need send with eval 5957c26
@gramos gramos - ActiveResoruce association added method delete to has_many
  association
3762032
@gramos gramos - ActiveResource added clear method to has_many association 3e32d63
@gramos gramos - Active Resource Fix has_many association, update resource list
  after some methods
4f16129
@gramos gramos - ActiveResource association has_many, added method resource= 03f51e1
@gramos gramos - ActiveResource association has_many fix resource=
  should set an array with the added methods
fa49cd8
@gramos gramos - added ActiveResoruce::Associations::AssociationCollection
  move all related methods to this new class
8027093
@gramos gramos - ActiveResource::Associosiations::AssociationCollection, added missi…
…ng file
43d5866
@gramos gramos - some changes about coding style 8a0fe20
@gramos gramos - ActiveResource::Associations, simple cache added (like AR)
  project.milestones             # fetches milestones
  project.milestones.size        # uses the milestone cache
  project.milestones(true).size  # fetches milestones
fc4e765
@gramos gramos - added documentation for ActiveResource::Associations be8cbf6
@gramos gramos - added cache doc ActiveResource::Associations 249c4ed
@gramos gramos - ActiveResource::Associations, update doc. 1ed964a
@gramos gramos - ActiveResource::Associations, fix some typo error in doc
- tiny fix in set_resource_instance_variable
9f634ec
@gramos gramos - ActiveResource::Associations, added doc for has_one 9ee1e16
@gramos gramos - ActiveResource::Associations, Fix doc 9d8b876
@gramos gramos Merge branch 'ares-associations' of github.com:gramos/rails into ares…
…-associations
eb5e3c3
@hosiawak

+1

@gramos

This pull request is wrong I did a mistake with the git rebase, I did a new fresh pull request:
http://github.com/rails/rails/pull/70

@claudiob claudiob referenced this pull request from a commit in claudiob/rails
@robin850 robin850 Follow up of #68
Try to be consistent across the different stylesheets and fix the CSS
for the rails theme.
a1d7e21
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 27, 2010
  1. @gramos

    - added associations module

    gramos authored
    - added asociations unit test file
  2. @gramos
  3. @gramos
  4. @gramos

    - fix ActiveResource has_one association

    gramos authored
      resource_id column is on the associated resource (belogns_to)
    - refactoring association test cases
Commits on Sep 28, 2010
  1. @gramos
  2. @gramos

    - ActiveResource has_one association

    gramos authored
      test_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
  3. @gramos

    - Active Resource has_one association

    gramos authored
      test_should_assign_a_new_project_manager
  4. @gramos
Commits on Sep 29, 2010
  1. @gramos
  2. @gramos
  3. @gramos

    - Active Resource

    gramos authored
      test_belongs_to_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
  4. @gramos

    - Active Resource associations refactoring

    gramos authored
      * Added method set_resource_instance_variable(resource)
      * added modules InstanceMethods and ClassMethods
      * include instead of extend in ActiveResource::Base
  5. @gramos
  6. @gramos
  7. @gramos
  8. @gramos
  9. @gramos

    - ActiveResource association remove :class_name option

    gramos authored
      is not implemented yet
  10. @gramos
  11. @gramos

    - ActiveResource, only constantize the resource class

    gramos authored
      when is used it.
  12. @gramos
  13. @gramos

    - ActiveResource added

    gramos authored
      test_has_many_accessor_should_return_the_an_array_with_the_associated_milestones
  14. @gramos

    - ActiveResource

    gramos authored
      test_has_many_accessor_should_return_the_an_empty_array_when_it_does_not_has_milestones
  15. @gramos
Commits on Oct 1, 2010
  1. @gramos

    - ActiveResource associaions

    gramos authored
      test_has_many_accessor_should_return_the_an_array_including_the_added_obj
  2. @gramos
  3. @gramos
  4. @gramos
  5. @gramos
  6. @gramos
  7. @gramos
Commits on Oct 2, 2010
  1. @gramos

    - ActiveResource association has_many fix resource=

    gramos authored
      should set an array with the added methods
Commits on Oct 4, 2010
  1. @gramos

    - added ActiveResoruce::Associations::AssociationCollection

    gramos authored
      move all related methods to this new class
  2. @gramos
  3. @gramos
  4. @gramos

    - ActiveResource::Associations, simple cache added (like AR)

    gramos authored
      project.milestones             # fetches milestones
      project.milestones.size        # uses the milestone cache
      project.milestones(true).size  # fetches milestones
Commits on Oct 5, 2010
  1. @gramos
  2. @gramos
  3. @gramos
  4. @gramos

    - ActiveResource::Associations, fix some typo error in doc

    gramos authored
    - tiny fix in set_resource_instance_variable
  5. @gramos
  6. @gramos
  7. @gramos

    - added associations module

    gramos authored
    - added asociations unit test file
  8. @gramos
  9. @gramos
  10. @gramos

    - fix ActiveResource has_one association

    gramos authored
      resource_id column is on the associated resource (belogns_to)
    - refactoring association test cases
  11. @gramos
  12. @gramos

    - ActiveResource has_one association

    gramos authored
      test_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
  13. @gramos

    - Active Resource has_one association

    gramos authored
      test_should_assign_a_new_project_manager
  14. @gramos
  15. @gramos
  16. @gramos
  17. @gramos

    - Active Resource

    gramos authored
      test_belongs_to_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
  18. @gramos

    - Active Resource associations refactoring

    gramos authored
      * Added method set_resource_instance_variable(resource)
      * added modules InstanceMethods and ClassMethods
      * include instead of extend in ActiveResource::Base
  19. @gramos
  20. @gramos
  21. @gramos
  22. @gramos
  23. @gramos

    - ActiveResource association remove :class_name option

    gramos authored
      is not implemented yet
  24. @gramos
  25. @gramos

    - ActiveResource, only constantize the resource class

    gramos authored
      when is used it.
  26. @gramos
  27. @gramos

    - ActiveResource added

    gramos authored
      test_has_many_accessor_should_return_the_an_array_with_the_associated_milestones
  28. @gramos

    - ActiveResource

    gramos authored
      test_has_many_accessor_should_return_the_an_empty_array_when_it_does_not_has_milestones
  29. @gramos
  30. @gramos

    - ActiveResource associaions

    gramos authored
      test_has_many_accessor_should_return_the_an_array_including_the_added_obj
  31. @gramos
  32. @gramos
  33. @gramos
  34. @gramos
  35. @gramos
  36. @gramos
  37. @gramos

    - ActiveResource association has_many fix resource=

    gramos authored
      should set an array with the added methods
  38. @gramos

    - added ActiveResoruce::Associations::AssociationCollection

    gramos authored
      move all related methods to this new class
  39. @gramos
  40. @gramos
  41. @gramos

    - ActiveResource::Associations, simple cache added (like AR)

    gramos authored
      project.milestones             # fetches milestones
      project.milestones.size        # uses the milestone cache
      project.milestones(true).size  # fetches milestones
  42. @gramos
  43. @gramos
  44. @gramos
  45. @gramos

    - ActiveResource::Associations, fix some typo error in doc

    gramos authored
    - tiny fix in set_resource_instance_variable
  46. @gramos
  47. @gramos
  48. @gramos
This page is out of date. Refresh to see the latest.
View
233 activeresource/lib/active_resource/associations.rb
@@ -0,0 +1,233 @@
+require 'active_resource/associations/association_collection'
+
+module ActiveResource
+ module Associations
+
+ # Active Resource Associations works in the same way than Active Record
+ # associations, it follows the same coventions and method names.
+ # At the moment it support only one-to-one and one-to-many associations,
+ # many-to-many associations are not implemented yet.
+ #
+ # An example of use:
+ #
+ # class Project < ActiveRecord::Base
+ # self.site = "http://37s.sunrise.i:3000"
+ #
+ # belongs_to :portfolio
+ # has_one :project_manager
+ # has_many :milestones
+ # end
+ #
+ # The project class now has the following methods in order to manipulate the relationships:
+ # * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt>
+ # * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
+ # * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone), Project#milestone.delete(milestone)</tt>
+ #
+ #
+ # == Auto-generated methods
+ #
+ # === Singular associations (one-to-one)
+ # | | belongs_to |
+ # generated methods | belongs_to | :polymorphic | has_one
+ # ----------------------------------+------------+--------------+---------
+ # other | X | X | X
+ # other=(other) | X | X | X
+ #
+ # ===Collection associations (one-to-many)
+ #
+ # generated methods (only one-to-many)
+ # --------------------------
+ # others
+ # others=[other,other]
+ # others<<
+ # others.size
+ # others.length
+ # others.empty?
+ # others.clear
+ # others.delete(other)
+ #
+ # === One-to-one
+ #
+ # Use has_one in the base, and belongs_to in the associated model.
+ #
+ # class ProjectManager < ActiveResource::Base
+ # self.site = "http://37s.sunrise.i:3000"
+ # belongs_to :project
+ # end
+ #
+ # class Project < ActiveResource::Base
+ # self.site = "http://37s.sunrise.i:3000"
+ # has_one :project_manager
+ # end
+ #
+ # @project = Project.find(1)
+ # @project.project_manager = ProjectManager.find(3)
+ # @project.project_manager #=> #<ProjectManager:0x7fb91bb05708 @persisted=true,
+ # @attributes={"name"=>"David", "project_id"=>1, "id"=>5}, @prefix_options={}>
+ #
+ #
+ # === One-to-many
+ #
+ # Use has_many in the base, and belongs_to in the associated model.
+ #
+ # class Project < ActiveResource::Base
+ # self.site = "http://37s.sunrise.i:3000"
+ # has_many :milestones
+ # end
+ #
+ # class Milestone < ActiveResource::Base
+ # self.site = "http://37s.sunrise.i:3000"
+ # end
+ #
+ # @milestone = Milestone.find(2)
+ # @project = Project.find(1)
+ # @project.milestones << @milestone
+ #
+ # This will set the @milestone.milestone_id to @project.id
+ # and save @milestone, then when you call @project.milestones
+ # will return an AssociationCollection list with the recently milestone added
+ # included.
+ #
+ # @project.milestones #=>[#<Milestone:0x7f8b3134ac88 @persisted=true,
+ # @attributes={"title"=>"pre", "project_id"=>nil, "id"=>1},
+ # @prefix_options={}>, #<Milestone:0x7f8b31324768 @errors=#<OrderedHash {}>,
+ # @validation_context=nil, @persisted=true, @attributes={"title"=>"rc other",
+ # "project_id"=>nil, "id"=>2}, @remote_errors=nil, @prefix_options={}>]
+ #
+ #
+ # === Collections
+ #
+ # * Adding an object to a collection (+has_many+) automatically saves that resource.
+ #
+ # === Cache
+ #
+ # * Every association set an instance variable over the base resource and works
+ # with a simple cache that keep the result of the last fetched resource
+ # unless you specifically instructed not to.
+ #
+ # project.milestones # fetches milestones resources
+ # project.milestones.size # uses the milestone cache
+ # project.milestones.empty? # uses the milestone cache
+ # project.milestones(true).size # fetches milestones from the database
+ # project.milestones # uses the milestone cache
+ #
+ def self.included(klass)
+ klass.send :include, InstanceMethods
+ klass.extend ClassMethods
+ end
+
+ module InstanceMethods
+ def set_resource_instance_variable(resource, force_reload = false)
+ if !instance_variable_defined?("@#{resource}") or force_reload
+ instance_variable_set("@#{resource}", yield)
+ end
+ instance_variable_get("@#{resource}")
+ end
+ end
+
+ module ClassMethods
+
+ def options(association, resource)
+ o = { :klass => klass_for(association, resource) }
+ o[:host_klass] = self
+
+ case association
+ when :has_many
+ o[:association_col] = o[:host_klass].to_s.singularize
+ when :belongs_to
+ o[:association_col] = o[:klass]
+ when :has_one
+ o[:association_col] = o[:host_klass].to_s
+ end
+ o[:association_col] = "#{o[:association_col].underscore}_id".to_sym
+ o
+ end
+
+ def klass_for(association, resource)
+ resource = resource.to_s
+ resource = resource.singularize if association == :has_many
+ resource.camelize
+ end
+
+ def has_one(resource, opts = {})
+ o = options(:has_one, resource)
+
+ # Define accessor method for resource
+ #
+ define_method(resource) do |*force_reload|
+ force_reload = force_reload.first || false
+
+ set_resource_instance_variable(resource, force_reload) do
+ o[:klass].constantize.find(:first, :params => { o[:association_col] => id })
+ end
+ end
+
+ # Define writter method for resource
+ #
+ define_method("#{resource}=") do |new_resource|
+ if send(resource).blank?
+ new_resource.send("#{o[:association_col]}=", id)
+ instance_variable_set("@#{resource}", new_resource.save)
+ else
+ instance_variable_get("@#{resource}").send(:update_attribute, o[:association_col], id)
+ end
+ end
+ end
+
+ def belongs_to(resource, opts = {})
+ o = options(:belongs_to, resource)
+
+ # Define accessor method for resource
+ #
+ define_method(resource) do |*force_reload|
+ force_reload = force_reload.first || false
+
+ association_col = send o[:association_col]
+ return nil if association_col.nil?
+ set_resource_instance_variable(resource, force_reload){
+ o[:klass].constantize.find(association_col)
+ }
+ end
+
+ # Define writter method for resource
+ #
+ define_method("#{resource}=") do |new_resource|
+ if send(o[:association_col]) != new_resource.id
+ send "#{o[:association_col]}=", new_resource.id
+ end
+ instance_variable_set("@#{resource}", new_resource)
+ end
+ end
+
+ def has_many(resource, opts = {})
+ o = options(:has_many, resource)
+
+ # Define accessor method for resource
+ #
+ define_method(resource) do |*force_reload|
+ force_reload = force_reload.first || false
+
+ set_resource_instance_variable(resource, force_reload) {
+ result = o[:klass].constantize.find(:all,
+ :params => { o[:association_col] => id }) || []
+
+ AssociationCollection.new result, self, o[:association_col]
+ }
+ end
+
+ define_method("#{resource}=") do |new_collection|
+ collection = send(resource)
+ to_remove = collection - new_collection
+ to_remove.each{|m| collection.delete(m)}
+
+ # FIXME should call the old clear
+ collection.clear
+ # FIXME Is this needed?
+ collection.concat new_collection
+ end
+ end
+
+ end
+ end
+
+end
View
31 activeresource/lib/active_resource/associations/association_collection.rb
@@ -0,0 +1,31 @@
+module ActiveResource
+ module Associations
+
+ class AssociationCollection < Array
+
+ def initialize(array, host_resource, association_col)
+ @host_resource = host_resource
+ @association_col = association_col
+ self.concat array
+ end
+
+ def <<(member)
+ member.send "#{@association_col}=", @host_resource.id
+ member.save
+ super(member)
+ end
+
+ def delete(member)
+ member.send "#{@association_col}=", nil
+ member.save
+ super(member)
+ end
+
+ def clear
+ self.each{|member| delete(member)}
+ super
+ end
+
+ end
+ end
+end
View
3  activeresource/lib/active_resource/base.rb
@@ -18,6 +18,7 @@
require 'active_resource/formats'
require 'active_resource/schema'
require 'active_resource/log_subscriber'
+require 'active_resource/associations'
module ActiveResource
# ActiveResource::Base is the main class for mapping RESTful resources as models in a Rails application.
@@ -262,7 +263,7 @@ class Base
# :singleton-method:
# The logger for diagnosing and tracing Active Resource calls.
cattr_accessor :logger
-
+ include Associations
class << self
# Creates a schema for this resource - setting the attributes that are
# known prior to fetching an instance from the remote system.
View
144 activeresource/test/cases/associations_test.rb
@@ -0,0 +1,144 @@
+require 'abstract_unit'
+require "fixtures/project"
+
+class ProjectManager < ActiveResource::Base
+ self.site = "http://37s.sunrise.i:3000"
+ belongs_to :project
+end
+
+class Project < ActiveResource::Base
+ self.site = "http://37s.sunrise.i:3000"
+ has_one :project_manager
+ has_many :milestones
+end
+
+class Milestone < ActiveResource::Base
+ self.site = "http://37s.sunrise.i:3000"
+end
+
+@project = { :id => 1, :name => "Rails"}
+@other_project = { :id => 2, :name => "Ruby"}
+@project_manager = {:id => 5, :name => "David", :project_id =>1}
+@other_project_manager = {:id => 6, :name => "John", :project_id => nil}
+@project_managers = [@project_manager]
+@milestone = { :id => 1, :title => "pre", :project_id => nil}
+@other_milestone = { :id => 2, :title => "rc other", :project_id => nil}
+
+ActiveResource::HttpMock.respond_to do |mock|
+ mock.get "/projects/.xml", {}, @project.to_xml(:root => 'project')
+ mock.get "/projects/1.xml", {}, @project.to_xml(:root => 'project')
+ mock.get "/projects/2.xml", {}, @other_project.to_xml(:root => 'project')
+ mock.get "/project_managers/5.xml", {}, @project_manager.to_xml(:root => 'project_manager')
+ mock.get "/project_managers/6.xml", {}, @other_project_manager.to_xml(:root => 'project_manager')
+ mock.get "/project_managers.xml?project_id=1", {}, @project_managers.to_xml
+ mock.get "/project_managers.xml?project_id=2", {}, [].to_xml
+ mock.get "/milestones.xml", {}, [@milestone].to_xml
+ mock.get "/milestones.xml?project_id=2", {}, [].to_xml
+ mock.get "/milestones.xml?project_id=1", {}, [@milestone].to_xml
+ mock.put "/project_managers/6.xml", {}, nil, 204
+ mock.put "/milestones/2.xml", {}, nil, 204
+ mock.put "/milestones/1.xml", {}, nil, 204
+ mock.get "/milestones/1.xml", {}, @milestone.to_xml(:root => 'milestone')
+ mock.get "/milestones/2.xml", {}, @other_milestone.to_xml(:root => 'milestone')
+end
+
+class AssociationsTest < Test::Unit::TestCase
+
+ def setup
+ @project = Project.find(1)
+ @other_project = Project.find(2)
+ @project_manager = ProjectManager.find(5)
+ @other_project_manager = ProjectManager.find(6)
+ @milestone = Milestone.find(1)
+ @other_milestone = Milestone.find(2)
+ end
+
+ #----------------------------------------------------------------------
+ # has_one association
+ #----------------------------------------------------------------------
+
+ def test_has_one_should_add_a_resource_accessor
+ assert @project.respond_to? :project_manager
+ end
+
+ def test_has_one_accessor_should_return_the_associated_project_manager
+ assert_equal @project_manager, @project.project_manager
+ end
+
+ def test_has_one_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
+ assert_nil @other_project.project_manager
+ end
+
+ def test_has_one_should_assign_a_new_project_manager_when_it_does_not_has_a_project_manager
+ @other_project.project_manager = @other_project_manager
+ assert_equal @other_project.id, @other_project_manager.project_id
+ end
+
+ #----------------------------------------------------------------------
+ # belogns_to association
+ #----------------------------------------------------------------------
+
+ def test_belongs_to_should_add_a_resource_accessor
+ assert @project_manager.respond_to? :project
+ end
+
+ def test_belongs_to_accessor_should_return_the_associated_project
+ assert_equal @project, @project_manager.project
+ end
+
+ def test_belongs_to_accessor_should_return_nil_when_the_does_not_has_an_associated_resource
+ assert_nil @other_project_manager.project
+ end
+
+ def test_has_one_should_assign_a_new_project_manager_when_it_does_not_has_a_project_manager
+ @other_project_manager.project = @other_project
+ assert_equal @other_project_manager.project_id, @other_project.id
+ end
+
+ #----------------------------------------------------------------------
+ # has_many association
+ #----------------------------------------------------------------------
+
+ def test_has_many_should_add_a_resource_accessor
+ assert @project.respond_to? :milestones
+ end
+
+ def test_has_many_accessor_should_return_the_an_array_with_the_associated_milestones
+ assert_equal [@milestone], @project.milestones
+ end
+
+ def test_has_many_accessor_should_return_the_an_empty_array_when_it_does_not_has_milestones
+ assert_equal [], @other_project.milestones
+ end
+
+ def test_has_many_accessor_should_return_the_an_array_including_the_added_obj
+ @project.milestones << @other_milestone
+ assert_equal @other_milestone.project_id, @project.id
+ end
+
+ def test_has_many_accessor_should_return_the_an_array_without_including_the_deleted_obj
+ @project.milestones << @other_milestone
+ @project.milestones.delete(@other_milestone)
+ assert_nil @other_milestone.project_id
+ end
+
+ def test_has_many_accessor_should_return_the_an_empty_array_after_clear
+ @project.milestones << @other_milestone
+ @project.milestones.clear
+
+ assert_equal [], @project.milestones
+ end
+
+ def test_has_many_accessor_should_return_the_new_array_after_assign
+ @project.milestones = [@other_milestone]
+ assert_equal [@other_milestone], @project.milestones
+
+ @project.milestones = []
+ assert_equal [], @project.milestones
+
+ @project.milestones = [@milestone, @other_milestone]
+ assert_equal [@milestone, @other_milestone], @project.milestones
+ end
+
+end
+
View
4 activeresource/test/fixtures/project.rb
@@ -2,6 +2,9 @@
class Project < ActiveResource::Base
self.site = "http://37s.sunrise.i:3000"
+ #----------------------------------------------------------------------
+ # validations
+ #
validates_presence_of :name
validate :description_greater_than_three_letters
@@ -18,6 +21,7 @@ def description_greater_than_three_letters
def name
attributes['name'] || nil
end
+
def description
attributes['description'] || nil
end
Something went wrong with that request. Please try again.