morpheus 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. data/.rspec +1 -1
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile +1 -1
  4. data/lib/morpheus.rb +3 -23
  5. data/lib/morpheus/base.rb +11 -11
  6. data/lib/morpheus/client.rb +10 -0
  7. data/lib/morpheus/client/associations.rb +6 -6
  8. data/lib/morpheus/client/cached_request_formatter.rb +20 -0
  9. data/lib/morpheus/client/log_subscriber.rb +2 -28
  10. data/lib/morpheus/client/railtie.rb +4 -4
  11. data/lib/morpheus/client/request_formatter.rb +50 -0
  12. data/lib/morpheus/client/uncached_request_formatter.rb +40 -0
  13. data/lib/morpheus/configuration.rb +30 -9
  14. data/lib/morpheus/mixins.rb +16 -0
  15. data/lib/morpheus/mixins/associations.rb +39 -37
  16. data/lib/morpheus/mixins/associations/association.rb +112 -0
  17. data/lib/morpheus/mixins/associations/belongs_to_association.rb +47 -0
  18. data/lib/morpheus/mixins/associations/has_many_association.rb +72 -0
  19. data/lib/morpheus/mixins/associations/has_one_association.rb +48 -0
  20. data/lib/morpheus/mixins/attributes.rb +97 -95
  21. data/lib/morpheus/mixins/conversion.rb +16 -14
  22. data/lib/morpheus/mixins/filtering.rb +13 -11
  23. data/lib/morpheus/mixins/finders.rb +47 -45
  24. data/lib/morpheus/mixins/introspection.rb +15 -13
  25. data/lib/morpheus/mixins/persistence.rb +32 -30
  26. data/lib/morpheus/mixins/reflections.rb +17 -15
  27. data/lib/morpheus/mixins/request_handling.rb +27 -25
  28. data/lib/morpheus/mixins/response_parsing.rb +10 -8
  29. data/lib/morpheus/mixins/url_support.rb +27 -25
  30. data/lib/morpheus/reflection.rb +5 -2
  31. data/lib/morpheus/type_caster.rb +1 -1
  32. data/lib/morpheus/version.rb +1 -1
  33. data/morpheus.gemspec +2 -2
  34. data/spec/dummy/app/resources/book.rb +1 -1
  35. data/spec/morpheus/base_spec.rb +35 -35
  36. data/spec/morpheus/client/cached_request_formatter_spec.rb +28 -0
  37. data/spec/morpheus/client/log_subscriber_spec.rb +53 -10
  38. data/spec/morpheus/client/request_formatter_spec.rb +5 -0
  39. data/spec/morpheus/client/uncached_request_formatter_spec.rb +29 -0
  40. data/spec/morpheus/configuration_spec.rb +49 -11
  41. data/spec/morpheus/{associations → mixins/associations}/association_spec.rb +1 -1
  42. data/spec/morpheus/{associations → mixins/associations}/belongs_to_association_spec.rb +1 -1
  43. data/spec/morpheus/{associations → mixins/associations}/has_many_association_spec.rb +1 -1
  44. data/spec/morpheus/{associations → mixins/associations}/has_one_association_spec.rb +1 -1
  45. data/spec/morpheus/mixins/associations_spec.rb +1 -1
  46. data/spec/morpheus/mixins/attributes_spec.rb +27 -6
  47. data/spec/morpheus/mixins/conversion_spec.rb +1 -1
  48. data/spec/morpheus/mixins/filtering_spec.rb +2 -2
  49. data/spec/morpheus/mixins/finders_spec.rb +1 -1
  50. data/spec/morpheus/mixins/introspection_spec.rb +1 -1
  51. data/spec/morpheus/mixins/persistence_spec.rb +1 -1
  52. data/spec/morpheus/mixins/reflections_spec.rb +1 -1
  53. data/spec/morpheus/mixins/request_handling_spec.rb +2 -2
  54. data/spec/morpheus/mixins/response_parsing_spec.rb +2 -2
  55. data/spec/morpheus/mixins/url_support_spec.rb +2 -2
  56. data/spec/morpheus/response_parser_spec.rb +5 -1
  57. data/spec/regressions/sorting_resources_spec.rb +119 -0
  58. data/spec/spec_helper.rb +3 -2
  59. metadata +159 -87
  60. data/lib/morpheus/associations/association.rb +0 -110
  61. data/lib/morpheus/associations/belongs_to_association.rb +0 -45
  62. data/lib/morpheus/associations/has_many_association.rb +0 -70
  63. data/lib/morpheus/associations/has_one_association.rb +0 -46
