smooth_operator 1.20.10 → 1.21.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 (37) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +2 -2
  3. data/lib/smooth_operator/array_with_meta_data.rb +20 -8
  4. data/lib/smooth_operator/attribute_assignment.rb +41 -54
  5. data/lib/smooth_operator/delegation.rb +14 -33
  6. data/lib/smooth_operator/finder_methods.rb +26 -17
  7. data/lib/smooth_operator/helpers.rb +10 -8
  8. data/lib/smooth_operator/internal_data.rb +45 -0
  9. data/lib/smooth_operator/open_struct.rb +9 -27
  10. data/lib/smooth_operator/operator.rb +11 -12
  11. data/lib/smooth_operator/persistence.rb +52 -41
  12. data/lib/smooth_operator/relation/array_relation.rb +2 -12
  13. data/lib/smooth_operator/relation/association_reflection.rb +2 -6
  14. data/lib/smooth_operator/relation/associations.rb +3 -3
  15. data/lib/smooth_operator/remote_call/base.rb +0 -4
  16. data/lib/smooth_operator/{model_name.rb → resource_name.rb} +2 -2
  17. data/lib/smooth_operator/schema.rb +9 -20
  18. data/lib/smooth_operator/serialization.rb +11 -11
  19. data/lib/smooth_operator/translation.rb +21 -12
  20. data/lib/smooth_operator/type_casting.rb +127 -0
  21. data/lib/smooth_operator/validations.rb +19 -3
  22. data/lib/smooth_operator/version.rb +1 -1
  23. data/lib/smooth_operator.rb +24 -3
  24. data/spec/smooth_operator/attribute_assignment_spec.rb +4 -13
  25. data/spec/smooth_operator/finder_methods_spec.rb +4 -9
  26. data/spec/smooth_operator/persistence_spec.rb +3 -15
  27. data/spec/smooth_operator/{model_name_spec.rb → resource_name_spec.rb} +1 -1
  28. data/spec/support/models/address.rb +0 -2
  29. data/spec/support/models/user.rb +3 -3
  30. data/spec/support/models/user_with_address_and_posts.rb +6 -14
  31. metadata +7 -12
  32. data/lib/smooth_operator/attribute_methods.rb +0 -92
  33. data/lib/smooth_operator/attributes/base.rb +0 -107
  34. data/lib/smooth_operator/attributes/dirty.rb +0 -29
  35. data/lib/smooth_operator/attributes/normal.rb +0 -15
  36. data/lib/smooth_operator/blank_slate.rb +0 -7
  37. data/spec/smooth_operator/attributes_dirty_spec.rb +0 -53
@@ -12,8 +12,10 @@ module SmoothOperator
12
12
 
13
13
  relative_path = resource_path(relative_path)
14
14
 
15
- if !parent_object.nil? && options[:ignore_parent] != true
16
- options[:resources_name] ||= "#{parent_object.class.resources_name}/#{parent_object.get_primary_key}/#{self.class.resources_name}"
15
+ if !_parent_object.nil? && options[:ignore_parent] != true
16
+ id = Helpers.primary_key(_parent_object)
17
+
18
+ options[:resources_name] ||= "#{_parent_object.class.resources_name}/#{id}/#{self.class.resources_name}"
17
19
  end
18
20
 
19
21
  self.class.make_the_call(http_verb, relative_path, data, options) do |remote_call|
@@ -27,12 +29,18 @@ module SmoothOperator
27
29
  if Helpers.absolute_path?(relative_path)
28
30
  Helpers.remove_initial_slash(relative_path)
29
31
  elsif persisted?
30
- Helpers.present?(relative_path) ? "#{get_primary_key}/#{relative_path}" : get_primary_key.to_s
32
+ id = Helpers.primary_key(self)
33
+
34
+ Helpers.present?(relative_path) ? "#{id}/#{relative_path}" : id.to_s
31
35
  else
32
36
  relative_path
33
37
  end
34
38
  end
35
39
 
40
+ def self.included(base)
41
+ base.extend(ClassMethods)
42
+ end
43
+
36
44
  ########################### MODULES BELLOW ###############################
37
45
 
38
46
  module HttpMethods
@@ -67,7 +75,6 @@ module SmoothOperator
67
75
 
