smooth_operator 1.21.0 → 1.21.1

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- M2EyMTBiMWExYzQ4Mjc0ZDM3M2IyMGRkZmFjMTEzYmVjYzg5NDJkMw==
4
+ N2I1ZjBjNDAwNjFjNzE5ODJkNmE4ZTA0MGViZjYxMjgzOGNiNzM2ZQ==
5
5
  data.tar.gz: !binary |-
6
- YmZjYzA1YWM0ZjJmYzMwOWZjN2ZmMzVkMjRiNDFlYzc5MjVmYzNlNQ==
6
+ YzBmMWExNmJiMzJjNWMxMTFhNDFlYWQ4YjBmMGI4ZmNlNTUyZjJlOQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- Mzg4ZGRhNDA4NWJjNmEzNDkzMWNjYjZhZTM5YTFiMGRiMmUzZWNmOWFmMzg4
10
- NjFiMGVjMDJhZGRkNTExNzdhNTAzOTU4MjQxNmVmZTBiMzIxM2Q5Y2I5MzZh
11
- MTlhYTZiYWYxNWU1OTZjZmM0YjQ0ZjFlMTYxMjIxZjE5NWMzMmE=
9
+ YTYxZmRjNmVlNGViM2MyZjU0NjJiNDhkNWMyN2QyNmU0MmU1YmEzOWY4ZWRh
10
+ NDE2MDliOTAwZjNjMzRkZDliYmQ3MDc4NjAyMDZjMGRjMGFhZjQ4OWU2ZGYw
11
+ YjVlYzkwNjYxZjJiNTgzNDM5M2E4MzFkNzQ0Y2U3MGM2YTRhYTA=
12
12
  data.tar.gz: !binary |-
13
- ODljN2NlMTBlZDM1NWYwMzhlZmJjMDBkNDM3ZGEwOTYzZmNmZGFmNDQwMjUy
14
- OWFhNjNmODRlNmUxYmI3MzdlZWQzZGEzZjg1MzE3ZmZkZDY2NmI5YjZiMDNj
15
- OTdhNTA0OWNlMTk5NmM2OTNkZTlkZTlkODZhNDZiODhhNmVhZjc=
13
+ N2I4MjM1YjI1MzE5YjhjOGJjNDZkMzU0MTBhMzE5OGFhMTA3MDIwOWNlYzE2
14
+ OWI2N2I0MjdiYTg1NDhlZDNkMmRiNDI5YmEyOWNjNzY2YWVhZGZlMzcyMDUw
15
+ ZWMzZmNjYjZkNDAzOTdmOWJjNTAxMTU3MjA2MzQ2M2VkOGRkNWE=
data/README.md CHANGED
@@ -1,11 +1,19 @@
1
- # SmoothOperator
1
+ # SmoothOperator [![Code Climate](https://codeclimate.com/repos/536a7b9f6956801228014b02/badges/13f79897976274a9de33/gpa.png)](https://codeclimate.com/repos/536a7b9f6956801228014b02/feed)
2
2
 
3
3
  Ruby gem, that mimics the ActiveRecord behaviour but through external API's.
4
4
  It's a lightweight and flexible alternative to ActiveResource, that responds to a REST API like you expect it too.
5
5
 
6
- Depends only on Faraday gem, no need for ActiveSupport or any other Active* gem.
6
+ Be sure to check out this micro-services example: https://github.com/goncalvesjoao/micro-services-example
7
7
 
8
- Although if I18n is present it will respond to .human_attribute_name method and if ActiveModel is present it will make use of 'ActiveModel::Name' to improve .model_name method.
8
+ Where a Rails4 app lists/creates/edits and destroys blog posts from a Padrino (aka Sinatra) app, using SmoothOperator::Rails instead of ActiveRecord::Base classes.
9
+
10
+ This micro-services example will also feature other cool stuff like:
11
+ - parallel requests;
12
+ - using HTTP PATCH verb for saving instead of PUT;
13
+ - form errors with simple_form gem;
14
+ - nested objects using cocoon gem;
15
+ - endless-pagination with kaminari gem
16
+ - and others...
9
17
 
10
18
  ---
11
19
 
@@ -13,7 +13,7 @@ module SmoothOperator
13
13
  attributes.delete(resources_name)
14
14
 
15
15
  @meta_data = attributes
16
-
16
+
17
17
  define_metada_methods
18
18
 