data/.rspec CHANGED
@@ -1 +1 @@
1
- --color
1
+ --order rand
@@ -0,0 +1,17 @@
1
+ # 0.5.0
2
+ * Upgrading typhoeus to ~> 0.4.2
3
+ * Morpheus::Client::LogSubscriber has been refactored out into separate formatter classes.
4
+
5
+ # 0.4.0
6
+ * Updated yajl-ruby to ~> 1.1.0 [3f30762](https://github.com/ryanmoran/morpheus/commit/3f30762528f4fc6b1f35775ce81e5ba1c03bc3c7).
7
+ * Updated typhoeus to ~> 0.3.3 [cf474b6](https://github.com/ryanmoran/morpheus/commit/cf474b651a77a8359ebb25600ab2be8a57a06df2).
8
+ * Added Yajl::ParseError exception handling support [3234984](https://github.com/ryanmoran/morpheus/commit/32349841d155188fe37906351f5091e756deca76).
9
+ * Continuing to add spec coverage.
10
+
11
+ # 0.3.9
12
+ * Fixed ResponseCache hashing issue where duplicate cache_key values were being created for different responses [5b507a7](https://github.com/ryanmoran/morpheus/commit/5b507a78e53120239ad38df0018b7324bd5969e9).
13
+ * Continuing to add spec coverage.
14
+
15
+ # 0.3.8
16
+ * Fixed dependency version issues with activemodel, activesupport, and i18n [36575ef](https://github.com/ryanmoran/morpheus/commit/36575efe6ca42edf1e7b461658c55048823730f7).
17
+ * Continuing to add spec coverage.
data/Gemfile CHANGED
@@ -3,6 +3,6 @@ source 'http://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem 'simplecov', '~> 0.6.1'
6
+ gem 'simplecov', '~> 0.6.4'
7
7
  gem 'autotest-standalone', '~> 4.5.9'
8
8
  end
@@ -13,11 +13,11 @@ require 'active_model'
13
13
  # The bulk of the library consists of the Base class and its mix-in modules, the request/response wrappers,
14
14
  # mocking, configuration, errors, and classes managing associations, reflections, relations, and typecasting.
15
15
  module Morpheus
16
- autoload :Version, 'morpheus/version'
17
-
18
16
  autoload :Base, 'morpheus/base'
17
+ autoload :Client, 'morpheus/client'
19
18
  autoload :Configuration, 'morpheus/configuration'
20
19
  autoload :Filter, 'morpheus/filter'
20
+ autoload :Mixins, 'morpheus/mixins'
21
21
  autoload :Mock, 'morpheus/mock'
22
22
  autoload :Reflection, 'morpheus/reflection'
23
23
  autoload :Relation, 'morpheus/relation'
@@ -28,19 +28,7 @@ module Morpheus
28
28
  autoload :ResponseParser, 'morpheus/response_parser'
29
29
  autoload :TypeCaster, 'morpheus/type_caster'
30
30
  autoload :UrlBuilder, 'morpheus/url_builder'
31
-
32
- # Mixins provide behaviors to the Base class.
33
- autoload :Associations, 'morpheus/mixins/associations'
34
- autoload :Attributes, 'morpheus/mixins/attributes'
35
- autoload :Conversion, 'morpheus/mixins/conversion'
36
- autoload :Filtering, 'morpheus/mixins/filtering'
37
- autoload :Finders, 'morpheus/mixins/finders'
38
- autoload :Introspection, 'morpheus/mixins/introspection'
39
- autoload :Persistence, 'morpheus/mixins/persistence'
40
- autoload :Reflections, 'morpheus/mixins/reflections'
41
- autoload :RequestHandling, 'morpheus/mixins/request_handling'
42
- autoload :ResponseParsing, 'morpheus/mixins/response_parsing'
43
- autoload :UrlSupport, 'morpheus/mixins/url_support'
31
+ autoload :Version, 'morpheus/version'
44
32
 
45
33
  # Error classes
46
34
  autoload :ConfigurationError, 'morpheus/errors'
@@ -52,14 +40,6 @@ module Morpheus
52
40
  autoload :InvalidResponseCode, 'morpheus/errors'
53
41
  end
54
42
 
55
- # Associations for application objects, typically ActiveRecord, to resource
56
- module Morpheus
57
- module Client
58
- autoload :Associations, 'morpheus/client/associations'
59
- autoload :LogSubscriber, 'morpheus/client/log_subscriber'
60
- end
61
- end
62
-
63
43
  # The Railtie loads the LogSubscriber for printing output to the Rails log, and
64
44
  # Associations which plug-in to ActiveRecord to link associated resources.
65
45
  require 'morpheus/client/railtie' if defined?(Rails)
@@ -17,17 +17,17 @@ module Morpheus
17
17
  # In many cases they rely upon other classes in the library to complete
18
18
  # their functionality. The helper classes can be used stand-alone, but
19
19
  # are most effective when used as collaborators to the mix-in behaviors.
20
- include Associations
21
- include Attributes
22
- include Conversion
23
- include Filtering
24
- include Finders
25
- include Introspection
26
- include Persistence
27
- include Reflections
28
- include RequestHandling
29
- include ResponseParsing
30
- include UrlSupport
20
+ include Mixins::Associations
21
+ include Mixins::Attributes
22
+ include Mixins::Conversion
23
+ include Mixins::Filtering
24
+ include Mixins::Finders
25
+ include Mixins::Introspection
26
+ include Mixins::Persistence
27
+ include Mixins::Reflections
28
+ include Mixins::RequestHandling
29
+ include Mixins::ResponseParsing
30
+ include Mixins::UrlSupport
31
31
 
32
32
  # Defines a default 'id' property on all instances of Morpheus::Base and subclasses
33
33
  property :id, :integer
@@ -0,0 +1,10 @@
1
+ # Associations for application objects, typically ActiveRecord, to resource
2
+ module Morpheus
3
+ module Client
4
+ autoload :Associations, 'morpheus/client/associations'
5
+ autoload :CachedRequestFormatter, 'morpheus/client/cached_request_formatter'
6
+ autoload :LogSubscriber, 'morpheus/client/log_subscriber'
7
+ autoload :RequestFormatter, 'morpheus/client/request_formatter'
8
+ autoload :UncachedRequestFormatter, 'morpheus/client/uncached_request_formatter'
9
+ end
10
+ end
@@ -11,11 +11,11 @@ module Morpheus
11
11
  def belongs_to_resource(association, options = {})
12
12
  define_method association do
13
13
  instance_variable_get("@#{association}") ||
14
- instance_variable_set("@#{association}", Morpheus::Associations::BelongsToAssociation.new(self, association, :options => options))
14
+ instance_variable_set("@#{association}", Morpheus::Mixins::Associations::BelongsToAssociation.new(self, association, :options => options))
15
15
  end
16
16
 
17
17
  define_method "#{association}=" do |target|
18
- instance_variable_set("@#{association}", Morpheus::Associations::BelongsToAssociation.new(self, association, :target => target, :options => options))
18
+ instance_variable_set("@#{association}", Morpheus::Mixins::Associations::BelongsToAssociation.new(self, association, :target => target, :options => options))
19
19
  send("#{association}_id=", target.id)
20
20
  end
21
21
 
@@ -24,22 +24,22 @@ module Morpheus
24
24
  def has_many_resources(association, options = {})
25
25
  define_method association do
26
26
  instance_variable_get("@#{association}") ||
27
- instance_variable_set("@#{association}", Morpheus::Associations::HasManyAssociation.new(self, association, :options => options))
27
+ instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasManyAssociation.new(self, association, :options => options))
28
28
  end
29
29
 
30
30
  define_method "#{association}=" do |target|
31
- instance_variable_set("@#{association}", Morpheus::Associations::HasManyAssociation.new(self, association, :target => target, :options => options))
31
+ instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasManyAssociation.new(self, association, :target => target, :options => options))
32
32
  end
33
33
  end
34
34
 
35
35
  def has_one_resource(association, options = {})
36
36
  define_method association do
37
37
  instance_variable_get("@#{association}") ||
38
- instance_variable_set("@#{association}", Morpheus::Associations::HasOneAssociation.new(self, association, :options => options))
38
+ instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasOneAssociation.new(self, association, :options => options))
39
39
  end
40
40
 
41
41
  define_method "#{association}=" do |target|
42
- instance_variable_set("@#{association}", Morpheus::Associations::HasOneAssociation.new(self, association, :target => target, :options => options))
42
+ instance_variable_set("@#{association}", Morpheus::Mixins::Associations::HasOneAssociation.new(self, association, :target => target, :options => options))
43
43
  end
44
44
  end
45
45
 
@@ -0,0 +1,20 @@
1
+ module Morpheus
2
+ module Client
3
+ class CachedRequestFormatter < RequestFormatter
4
+
5
+ def call
6
+ "#{request_statement} #{payload}"
7
+ end
8
+
9
+ def request_statement
10
+ statement = "CACHE (#{duration}ms)"
11
+ color(statement, request_color, true)
12
+ end
13
+
14
+ def duration
15
+ event.duration
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -12,37 +12,11 @@ module Morpheus
12
12
  end
13
13
 
14
14
  def uncached_request(event)
15
- duration = event.payload[:response].time * 1000
16
- request_statement = "#{event.payload[:class].to_s} #{event.payload[:method].to_s.upcase} (#{duration}ms)"
17
- if odd?
18
- request_statement = color(request_statement, MAGENTA, true)
19
- payload = color(payload(event), nil, true)
20
- else
21
- request_statement = color(request_statement, CYAN, true)
22
- payload = payload(event)
23
- end
24
-
25
- response_color = case event.payload[:response].code
26
- when 200..299 then GREEN
27
- when 400..599 then RED
28
- else YELLOW
29
- end
30
- response_statement = color("[#{event.payload[:response].code}]", response_color, true)
31
-
32
- "#{request_statement} #{response_statement} #{payload}"
15
+ UncachedRequestFormatter.call(self, event, odd?)
33
16
  end
34
17
 
35
18
  def cached_request(event)
36
- duration = event.duration
37
- request_statement = "CACHE (#{duration}ms)"
38
- if odd?
39
- request_statement = color(request_statement, MAGENTA, true)
40
- payload = color(payload(event), nil, true)
41
- else
42
- request_statement = color(request_statement, CYAN, true)
43
- payload = payload(event)
44
- end
45
- "#{request_statement} #{payload}"
19
+ CachedRequestFormatter.call(self, event, odd?)
46
20
  end
47
21
 
48
22
  def payload(event)
@@ -4,19 +4,19 @@ module Morpheus
4
4
 
5
5
  if defined?(ActiveRecord)
6
6
  ActiveRecord::Base.send(:include, Morpheus::Client::Associations)
7
- ActiveRecord::Base.send(:include, Morpheus::UrlSupport)
7
+ ActiveRecord::Base.send(:include, Morpheus::Mixins::UrlSupport)
8
8
  end
9
9
 
10
- initializer "morpheus.client.configure_request_cache" do |app|
10
+ initializer 'morpheus.client.configure_request_cache' do |app|
11
11
  app.middleware.use Morpheus::RequestQueue
12
12
  app.middleware.use Morpheus::RequestCache
13
13
  end
14
14
 
15
- initializer "morpheus.configure_logger", :after => :initialize_logger do |app|
15
+ initializer 'morpheus.configure_logger', :after => :initialize_logger do |app|
16
16
  Morpheus::Configuration.logger = Rails.logger
17
17
  end
18
18
 
19
- initializer "morpheus.client.log_subscriber", :after => "morpheus.configure_logger" do
19
+ initializer 'morpheus.client.log_subscriber', :after => 'morpheus.configure_logger' do
20
20
  Morpheus::Client::LogSubscriber.attach_to :morpheus
21
21
  end
22
22
 
@@ -0,0 +1,50 @@
1
+ module Morpheus
2
+ module Client
3
+ class RequestFormatter
4
+ MAGENTA = ActiveSupport::LogSubscriber::MAGENTA
5
+ CYAN = ActiveSupport::LogSubscriber::CYAN
6
+ GREEN = ActiveSupport::LogSubscriber::GREEN
7
+ RED = ActiveSupport::LogSubscriber::RED
8
+ YELLOW = ActiveSupport::LogSubscriber::YELLOW
9
+
10
+ attr_reader :subscriber, :event
11
+
12
+ def self.call(subscriber, event, odd)
13
+ new(subscriber, event, odd).call
14
+ end
15
+
16
+ def initialize(subscriber, event, odd)
17
+ @subscriber = subscriber
18
+ @event = event
19
+ @odd = odd
20
+ end
21
+
22
+ def odd?
23
+ @odd
24
+ end
25
+
26
+ def payload
27
+ if odd?
28
+ color(formatted_payload, nil, true)
29
+ else
30
+ formatted_payload
31
+ end
32
+ end
33
+
34
+ def color(*args)
35
+ subscriber.send(:color, *args)
36
+ end
37
+
38
+ def formatted_payload
39
+ payload = "#{event.payload[:url]}"
40
+ payload << " #{event.payload[:params].inspect}" unless event.payload[:params].blank?
41
+ payload
42
+ end
43
+
44
+ def request_color
45
+ odd? ? MAGENTA : CYAN
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,40 @@
1
+ module Morpheus
2
+ module Client
3
+ class UncachedRequestFormatter < RequestFormatter
4
+
5
+ def call
6
+ "#{request_statement} #{response_statement} #{payload}"
7
+ end
8
+
9
+ def request_statement
10
+ klass = event.payload[:class]
11
+ method = event.payload[:method].to_s.upcase
12
+ statement = "#{klass} #{method} (#{duration})"
13
+ color(statement, request_color, true)
14
+ end
15
+
16
+ def response_statement
17
+ statement = "[#{response.code}]"
18
+ color(statement, response_color, true)
19
+ end
20
+
21
+ def response
22
+ event.payload[:response]
23
+ end
24
+
25
+ def duration
26
+ value = response.time * 1000
27
+ "#{value}ms"
28
+ end
29
+
30
+ def response_color
31
+ case response.code
32
+ when 200..299 then GREEN
33
+ when 400..599 then RED
34
+ else YELLOW
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -2,33 +2,54 @@ module Morpheus
2
2
  module Configuration
3
3
  extend self
4
4
 
5
- attr_accessor :username, :password
5
+ def attributes
6
+ @attributes ||= {}
7
+ end
8
+
9
+ def username=(username)
10
+ attributes[:username] = username
11
+ end
12
+
13
+ def username
14
+ attributes[:username]
15
+ end
16
+
17
+ def password=(password)
18
+ attributes[:password] = password
19
+ end
20
+
21
+ def password
22
+ attributes[:password]
23
+ end
6
24
 
7
25
  # Sets and gets the remote host service domain.
8
26
  # The domain must be set before any requests can be made.
9
- attr_writer :host
27
+ def host=(host)
28
+ attributes[:host] = host
29
+ end
30
+
10
31
  def host
11
- @host || raise(Morpheus::ConfigurationError,
32
+ attributes[:host] || raise(Morpheus::ConfigurationError,
12
33
  'The request HOST has not been set. Please set the host using Morpheus::Configuration.host = "http://www.example.com"')
13
34
  end
14
35
 
15
36
  # Links to the underlying libcurl request pool.
16
37
  # Allows for concurrent requests.
17
38
  def hydra
18
- Typhoeus::Hydra.hydra
39
+ attributes[:hydra] ||= Typhoeus::Hydra.hydra
19
40
  end
20
41
 
21
42
  def hydra=(hydra)
22
- Typhoeus::Hydra.hydra = hydra
43
+ attributes[:hydra] = Typhoeus::Hydra.hydra = hydra
23
44
  end
24
45
 
25
46
  # Handles the default logger that is used by the LogSubscriber
26
47
  def logger
27
- @logger ||= ::Logger.new(STDOUT)
48
+ attributes[:logger] ||= ::Logger.new(STDOUT)
28
49
  end
29
50
 
30
51
  def logger=(logger)
31
- @logger = logger
52
+ attributes[:logger] = logger
32
53
  end
33
54
 
34
55
  # Can be set or unset to allow for test suite mocking.
@@ -44,11 +65,11 @@ module Morpheus
44
65
  end
45
66
 
46
67
  def parse_error_handler
47
- @parse_error_handler
68
+ attributes[:parse_error_handler]
48
69
  end
49
70
 
50
71
  def parse_error_handler=(handler)
51
- @parse_error_handler = handler
72
+ attributes[:parse_error_handler] = handler
52
73
  end
53
74
 
54
75
  end
@@ -0,0 +1,16 @@
1
+ # Mixins provide behaviors to support the Base class.
2
+ module Morpheus
3
+ module Mixins
4
+ autoload :Associations, 'morpheus/mixins/associations'
5
+ autoload :Attributes, 'morpheus/mixins/attributes'
6
+ autoload :Conversion, 'morpheus/mixins/conversion'
7
+ autoload :Filtering, 'morpheus/mixins/filtering'
8
+ autoload :Finders, 'morpheus/mixins/finders'
9
+ autoload :Introspection, 'morpheus/mixins/introspection'
10
+ autoload :Persistence, 'morpheus/mixins/persistence'
11
+ autoload :Reflections, 'morpheus/mixins/reflections'
12
+ autoload :RequestHandling, 'morpheus/mixins/request_handling'
13
+ autoload :ResponseParsing, 'morpheus/mixins/response_parsing'
14
+ autoload :UrlSupport, 'morpheus/mixins/url_support'
15
+ end
16
+ end
@@ -1,57 +1,59 @@
1
1
  module Morpheus
2
- module Associations
3
- autoload :Association, 'morpheus/associations/association'
4
- autoload :BelongsToAssociation, 'morpheus/associations/belongs_to_association'
5
- autoload :HasManyAssociation, 'morpheus/associations/has_many_association'
6
- autoload :HasOneAssociation, 'morpheus/associations/has_one_association'
7
-
8
- def self.included(base)
9
- base.extend(ClassMethods)
10
- end
2
+ module Mixins
3
+ module Associations
4
+ autoload :Association, 'morpheus/mixins/associations/association'
5
+ autoload :BelongsToAssociation, 'morpheus/mixins/associations/belongs_to_association'
6
+ autoload :HasManyAssociation, 'morpheus/mixins/associations/has_many_association'
7
+ autoload :HasOneAssociation, 'morpheus/mixins/associations/has_one_association'
8
+
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
11
12
 
12
- module ClassMethods
13
+ module ClassMethods
13
14
 
14
- def belongs_to(association, options = {})
15
- attribute_id_sym = "#{association}_id".to_sym
15
+ def belongs_to(association, options = {})
16
+ attribute_id_sym = "#{association}_id".to_sym
16
17
 
17
- property attribute_id_sym
18
+ property attribute_id_sym
18
19
 
19
- create_reflection(:belongs_to, association, options)
20
+ create_reflection(:belongs_to, association, options)
20
21
 
21
- define_method association do
22
- instance_variable_get("@#{association}") ||
23
- instance_variable_set("@#{association}", BelongsToAssociation.new(self, association, :options => options))
24
- end
22
+ define_method association do
23
+ instance_variable_get("@#{association}") ||
24
+ instance_variable_set("@#{association}", BelongsToAssociation.new(self, association, :options => options))
25
+ end
25
26
 
26
- define_method "#{association}=" do |target|
27
- instance_variable_set("@#{association}", BelongsToAssociation.new(self, association, :target => target, :options => options))
28
- send("#{association}_id=", target.id)
27
+ define_method "#{association}=" do |target|
28
+ instance_variable_set("@#{association}", BelongsToAssociation.new(self, association, :target => target, :options => options))
29
+ send("#{association}_id=", target.id)
30
+ end
29
31
  end
30
- end
31
32
 
32
- def has_many(association, options = {})
33
- create_reflection(:has_many, association, options)
33
+ def has_many(association, options = {})
34
+ create_reflection(:has_many, association, options)
34
35
 
35
- define_method association do
36
- instance_variable_get("@#{association}") ||
37
- instance_variable_set("@#{association}", HasManyAssociation.new(self, association, :options => options))
36
+ define_method association do
37
+ instance_variable_get("@#{association}") ||
38
+ instance_variable_set("@#{association}", HasManyAssociation.new(self, association, :options => options))
39
+ end
38
40
  end
39
- end
40
41
 
41
- def has_one(association, options = {})
42
- create_reflection(:has_one, association, options)
42
+ def has_one(association, options = {})
43
+ create_reflection(:has_one, association, options)
43
44
 
44
- define_method association do
45
- instance_variable_get("@#{association}") ||
46
- instance_variable_set("@#{association}", HasOneAssociation.new(self, association, :options => options))
47
- end
45
+ define_method association do
46
+ instance_variable_get("@#{association}") ||
47
+ instance_variable_set("@#{association}", HasOneAssociation.new(self, association, :options => options))
48
+ end
48
49
 
49
- define_method "#{association}=" do |target|
50
- instance_variable_set("@#{association}", HasOneAssociation.new(self, association, :target => target, :options => options))
50
+ define_method "#{association}=" do |target|
51
+ instance_variable_set("@#{association}", HasOneAssociation.new(self, association, :target => target, :options => options))
52
+ end
51
53
  end
54
+
52
55
  end
53
56
 
54
57
  end
55
-
56
58
  end
57
59
  end