68
76
  attr_writer :headers
69
77
 
70
-
71
78
  def make_the_call(http_verb, relative_path = '', data = {}, options = {})
72
79
  operator_args = operator_method_args(http_verb, relative_path, data, options)
73
80
 
@@ -127,13 +134,5 @@ module SmoothOperator
127
134
  end
128
135
  end
129
136
 
130
- include HttpMethods
131
-
132
- def self.included(base)
133
- base.extend(ClassMethods)
134
- base.extend(HttpMethods)
135
- end
136
-
137
137
  end
138
-
139
138
  end
@@ -7,28 +7,20 @@ module SmoothOperator
7
7
 
8
8
  attr_reader :last_remote_call
9
9
 
10
- def get_primary_key
11
- get_internal_data(self.class.primary_key)
12
- end
13
-
14
- def reload(relative_path = nil, data = {}, options = {})
15
- raise 'UnknownPath' if Helpers.blank?(relative_path) && (!respond_to?(self.class.primary_key) || Helpers.blank?(get_primary_key))
10
+ def new_record?(ignore_cache = false)
11
+ return @new_record if !ignore_cache && defined?(@new_record)
16
12
 
17
- persistence_call(:reload, relative_path, data, options) do |remote_call|
18
- block_given? ? yield(remote_call) : remote_call.status
19
- end
13
+ @new_record = Helpers.has_primary_key?(self)
20
14
  end
21
15
 
22
- def new_record?(bypass_cache = false)
23
- return @new_record if !bypass_cache && defined?(@new_record)
24
-
25
- @new_record = Helpers.blank?(get_primary_key)
26
- end
16
+ def marked_for_destruction?(ignore_cache = false)
17
+ if !ignore_cache && defined?(@marked_for_destruction)
18
+ return @marked_for_destruction
19
+ end
27
20
 
28
- def marked_for_destruction?(bypass_cache = false)
29
- return @marked_for_destruction if !bypass_cache && defined?(@marked_for_destruction)
21
+ _destroy = internal_data_get(self.class.destroy_key)
30
22
 
31
- @marked_for_destruction = ["true", "1", true].include?(get_internal_data(self.class.destroy_key))
23
+ @marked_for_destruction = TypeCasting::TRUE_VALUES.include?(_destroy)
32
24
  end
33
25
 
34
26
  def destroyed?
@@ -41,13 +33,28 @@ module SmoothOperator
41
33
  !(new_record? || destroyed?)
42
34
  end
43
35
 
36
+ def known_attribute?(attribute)
37
+ super ||
38
+ [self.class.primary_key, self.class.destroy_key].include?(attribute.to_s)
39
+ end
40
+
41
+ def reload(relative_path = nil, data = {}, options = {})
42
+ if Helpers.blank?(relative_path) && Helpers.has_primary_key?(self)
43
+ raise 'UnknownPath'
44
+ end
45
+
46
+ _persistence_call(:reload, relative_path, data, options) do |remote_call|
47
+ block_given? ? yield(remote_call) : remote_call.status
48
+ end
49
+ end
50
+
44
51
  def save(relative_path = nil, data = {}, options = {})
45
- data = data_with_object_attributes(data, options)
52
+ data = resource_attributes(data, options)
53
+
54
+ method = new_record? ? :create : :update
46
55
 
47
- if new_record?
48
- create(relative_path, data, options) { |remote_call| block_given? ? yield(remote_call) : remote_call.status }
49
- else
50
- update(relative_path, data, options) { |remote_call| block_given? ? yield(remote_call) : remote_call.status }
56
+ send(method, relative_path, data, options) do |remote_call|
57
+ block_given? ? yield(remote_call) : remote_call.status
51
58
  end
52
59
  end
53
60
 
@@ -60,18 +67,17 @@ module SmoothOperator
60
67
  def destroy(relative_path = nil, data = {}, options = {})
61
68
  return false unless persisted?
62
69
 
63
- persistence_call(:destroy, relative_path, data, options) do |remote_call|
70
+ _persistence_call(:destroy, relative_path, data, options) do |remote_call|
64
71
  @destroyed = true if remote_call.status
65
72
 
66
73
  block_given? ? yield(remote_call) : remote_call.status