19
19
  super(@internal_array)
@@ -1,7 +1,7 @@
1
- require "smooth_operator/relation/reflection"
1
+ require "smooth_operator/associations/reflection"
2
2
 
3
3
  module SmoothOperator
4
- module Relation
4
+ module Associations
5
5
  class AssociationReflection < Reflection
6
6
 
7
7
  attr_reader :related_reflection, :macro
@@ -1,6 +1,6 @@
1
1
  module SmoothOperator
2
- module Relation
3
- class ArrayRelation < SimpleDelegator
2
+ module Associations
3
+ class HasManyRelation < SimpleDelegator
4
4
 
5
5
  attr_reader :object, :association
6
6
 
@@ -1,5 +1,5 @@
1
1
  module SmoothOperator
2
- module Relation
2
+ module Associations
3
3
  class Reflection
4
4
 
5
5
  attr_reader :name, :klass, :options
@@ -0,0 +1,100 @@
1
+ require "smooth_operator/associations/has_many_relation"
2
+ require "smooth_operator/associations/association_reflection"
3
+
4
+ module SmoothOperator
5
+ module Associations
6
+
7
+ def has_many(nested_object_name, options = {})
8
+ accepts_nested_objects(nested_object_name, :has_many, options)
9
+ end
10
+
11
+ def has_one(nested_object_name, options = {})
12
+ accepts_nested_objects(nested_object_name, :has_one, options)
13
+ end
14
+
15
+ def belongs_to(nested_object_name, options = {})
16
+ accepts_nested_objects(nested_object_name, :belongs_to, options)
17
+ end
18
+
19
+ def reflections
20
+ Helpers.get_instance_variable(self, :reflections, {})
21
+ end
22
+
23
+ def reflect_on_association(association)
24
+ reflections[association]
25
+ end
26
+
27
+ def reflect_on_all_associations(macro = nil)
28
+ macro ? reflections.values.select { |reflection| reflection.macro == macro } : reflections.values
29
+ end
30
+
31
+ protected ###################### PROTECTED ###################
32
+
33
+ def accepts_nested_objects(association, macro, options = {})
34
+ options = parse_options(options, { macro: macro })
35
+
36
+ reflection = AssociationReflection.new(association, Reflection.new(name, {}), options)
37
+
38
+ schema(association => reflection.klass)
39
+
40
+ reflections.merge!(association => reflection)
41
+
42
+ if reflection.has_many?
43
+ define_has_many_association_method(reflection, association)
44
+ else
45
+ define_single_association_method(reflection, association)
46
+ end
47
+
48
+ self.send(:attr_reader, "#{association}_attributes".to_sym)
49
+
50
+ define_attributes_setter_methods(reflection, association)
51
+ end
52
+
53
+ private ####################### PRIVATE ######################
54
+
55
+ def define_has_many_association_method(reflection, association)
56
+ define_method(association) do
57
+ has_many_relation = instance_variable_get("@#{association}")
58
+
59
+ if has_many_relation.nil?
60
+ has_many_relation = HasManyRelation.new(self, association)
61
+
62
+ instance_variable_set("@#{association}", has_many_relation)
63
+ end
64
+
65
+ has_many_relation.send(:refresh)
66
+
67
+ has_many_relation
68
+ end
69
+ end
70
+
71
+ def define_single_association_method(reflection, association)
72
+ define_method(association) { internal_data_get(association.to_s) }
73
+
74
+ define_method("build_#{association}") do |attributes = {}|
75
+ new_instance = reflection.klass.new(attributes)
76
+
77
+ internal_data_push(association, new_instance)
78
+
79
+ new_instance
80
+ end
81
+ end
82
+
83
+ def define_attributes_setter_methods(reflection, association)
84
+ define_method("#{association}_attributes=") do |attributes|
85
+ instance_variable_set("@#{association}_attributes", attributes)
86
+
87
+ attributes = attributes.values if reflection.has_many?
88
+
89
+ internal_data_push(association.to_s, attributes)
90
+ end
91
+ end
92
+
93
+ def parse_options(options, default_options)
94
+ options = options.is_a?(Hash) ? options.merge(default_options) : default_options
95
+
96
+ Helpers.symbolyze_keys(options)
97
+ end
98
+
99
+ end
100
+ end
@@ -23,7 +23,7 @@ module SmoothOperator
23
23
  @_meta_data = _attributes
24
24
  end
25
25
 
