smooth_operator 1.20.10 → 1.21.0

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