67
74
  end
68
75
  end
69
76
 
70
-
71
77
  protected ######################### PROTECTED ##################
72
78
 
73
79
  def create(relative_path, data, options)
74
- persistence_call(:create, relative_path, data, options) do |remote_call|
80
+ _persistence_call(:create, relative_path, data, options) do |remote_call|
75
81
  @new_record = false if remote_call.status
76
82
 
77
83
  block_given? ? yield(remote_call) : remote_call
@@ -79,12 +85,24 @@ module SmoothOperator
79
85
  end
80
86
 
81
87
  def update(relative_path, data, options)
82
- persistence_call(:update, relative_path, data, options) do |remote_call|
88
+ _persistence_call(:update, relative_path, data, options) do |remote_call|
83
89
  block_given? ? yield(remote_call) : remote_call
84
90
  end
85
91
  end
86
92
 
87
- def persistence_call(method, relative_path, data, options)
93
+ def resource_attributes(data, options)
94
+ data = Helpers.stringify_keys(data)
95
+
96
+ hash = serializable_hash(options[:serializable_options]).dup
97
+
98
+ hash.delete(self.class.primary_key)
99
+
100
+ { self.class.resource_name => hash }.merge(data)
101
+ end
102
+
103
+ private ##################### PRIVATE ##################
104
+
105
+ def _persistence_call(method, relative_path, data, options)
88
106
  options ||= {}
89
107
 
90
108
  http_verb = options[:http_verb] || self.class.methods_vs_http_verbs[method]
@@ -93,24 +111,13 @@ module SmoothOperator
93
111
  @last_remote_call = remote_call
94
112
 
95
113
  if !@last_remote_call.error? && @last_remote_call.parsed_response.is_a?(Hash)
96
- assign_attributes @last_remote_call.parsed_response, from_server: true
114
+ assign_attributes @last_remote_call.parsed_response, data_from_server: true
97
115
  end
98
116
 
99
117
  yield(remote_call)
100
118
  end
101
119
  end
102
120
 
103
- def data_with_object_attributes(data, options)
104
- data = Helpers.stringify_keys(data)
105
-
106
- hash = serializable_hash(options[:serializable_options]).dup
107
-
108
- hash.delete(self.class.primary_key)
109
-
110
- { self.class.resource_name => hash }.merge(data)
111
- end
112
-
113
-
114
121
  module ClassMethods
115
122
 
116
123
  METHODS_VS_HTTP_VERBS = { reload: :get, create: :post, update: :put, destroy: :delete }
@@ -132,11 +139,15 @@ module SmoothOperator
132
139
  attr_writer :destroy_key
133
140
 
134
141
  METHODS_VS_HTTP_VERBS.keys.each do |method|
135
- define_method("#{method}_http_verb=") { |http_verb| methods_vs_http_verbs[method] = http_verb }
142
+ define_method("#{method}_http_verb=") do |http_verb|
143
+ methods_vs_http_verbs[method] = http_verb
144
+ end
136
145
  end
137
146
 
138
147
  def create(attributes = nil, relative_path = nil, data = {}, options = {})
139
- new(attributes).tap { |object| object.save(relative_path, data, options) }
148
+ new(attributes).tap do |object|
149
+ object.save(relative_path, data, options)
150
+ end
140
151
  end
141
152
 
142
153
  end
@@ -1,6 +1,6 @@
1
1
  module SmoothOperator
2
2
  module Relation
3
- class ArrayRelation < ::SimpleDelegator
3
+ class ArrayRelation < SimpleDelegator
4
4
 
5
5
  attr_reader :object, :association
6
6
 
@@ -30,18 +30,8 @@ module SmoothOperator
30
30
 
31
31
  protected ############### PROTECTED ###############
32
32
 
33
- # def method_missing(method, *args, &block)
34
- # if get_array.respond_to?(method)
35
- # puts "if true #{method} - #{args}"
36
- # get_array.send(method, *args)
37
- # else
38
- # puts "if else #{method}"
39
- # super
40
- # end
41
- # end
42
-
43
33
  def get_array
44
- data = object.get_internal_data(association.to_s)
34
+ data = object.internal_data_get(association.to_s)
45
35
 