26
- @_internal_errors = attributes.delete(self.class.errors_key)
26
+ induce_errors(attributes.delete(self.class.errors_key))
27
27
 
28
28
  options.each { |key, value| @_options[key] = value } if options.is_a? Hash
29
29
 
@@ -34,10 +34,6 @@ module SmoothOperator
34
34
  end
35
35
  end
36
36
 
37
- def _parent_object
38
- _options[:parent_object]
39
- end
40
-
41
37
  protected ################# PROTECTED METHODS DOWN BELOW ###################
42
38
 
43
39
  def before_initialize(attributes, options); end
@@ -0,0 +1,17 @@
1
+ module SmoothOperator
2
+ module HttpMethods
3
+
4
+ HTTP_VERBS = %w[get post put patch delete]
5
+
6
+ HTTP_VERBS.each do |method|
7
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
8
+ def #{method}(relative_path = '', params = {}, options = {})
9
+ make_the_call(:#{method}, relative_path, params, options) do |remote_call|
10
+ block_given? ? yield(remote_call) : remote_call
11
+ end
12
+ end
13
+ RUBY
14
+ end
15
+
16
+ end
17
+ end
@@ -12,10 +12,12 @@ module SmoothOperator
12
12
 
13
13
  relative_path = resource_path(relative_path)
14
14
 
15
- if !_parent_object.nil? && options[:ignore_parent] != true
16
- id = Helpers.primary_key(_parent_object)
15
+ parent_object = _options[:parent_object]
17
16
 
18
- options[:resources_name] ||= "#{_parent_object.class.resources_name}/#{id}/#{self.class.resources_name}"
17
+ if !parent_object.nil? && options[:ignore_parent] != true
18
+ id = Helpers.primary_key(parent_object)
19
+
20
+ options[:resources_name] ||= "#{parent_object.class.resources_name}/#{id}/#{self.class.resources_name}"
19
21
  end
20
22
 
21
23
  self.class.make_the_call(http_verb, relative_path, data, options) do |remote_call|
@@ -23,8 +25,6 @@ module SmoothOperator
23
25
  end
24
26
  end
25
27
 
26
- protected ######################## PROTECTED ###################
27
-
28
28
  def resource_path(relative_path)
29
29
  if Helpers.absolute_path?(relative_path)
30
30
  Helpers.remove_initial_slash(relative_path)
@@ -41,24 +41,6 @@ module SmoothOperator
41
41
  base.extend(ClassMethods)
42
42
  end
43
43
 
44
- ########################### MODULES BELLOW ###############################
45
-
46
- module HttpMethods
47
-
48
- HTTP_VERBS = %w[get post put patch delete]
49
-
50
- HTTP_VERBS.each do |method|
51
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
52
- def #{method}(relative_path = '', params = {}, options = {})
53
- make_the_call(:#{method}, relative_path, params, options) do |remote_call|
54
- block_given? ? yield(remote_call) : remote_call
55
- end
56
- end
57
- RUBY
58
- end
59
-
60
- end
61
-
62
44
  module ClassMethods
63
45
 
64
46
  OPTIONS = [:endpoint, :endpoint_user, :endpoint_pass, :timeout]
@@ -76,15 +58,15 @@ module SmoothOperator
76
58
  attr_writer :headers
77
59
 
78
60
  def make_the_call(http_verb, relative_path = '', data = {}, options = {})
79
- operator_args = operator_method_args(http_verb, relative_path, data, options)
61
+ options = HelperMethods.populate_options(self, options)
80
62
 
81
- if Helpers.present?(operator_args[4][:hydra])
82
- operator_call = Operators::Typhoeus
83
- else
84
- operator_call = Operators::Faraday
85
- end
63
+ resource_path = resource_path(relative_path, options)
64
+
65
+ params, data = *HelperMethods.strip_params(self, http_verb, data)
86
66
 
87
- operator_call.make_the_call(*operator_args) do |remote_call|
67
+ operator = HelperMethods.get_me_an_operator(options)
68
+
69
+ operator.make_the_call(http_verb, resource_path, params, data, options) do |remote_call|
88
70
  block_given? ? yield(remote_call) : remote_call
89
71
  end
90
72
  end
@@ -93,45 +75,52 @@ module SmoothOperator
93
75
  params
94
76
  end
95
77
 
96
- protected #################### PROTECTED ##################
97
-
98
- def operator_method_args(http_verb, relative_path, data, options)
99
- options = populate_options(options)
78
+ def resource_path(relative_path, options)
79
+ resources_name = options[:resources_name] || self.resources_name
100
80
 
101
- [http_verb, resource_path(relative_path, options), *strip_params(http_verb, data), options]
81
+ if Helpers.present?(resources_name)
82
+ Helpers.present?(relative_path) ? "#{resources_name}/#{relative_path}" : resources_name
83
+ else
84
+ relative_path.to_s
85
+ end
102
86
  end
103
87
 
104
- private #################### PRIVATE ##################
105
-
106
- def populate_options(options)
107
- options ||= {}
88
+ end
108
89
 
109
- OPTIONS.each { |option| options[option] ||= send(option) }
90
+ module HelperMethods
110
91
 
111
- options[:headers] = headers.merge(options[:headers] || {})
92
+ extend self
112
93
 
113
- options
94
+ def get_me_an_operator(options)
95
+ if options[:parallel_connection].nil?
96
+ Operators::Faraday
97
+ else
98
+ Operators::Typhoeus
99
+ end
114
100
  end
115
101
 
116
- def resource_path(relative_path, options)
117
- _resources_name = options[:resources_name] || self.resources_name
102
+ def populate_options(object, options)
103
+ options ||= {}
118
104
 
119
- if Helpers.present?(_resources_name)
120
- Helpers.present?(relative_path) ? "#{_resources_name}/#{relative_path}" : _resources_name
121
- else
122
- relative_path.to_s
105
+ ClassMethods::OPTIONS.each do |option|
106
+ options[option] ||= object.send(option)
123
107
  end
108
+
109
+ options[:headers] = object.headers.merge(options[:headers] || {})
110
+
111
+ options
124
112
  end
125
113
 
126
- def strip_params(http_verb, data)
114
+ def strip_params(object, http_verb, data)
127
115
  data ||= {}
128
116
 
129
117
  if [:get, :head, :delete].include?(http_verb)
130
- [query_string(data), nil]
118
+ [object.query_string(data), nil]
131
119
  else
132
- [query_string({}), data]
120
+ [object.query_string({}), data]
133
121
  end
134
122
  end
123
+
135
124
  end
136
125
 
137
126
  end
@@ -43,7 +43,7 @@ module SmoothOperator
43
43
  raise 'UnknownPath'
44
44
  end
45
45
 
46
- _persistence_call(:reload, relative_path, data, options) do |remote_call|
46
+ make_a_persistence_call(:reload, relative_path, data, options) do |remote_call|
47
47
  block_given? ? yield(remote_call) : remote_call.status
48
48
  end
49
49
  end
@@ -67,7 +67,7 @@ module SmoothOperator
67
67
  def destroy(relative_path = nil, data = {}, options = {})
68
68
  return false unless persisted?
69
69
 
70
- _persistence_call(:destroy, relative_path, data, options) do |remote_call|
70
+ make_a_persistence_call(:destroy, relative_path, data, options) do |remote_call|
71
71
  @destroyed = true if remote_call.status
72
72
 
73
73
  block_given? ? yield(remote_call) : remote_call.status
@@ -77,7 +77,7 @@ module SmoothOperator
77
77
  protected ######################### PROTECTED ##################
78
78
 
79
79
  def create(relative_path, data, options)
80
- _persistence_call(:create, relative_path, data, options) do |remote_call|
80
+ make_a_persistence_call(:create, relative_path, data, options) do |remote_call|
81
81
  @new_record = false if remote_call.status
82
82
 
83
83
  block_given? ? yield(remote_call) : remote_call
@@ -85,7 +85,7 @@ module SmoothOperator
85
85
  end
86
86
 
87
87
  def update(relative_path, data, options)
88
- _persistence_call(:update, relative_path, data, options) do |remote_call|
88
+ make_a_persistence_call(:update, relative_path, data, options) do |remote_call|
89
89
  block_given? ? yield(remote_call) : remote_call
90
90
  end
91
91
  end
@@ -102,7 +102,7 @@ module SmoothOperator
102
102
 
103
103
  private ##################### PRIVATE ##################
104
104
 
105
- def _persistence_call(method, relative_path, data, options)
105
+ def make_a_persistence_call(method, relative_path, data, options)
106
106
  options ||= {}
107
107
 
108
108
  http_verb = options[:http_verb] || self.class.methods_vs_http_verbs[method]
@@ -6,8 +6,7 @@ module SmoothOperator
6
6
  end
7
7
 
8
8
  def internal_structure
9
- Helpers.get_instance_variable(self, :internal_structure,
10
- { primary_key => nil })
9
+ Helpers.get_instance_variable(self, :internal_structure, {})
11
10
  end
12
11
 
13
12
  def known_attribute?(attribute)
@@ -2,15 +2,23 @@ module SmoothOperator
2
2
  module Validations
3
3
 
4
4
  def valid?(context = nil)
5
- Helpers.blank?(_internal_errors)
5
+ Helpers.blank?(induced_errors)
6
6
  end
7
7
 
8
8
  def invalid?
9
9
  !valid?
10
10
  end
11
11
 
12
- def _internal_errors
13
- @_internal_errors ||= {}
12
+ def induced_errors
13
+ @induced_errors ||= {}
14
+ end
15
+
16
+ def clear_induced_errors
17
+ @induced_errors = {}
18
+ end
19
+
20
+ def induce_errors(value)
21
+ @induced_errors = value
14
22
  end
15
23
 
16
24
  def self.included(base)
@@ -1,3 +1,3 @@
1
1
  module SmoothOperator
2
- VERSION = "1.21.0"
2
+ VERSION = "1.21.1"
3
3
  end
@@ -5,22 +5,23 @@ require "smooth_operator/operator"
5
5
  require "smooth_operator/persistence"
6
6
  require "smooth_operator/translation"
7
7
  require "smooth_operator/open_struct"
8
+ require "smooth_operator/http_methods"
9
+ require "smooth_operator/associations"
8
10
  require "smooth_operator/finder_methods"
9
- require "smooth_operator/relation/associations"
10
11
 
11
12
  module SmoothOperator
12
13
  class Base < OpenStruct
13
14
 
14
15
  extend Schema
16
+ extend HttpMethods
17
+ extend Associations
15
18
  extend FinderMethods
16
- extend Operator::HttpMethods
17
- extend Relation::Associations
18
19
  extend Translation if defined? I18n
19
20
 
20
21
  include Operator
22
+ include HttpMethods
21
23
  include Persistence
22
24
  include FinderMethods
23
- include Operator::HttpMethods
24
25
 
25
26
  self.strict_behaviour = true
26
27
 
@@ -37,6 +38,8 @@ module SmoothOperator
37
38
  include ActiveModel::Validations::Callbacks
38
39
  include ActiveModel::Conversion
39
40
 
41
+ validate :validate_induced_errors, :validate_nested_objects
42
+
40
43
  def column_for_attribute(attribute_name)
41
44
  type = self.class.attribute_type(attribute_name)
42
45
 
@@ -44,12 +47,11 @@ module SmoothOperator
44
47
  end
45
48
 
46
49
  def save(relative_path = nil, data = {}, options = {})
47
- # clear_server_errors
48
50
  return false unless before_save
49
51
 
50
- save_result = valid? ? super : false
52
+ clear_induced_errors
51
53
 
52
- # import_server_errors
54
+ save_result = valid? ? super : false
53
55
 
54
56
  after_save if valid? && save_result
55
57
 
@@ -62,6 +64,22 @@ module SmoothOperator
62
64
 
63
65
  def after_save; end
64
66
 
67
+ protected ################# PROTECTED ###################
68
+
69
+ def validate_induced_errors
70
+ induced_errors.each do |key, value|
71
+ [*value].each do |_value|
72
+ self.errors.add(key, _value) unless self.errors.added?(key, _value)
73
+ end
74
+ end
75
+
76
+ Helpers.blank?(induced_errors)
77
+ end
78
+
79
+ def validate_nested_objects
80
+ # nested_objects.map { |reflection, nested_object| nested_object.valid? }.all?
81
+ end
82
+
65
83
  end
66
84
  end
67
85
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smooth_operator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 1.21.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - João Gonçalves
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-31 00:00:00.000000000 Z
11
+ date: 2014-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,20 +82,21 @@ files:
82
82
  - console.rb
83
83
  - lib/smooth_operator.rb
84
84
  - lib/smooth_operator/array_with_meta_data.rb
85
+ - lib/smooth_operator/associations.rb
86
+ - lib/smooth_operator/associations/association_reflection.rb
87
+ - lib/smooth_operator/associations/has_many_relation.rb
88
+ - lib/smooth_operator/associations/reflection.rb
85
89
  - lib/smooth_operator/attribute_assignment.rb
86
90
  - lib/smooth_operator/delegation.rb
87
91
  - lib/smooth_operator/finder_methods.rb
88
92
  - lib/smooth_operator/helpers.rb
93
+ - lib/smooth_operator/http_methods.rb
89
94
  - lib/smooth_operator/internal_data.rb
90
95
  - lib/smooth_operator/open_struct.rb
91
96
  - lib/smooth_operator/operator.rb
92
97
  - lib/smooth_operator/operators/faraday.rb
93
98
  - lib/smooth_operator/operators/typhoeus.rb
94
99
  - lib/smooth_operator/persistence.rb
95
- - lib/smooth_operator/relation/array_relation.rb
96
- - lib/smooth_operator/relation/association_reflection.rb
97
- - lib/smooth_operator/relation/associations.rb
98
- - lib/smooth_operator/relation/reflection.rb
99
100
  - lib/smooth_operator/remote_call/base.rb
100
101
  - lib/smooth_operator/remote_call/errors/connection_failed.rb
101
102
  - lib/smooth_operator/remote_call/errors/timeout.rb
@@ -1,102 +0,0 @@
1
- require "smooth_operator/relation/array_relation"
2
- require "smooth_operator/relation/association_reflection"
3
-
4
- module SmoothOperator
5
- module Relation
6
- module Associations
7
-
8
- def has_many(nested_object_name, options = {})
9
- accepts_nested_objects(nested_object_name, :has_many, options)
10
- end
11
-
12
- def has_one(nested_object_name, options = {})
13
- accepts_nested_objects(nested_object_name, :has_one, options)
14
- end
15
-
16
- def belongs_to(nested_object_name, options = {})
17
- accepts_nested_objects(nested_object_name, :belongs_to, options)
18
- end
19
-
20
- def reflections
21
- Helpers.get_instance_variable(self, :reflections, {})
22
- end
23
-
24
- def reflect_on_association(association)
25
- reflections[association]
26
- end
27
-
28
- def reflect_on_all_associations(macro = nil)
29
- macro ? reflections.values.select { |reflection| reflection.macro == macro } : reflections.values
30
- end
31
-
32
- protected ###################### PROTECTED ###################
33
-
34
- def accepts_nested_objects(association, macro, options = {})
35
- options = parse_options(options, { macro: macro })
36
-
37
- reflection = AssociationReflection.new(association, Reflection.new(name, {}), options)
38
-
39
- schema(association => reflection.klass)
40
-
41
- reflections.merge!(association => reflection)
42
-
43
- if reflection.has_many?
44
- define_has_many_association_method(reflection, association)
45
- else
46
- define_single_association_method(reflection, association)
47
- end
48
-
49
- self.send(:attr_reader, "#{association}_attributes".to_sym)
50
-
51
- define_attributes_setter_methods(reflection, association)
52
- end
53
-
54
- private ####################### PRIVATE ######################
55
-
56
- def define_has_many_association_method(reflection, association)
57
- define_method(association) do
58
- array_relation = instance_variable_get("@#{association}")
59
-
60
- if array_relation.nil?
61
- array_relation = ArrayRelation.new(self, association)
62
-
63
- instance_variable_set("@#{association}", array_relation)
64
- end
65
-
66
- array_relation.send(:refresh)
67
-
68
- array_relation
69
- end
70
- end
71
-
72
- def define_single_association_method(reflection, association)
73
- define_method(association) { internal_data_get(association.to_s) }
74
-
75
- define_method("build_#{association}") do |attributes = {}|
76
- new_instance = reflection.klass.new(attributes)
77
-
78
- internal_data_push(association, new_instance)
79
-
80
- new_instance
81
- end
82
- end
83
-
84
- def define_attributes_setter_methods(reflection, association)
85
- define_method("#{association}_attributes=") do |attributes|
86
- instance_variable_set("@#{association}_attributes", attributes)
87
-
88
- attributes = attributes.values if reflection.has_many?
89
-
90
- internal_data_push(association.to_s, attributes)
91
- end
92
- end
93
-
94
- def parse_options(options, default_options)
95
- options = options.is_a?(Hash) ? options.merge(default_options) : default_options
96
-
97
- Helpers.symbolyze_keys(options)
98
- end
99
-
100
- end
101
- end
102
- end