morpheus 0.4.0 → 0.5.0

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