46
36
  data.nil? ? [] : [*data]
47
37
  end
@@ -8,8 +8,8 @@ module SmoothOperator
8
8
 
9
9
  def initialize(association, related_reflection, options)
10
10
  super(association, options)
11
- @macro = options[:macro] || macro_default(association)
12
- @related_reflection = related_reflection
11
+
12
+ @related_reflection, @macro = related_reflection, options[:macro]
13
13
  end
14
14
 
15
15
  def primary_key
@@ -62,10 +62,6 @@ module SmoothOperator
62
62
 
63
63
  private ################################# private
64
64
 
65
- def macro_default(association)
66
- Helpers.plural?(association) ? :has_many : :belongs_to
67
- end
68
-
69
65
  def foreign_key_default
70
66
  if has_many? || has_one?
71
67
  "#{related_reflection.single_name}_id"
@@ -70,12 +70,12 @@ module SmoothOperator
70
70
  end
71
71
 
72
72
  def define_single_association_method(reflection, association)
73
- define_method(association) { get_internal_data(association.to_s) }
73
+ define_method(association) { internal_data_get(association.to_s) }
74
74
 
75
75
  define_method("build_#{association}") do |attributes = {}|
76
76
  new_instance = reflection.klass.new(attributes)
77
77
 
78
- push_to_internal_data(association, new_instance)
78
+ internal_data_push(association, new_instance)
79
79
 
80
80
  new_instance
81
81
  end
@@ -87,7 +87,7 @@ module SmoothOperator
87
87
 
88
88
  attributes = attributes.values if reflection.has_many?
89
89
 
90
- push_to_internal_data(association.to_s, attributes)
90
+ internal_data_push(association.to_s, attributes)
91
91
  end
92
92
  end
93
93
 
@@ -62,10 +62,6 @@ module SmoothOperator
62
62
  error? ? nil : ok?
63
63
  end
64
64
 
65
- def objects
66
- object.respond_to?(:length) ? object : []
67
- end
68
-
69
65
  def data
70
66
  object.nil? ? parsed_response : object
71
67
  end
@@ -1,5 +1,5 @@
1
1
  module SmoothOperator
2
- module ModelName
2
+ module ResourceName
3
3
 
4
4
  def resources_name(default_bypass = nil)
5
5
  return @resources_name if defined?(@resources_name)
@@ -40,7 +40,7 @@ module SmoothOperator
40
40
  end
41
41
 
42
42
  ActiveModel::Name.new(self, namespace, @_model_name).tap do |model_name|
43
- def model_name.human(options = {}); @klass.send(:_translate, "models.#{i18n_key}", options); end
43
+ def model_name.human(options = {}); SmoothOperator::Translation::HelperMethods.translate("models.#{i18n_key}", options); end
44
44
  end
45
45
  end
46
46
  end
@@ -1,32 +1,21 @@
1
1
  module SmoothOperator
2
2
  module Schema
3
3
 
4
- def known_by_schema?(attribute)
5
- self.class.internal_structure.include?(attribute.to_s)
4
+ def schema(structure)
5
+ internal_structure.merge! Helpers.stringify_keys(structure)
6
6
  end
7
7
 
8
- def get_attribute_type(attribute)
9
- self.class.internal_structure[attribute.to_s]
8
+ def internal_structure
9
+ Helpers.get_instance_variable(self, :internal_structure,
10
+ { primary_key => nil })
10
11
  end
11
12
 
12
- def self.included(base)
13
- base.extend(ClassMethods)
13
+ def known_attribute?(attribute)
14
+ internal_structure.has_key?(attribute.to_s)
14
15
  end
15
16
 
16
- module ClassMethods
17
-
18
- attr_writer :resource_name
19
-
20
- def schema(structure)
21
- internal_structure.merge! Helpers.stringify_keys(structure)
22
-
23
- known_attributes.merge internal_structure.keys
24
- end
25
-
26
- def internal_structure
27
- Helpers.get_instance_variable(self, :internal_structure, { "errors" => nil, primary_key => nil, destroy_key => nil })
28
- end
29
-
17
+ def attribute_type(attribute)
18
+ internal_structure[attribute.to_s]
30
19
  end
31
20
 
32
21
  end
@@ -5,13 +5,13 @@ module SmoothOperator
5
5
  def to_hash(options = nil)
6
6
  Helpers.symbolyze_keys(serializable_hash(options) || {})
7
7
  end
8
-
8
+
9
9
  # alias :attributes :to_hash
10
10
  def attributes; to_hash; end
11
-
11
+
12
12
  def to_json(options = nil)
13
13
  require 'json' unless defined? JSON
14
-
14
+
15
15
  JSON(serializable_hash(options) || {})
16
16
  end
17
17
 
@@ -23,8 +23,8 @@ module SmoothOperator
23
23
  hash = {}
24
24
  options ||= {}
25
25
 
26
- attribute_names(options).each do |attribute_name|
27
- hash[attribute_name] = read_attribute_for_hashing(attribute_name, options)
26
+ _attribute_names(options).each do |attribute_name|
27
+ hash[attribute_name] = _read_attribute_for_hashing(attribute_name, options)
28
28
  end
29
29
 
30
30
  method_names(options).each do |method_name|
@@ -36,9 +36,9 @@ module SmoothOperator
36
36
 
37
37
 
38
38
  protected ##################### PROTECTED ###################
39
-
39
+
40
40
  # TODO: COMPLEX METHOD
41
- def attribute_names(options)
41
+ def _attribute_names(options)
42
42
  attribute_names = internal_data.keys.sort
43
43
 
44
44
  if only = options[:only]
@@ -54,19 +54,19 @@ module SmoothOperator
54
54
  [*options[:methods]].select { |n| respond_to?(n) }
55
55
  end
56
56
 
57
- def read_attribute_for_hashing(attribute_name, options)
57
+ def _read_attribute_for_hashing(attribute_name, options)
58
58
  object = read_attribute_for_serialization(attribute_name)
59
59
 
60
60
  _options = options[attribute_name] || options[attribute_name.to_sym]
61
61
 
62
62
  if object.is_a?(Array)
63
- object.map { |array_entry| attribute_to_hash(array_entry, _options) }
63
+ object.map { |array_entry| _attribute_to_hash(array_entry, _options) }
64
64
  else
65
- attribute_to_hash(object, _options)
65
+ _attribute_to_hash(object, _options)
66
66
  end
67
67
  end
68
68
 
69
- def attribute_to_hash(object, options = nil)
69
+ def _attribute_to_hash(object, options = nil)
70
70
  if object.respond_to?(:serializable_hash)
71
71
  Helpers.symbolyze_keys(object.serializable_hash(options))
72
72
  else
@@ -2,23 +2,32 @@ module SmoothOperator
2
2
  module Translation
3
3
 
4
4
  def human_attribute_name(attribute_key_name, options = {})
5
- _translate("attributes.#{model_name.i18n_key}.#{attribute_key_name}", options = {})
5
+ HelperMethods.translate(
6
+ "attributes.#{model_name.i18n_key}.#{attribute_key_name}",
7
+ options
8
+ )
6
9
  end
7
10
 
8
- private ###################### PRIVATE #########################
11
+ module HelperMethods
9
12
 
10
- def _translate(namespace = '', options = {})
11
- no_translation = "-- no translation --"
13
+ extend self
12
14
 
13
- defaults = ["smooth_operator.#{namespace}".to_sym]
14
- defaults << "activerecord.#{namespace}".to_sym
15
- defaults << options[:default] if options[:default]
16
- defaults.flatten!
17
- defaults << no_translation
15
+ def translate(namespace = '', options = {})
16
+ no_translation = "-- no translation --"
17
+
18
+ defaults = ["smooth_operator.#{namespace}".to_sym]
19
+ defaults << "activerecord.#{namespace}".to_sym
20
+ defaults << options[:default] if options[:default]
21
+ defaults.flatten!
22
+ defaults << no_translation
23
+
24
+ options = { count: 1, default: defaults }
25
+ .merge!(options.except(:default))
26
+
27
+ I18n.translate(defaults.shift, options)
28
+ end
18
29
 
19
- options = { count: 1, default: defaults }.merge!(options.except(:default))
20
- I18n.translate(defaults.shift, options)
21
30
  end
22
31
 
23
32
  end
24
- end
33
+ end