active_mocker 2.1.3 → 2.2.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +5 -0
  4. data/lib/active_mocker.rb +7 -6
  5. data/lib/active_mocker/config.rb +6 -8
  6. data/lib/active_mocker/deprecated_components/mock_abilities.rb +6 -10
  7. data/lib/active_mocker/deprecated_components/rspec.rb +2 -1
  8. data/lib/active_mocker/display_errors.rb +3 -2
  9. data/lib/active_mocker/error_object.rb +13 -13
  10. data/lib/active_mocker/file_path_to_ruby_class.rb +2 -3
  11. data/lib/active_mocker/file_writer.rb +125 -0
  12. data/lib/active_mocker/generate.rb +56 -71
  13. data/lib/active_mocker/hash_new_style.rb +2 -1
  14. data/lib/active_mocker/loaded_mocks.rb +9 -11
  15. data/lib/active_mocker/mock.rb +28 -26
  16. data/lib/active_mocker/mock/alias_attribute.rb +19 -0
  17. data/lib/active_mocker/mock/association.rb +2 -1
  18. data/lib/active_mocker/mock/base.rb +22 -20
  19. data/lib/active_mocker/mock/belongs_to.rb +1 -1
  20. data/lib/active_mocker/mock/collection.rb +6 -6
  21. data/lib/active_mocker/mock/do_nothing_active_record_methods.rb +4 -7
  22. data/lib/active_mocker/mock/exceptions.rb +1 -4
  23. data/lib/active_mocker/mock/has_and_belongs_to_many.rb +2 -1
  24. data/lib/active_mocker/mock/has_many.rb +6 -7
  25. data/lib/active_mocker/mock/has_one.rb +2 -2
  26. data/lib/active_mocker/mock/hash_process.rb +2 -2
  27. data/lib/active_mocker/mock/mock_relation.rb +1 -0
  28. data/lib/active_mocker/mock/object_inspect.rb +2 -2
  29. data/lib/active_mocker/mock/queries.rb +12 -16
  30. data/lib/active_mocker/mock/records.rb +3 -3
  31. data/lib/active_mocker/mock/relation.rb +5 -5
  32. data/lib/active_mocker/mock/single_relation.rb +2 -4
  33. data/lib/active_mocker/mock/template_methods.rb +3 -5
  34. data/lib/active_mocker/mock_creator.rb +78 -22
  35. data/lib/active_mocker/mock_template.erb +1 -0
  36. data/lib/active_mocker/mock_template/_recreate_class_method_calls.erb +12 -0
  37. data/lib/active_mocker/null_progress.rb +2 -2
  38. data/lib/active_mocker/parent_class.rb +4 -2
  39. data/lib/active_mocker/progress.rb +6 -8
  40. data/lib/active_mocker/public_methods.rb +3 -2
  41. data/lib/active_mocker/railtie.rb +3 -3
  42. data/lib/active_mocker/rspec.rb +2 -1
  43. data/lib/active_mocker/rspec_helper.rb +4 -3
  44. data/lib/active_mocker/task.rake +9 -10
  45. data/lib/active_mocker/template_creator.rb +5 -5
  46. data/lib/active_mocker/version.rb +2 -1
  47. metadata +25 -8
@@ -1,11 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  class HasOne < SingleRelation
3
4
  attr_reader :item
4
5
 
5
6
  def initialize(item, child_self:, foreign_key:)
6
- item.send(:write_attribute, foreign_key, item.try(:id)) if !item.try(:id).nil?
7
+ item.send(:write_attribute, foreign_key, item.try(:id)) unless item.try(:id).nil?
7
8
  super
8
9
  end
9
-
10
10
  end
11
11
  end
@@ -1,7 +1,7 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  # @api private
3
4
  class HashProcess
4
-
5
5
  attr_accessor :hash, :processor
6
6
 
7
7
  def initialize(hash, processor)
@@ -19,4 +19,4 @@ module ActiveMocker
19
19
  self
20
20
  end
21
21
  end
22
- end
22
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  class MockRelation
3
4
  # @param [ActiveMocker::Base] mock, a generated mock class
@@ -1,6 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  class ObjectInspect
3
-
4
4
  def initialize(class_name, attributes)
5
5
  @class_name = class_name
6
6
  @attributes = attributes
@@ -37,4 +37,4 @@ module ActiveMocker
37
37
  end
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -1,13 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  module Queries
3
-
4
4
  class Find
5
-
6
5
  def initialize(record)
7
6
  @record = record
8
7
  end
9
8
 
10
- def is_of(conditions={})
9
+ def is_of(conditions = {})
11
10
  conditions.all? do |col, match|
12
11
  if match.is_a? Enumerable
13
12
  any_match(col, match)
@@ -26,17 +25,15 @@ module ActiveMocker
26
25
  def compare(col, match)
27
26
  @record.send(col) == match
28
27
  end
29
-
30
28
  end
31
29
 
32
30
  class WhereNotChain
33
-
34
31
  def initialize(collection, parent_class)
35
32
  @collection = collection
36
33
  @parent_class = parent_class
37
34
  end
38
35
 
39
- def not(conditions={})
36
+ def not(conditions = {})
40
37
  @parent_class.call(@collection.reject do |record|
41
38
  Find.new(record).is_of(conditions)
42
39
  end)
@@ -60,16 +57,16 @@ module ActiveMocker
60
57
  #
61
58
  # Post.limit(100).delete_all
62
59
  # # => ActiveMocker::Error: delete_all doesn't support limit scope
63
- def delete_all(conditions=nil)
60
+ def delete_all(conditions = nil)
64
61
  raise ActiveMocker::Error.new("delete_all doesn't support limit scope") if from_limit?
65
62
  if conditions.nil?
66
63
  to_a.map(&:delete)
67
64
  return to_a.clear
68
65
  end
69
- where(conditions).map { |r| r.delete }.count
66
+ where(conditions).map(&:delete).count
70
67
  end
71
68
 
72
- alias_method :destroy_all, :delete_all
69
+ alias destroy_all delete_all
73
70
 
74
71
  # Returns a new relation, which is the result of filtering the current relation
75
72
  # according to the conditions in the arguments.
@@ -113,7 +110,7 @@ module ActiveMocker
113
110
  # User.where.not(name: "Jon")
114
111
  #
115
112
  # See WhereChain for more details on #not.
116
- def where(conditions=nil)
113
+ def where(conditions = nil)
117
114
  return WhereNotChain.new(all, method(:__new_relation__)) if conditions.nil?
118
115
  __new_relation__(to_a.select do |record|
119
116
  Find.new(record).is_of(conditions)
@@ -131,7 +128,7 @@ module ActiveMocker
131
128
  #
132
129
  # <tt>ActiveMocker::RecordNotFound</tt> will be raised if one or more ids are not found.
133
130
  def find(ids)
134
- raise RecordNotFound.new("Couldn't find #{self.name} without an ID") if ids.nil?
131
+ raise RecordNotFound.new("Couldn't find #{name} without an ID") if ids.nil?
135
132
  results = [*ids].map do |id|
136
133
  find_by!(id: id.to_i)
137
134
  end
@@ -200,10 +197,10 @@ module ActiveMocker
200
197
 
201
198
  # Like <tt>find_by</tt>, except that if no record is found, raises
202
199
  # an <tt>ActiveMocker::RecordNotFound</tt> error.
203
- def find_by!(conditions={})
200
+ def find_by!(conditions = {})
204
201
  result = find_by(conditions)
205
202
  if result.nil?
206
- raise RecordNotFound.new("Couldn't find #{self.name} with '#{conditions.keys.first}'=#{conditions.values.first}")
203
+ raise RecordNotFound.new("Couldn't find #{name} with '#{conditions.keys.first}'=#{conditions.values.first}")
207
204
  end
208
205
  result
209
206
  end
@@ -234,7 +231,7 @@ module ActiveMocker
234
231
  find_by(attributes) || create(attributes, &block)
235
232
  end
236
233
 
237
- alias_method :find_or_create_by!, :find_or_create_by
234
+ alias find_or_create_by! find_or_create_by
238
235
 
239
236
  # Like <tt>find_or_create_by</tt>, but calls <tt>new</tt> instead of <tt>create</tt>.
240
237
  def find_or_initialize_by(attributes, &block)
@@ -354,10 +351,9 @@ module ActiveMocker
354
351
  end
355
352
 
356
353
  def __new_relation__(collection)
357
- duped = self.dup
354
+ duped = dup
358
355
  duped.collection = collection
359
356
  duped
360
357
  end
361
-
362
358
  end
363
359
  end
@@ -1,6 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  class Records
3
-
4
4
  extend Forwardable
5
5
  def_delegators :records, :<<, :count, :length, :to_a
6
6
 
@@ -16,7 +16,7 @@ module ActiveMocker
16
16
  end
17
17
 
18
18
  def delete(record)
19
- raise RecordNotFound, 'Record has not been created.' unless records.delete(record)
19
+ raise RecordNotFound, "Record has not been created." unless records.delete(record)
20
20
  end
21
21
 
22
22
  def exists?(record)
@@ -61,4 +61,4 @@ module ActiveMocker
61
61
  record
62
62
  end
63
63
  end
64
- end
64
+ end
@@ -1,16 +1,17 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  class Relation < Collection
3
4
  include Queries
4
5
 
5
- def initialize(collection=[])
6
+ def initialize(collection = [])
6
7
  super
7
8
  @from_limit = false
8
9
  end
9
10
 
10
11
  def inspect
11
12
  entries = to_a.take(11).map!(&:inspect)
12
- entries[10] = '...' if entries.size == 11
13
- "#<#{self.class.name} [#{entries.join(', ')}]>"
13
+ entries[10] = "..." if entries.size == 11
14
+ "#<#{self.class.name} [#{entries.join(", ")}]>"
14
15
  end
15
16
 
16
17
  def from_limit?
@@ -22,6 +23,5 @@ module ActiveMocker
22
23
  def set_from_limit
23
24
  @from_limit = true
24
25
  end
25
-
26
26
  end
27
- end
27
+ end
@@ -1,6 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  class SingleRelation
3
-
4
4
  attr_reader :item
5
5
 
6
6
  def initialize(item, child_self:, foreign_key:)
@@ -9,7 +9,7 @@ module ActiveMocker
9
9
  end
10
10
 
11
11
  def assign_associations(child_self, item)
12
- [*item.class._find_associations_by_class(child_self.class.send('mocked_class'))].each do |type, relations|
12
+ [*item.class._find_associations_by_class(child_self.class.send("mocked_class"))].each do |_type, relations|
13
13
  relations.each do |relation|
14
14
  if item.send(relation).class <= Collection
15
15
  item.send(relation) << child_self
@@ -19,7 +19,5 @@ module ActiveMocker
19
19
  end
20
20
  end
21
21
  end
22
-
23
22
  end
24
23
  end
25
-
@@ -1,12 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  module TemplateMethods
3
-
4
4
  def self.included(base)
5
5
  base.extend(ClassMethods)
6
6
  end
7
7
 
8
8
  module ClassMethods
9
-
10
9
  def attributes
11
10
  HashWithIndifferentAccess.new({})
12
11
  end
@@ -24,7 +23,7 @@ module ActiveMocker
24
23
  end
25
24
 
26
25
  def mocked_class
27
- ''
26
+ ""
28
27
  end
29
28
 
30
29
  def attribute_names
@@ -32,9 +31,8 @@ module ActiveMocker
32
31
  end
33
32
 
34
33
  def primary_key
35
- ''
34
+ ""
36
35
  end
37
-
38
36
  end
39
37
  end
40
38
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveMocker
2
3
  class MockCreator
3
4
  def initialize(file:,
@@ -8,6 +9,7 @@ module ActiveMocker
8
9
  enabled_partials: nil,
9
10
  klasses_to_be_mocked:,
10
11
  mock_append_name:,
12
+ active_record_model:,
11
13
  active_record_base_klass: ActiveRecord::Base)
12
14
  @file = file
13
15
  @file_out = file_out
@@ -18,6 +20,7 @@ module ActiveMocker
18
20
  @klasses_to_be_mocked = klasses_to_be_mocked
19
21
  @active_record_base_klass = active_record_base_klass
20
22
  @mock_append_name = mock_append_name
23
+ @active_record_model = active_record_model
21
24
  @errors = []
22
25
  @completed = false
23
26
  end
@@ -61,14 +64,15 @@ module ActiveMocker
61
64
  # -- Defaults -- #
62
65
  def template_creator_default(file_out)
63
66
  TemplateCreator.new(file_out: file_out,
64
- erb_template: File.new(File.join(File.dirname(__FILE__), "mock_template.erb"), 'r'),
67
+ erb_template: File.new(File.join(File.dirname(__FILE__), "mock_template.erb"), "r"),
65
68
  binding: binding,
66
- post_process: -> (str) {
67
- ruby_code = DissociatedIntrospection::RubyCode.build_from_source(str, parse_with_comments: true)
69
+ post_process: lambda do |str|
70
+ ruby_code = DissociatedIntrospection::RubyCode.build_from_source(str,
71
+ parse_with_comments: true)
68
72
  DissociatedIntrospection::WrapInModules.new(ruby_code: ruby_code)
69
73
  .call(modules: nested_modules)
70
74
  .source_from_ast.gsub(/end\n/, "end\n\n")
71
- })
75
+ end)
72
76
  end
73
77
 
74
78
  def class_introspector_default
@@ -77,7 +81,15 @@ module ActiveMocker
77
81
 
78
82
  class << self
79
83
  def enabled_partials_default
80
- [:modules_constants, :class_methods, :attributes, :scopes, :defined_methods, :associations]
84
+ [
85
+ :modules_constants,
86
+ :class_methods,
87
+ :attributes,
88
+ :scopes,
89
+ :recreate_class_method_calls,
90
+ :defined_methods,
91
+ :associations,
92
+ ]
81
93
  end
82
94
 
83
95
  public :enabled_partials_default
@@ -99,11 +111,18 @@ module ActiveMocker
99
111
  OpenStruct.new(enabled_partials.each_with_object({}) do |p, hash|
100
112
  begin
101
113
  file = File.new(File.join(File.dirname(__FILE__), "mock_template/_#{p}.erb"))
102
- self.extend("ActiveMocker::MockCreator::#{p.to_s.camelize}".constantize)
103
- hash[p] = ERB.new(file.read, nil, '-', "_sub#{p}").result(binding)
114
+ extend("ActiveMocker::MockCreator::#{p.to_s.camelize}".constantize)
115
+ hash[p] = ERB.new(file.read, nil, "-", "_sub#{p}").result(binding)
104
116
  rescue => e
105
- errors << ErrorObject.new(class_name: class_name, original_error: e, type: :generation, level: :error, message: e.message)
106
- errors << ErrorObject.new(class_name: class_name, original_error: e, type: :erb, level: :debug, message: "Erb template: #{p} failed.\n#{file.path}")
117
+ errors << ErrorObject.new(class_name: class_name,
118
+ original_error: e, type: :generation,
119
+ level: :error,
120
+ message: e.message)
121
+ errors << ErrorObject.new(class_name: class_name,
122
+ original_error: e,
123
+ type: :erb,
124
+ level: :debug,
125
+ message: "Erb template: #{p} failed.\n#{file.path}")
107
126
  raise e
108
127
  end
109
128
  end)
@@ -119,12 +138,10 @@ module ActiveMocker
119
138
  end
120
139
  end
121
140
 
122
- def parent_class
123
- @parent_class
124
- end
141
+ attr_reader :parent_class, :active_record_model
125
142
 
126
143
  def primary_key
127
- @primary_key ||= ActiveRecordSchemaScrapper::Attribute.new(name: 'id', type: :integer)
144
+ @primary_key ||= ActiveRecordSchemaScrapper::Attribute.new(name: "id", type: :integer)
128
145
  end
129
146
 
130
147
  module ModulesConstants
@@ -139,7 +156,7 @@ module ActiveMocker
139
156
  @modules ||= begin
140
157
  {
141
158
  included: get_module_by_reference(:included_modules),
142
- extended: get_module_by_reference(:extended_modules)
159
+ extended: get_module_by_reference(:extended_modules),
143
160
  }
144
161
  end
145
162
  end
@@ -147,7 +164,28 @@ module ActiveMocker
147
164
  private
148
165
 
149
166
  def get_module_by_reference(type)
150
- reject_local_const(class_introspector.public_send(type)).map(&:referenced_name)
167
+ isolated_module_names = reject_local_const(class_introspector.public_send(type)).map(&:referenced_name)
168
+ real_module_names = get_real_module(type).map(&:name).compact
169
+ isolated_module_names.map do |isolated_name|
170
+ real_name = real_module_names.detect do |rmn|
171
+ real_parts = rmn.split("::")
172
+ total_parts_count = active_record_model.name.split("::").count + isolated_name.split("::").count
173
+ [
174
+ real_parts.include?(active_record_model.name),
175
+ real_parts.include?(isolated_name),
176
+ (total_parts_count == real_parts.count)
177
+ ].all?
178
+ end
179
+ real_name ? real_name : isolated_name
180
+ end
181
+ end
182
+
183
+ def get_real_module(type)
184
+ if type == :extended_modules
185
+ active_record_model.singleton_class.included_modules
186
+ else
187
+ active_record_model.included_modules
188
+ end
151
189
  end
152
190
 
153
191
  def reject_local_const(source)
@@ -161,9 +199,7 @@ module ActiveMocker
161
199
  def attributes
162
200
  @attribute ||= begin
163
201
  a = schema_scrapper.attributes.to_a
164
- unless a.any? { |aa| aa.name == "id" }
165
- a << primary_key
166
- end
202
+ a << primary_key unless a.any? { |aa| aa.name == "id" }
167
203
  a
168
204
  end
169
205
  end
@@ -180,7 +216,7 @@ module ActiveMocker
180
216
 
181
217
  def types_hash
182
218
  attributes.each_with_object(HashNewStyle.new) do |attr, types|
183
- types[attr.name] = "#{attr.type}"
219
+ types[attr.name] = attr.type.to_s
184
220
  end.inspect
185
221
  end
186
222
 
@@ -199,7 +235,7 @@ module ActiveMocker
199
235
  end
200
236
 
201
237
  def attribute_names
202
- attributes.map { |a| a.name }
238
+ attributes.map(&:name)
203
239
  end
204
240
 
205
241
  def abstract_class
@@ -226,8 +262,26 @@ module ActiveMocker
226
262
  end
227
263
  end
228
264
 
229
- module DefinedMethods
265
+ AliasAttributeMethod = Struct.new(:new_name, :old_name)
266
+ module RecreateClassMethodCalls
267
+ def class_method_calls
268
+ @class_method_calls ||= class_introspector
269
+ .class_macros
270
+ .select { |h| h.keys.first == :alias_attribute }
271
+ .map do |h|
272
+ a = h.values.first.first
273
+ AliasAttributeMethod.new(a[0].to_s, a[1].to_s)
274
+ end
275
+ end
276
+
277
+ def attribute_aliases
278
+ class_method_calls.each_with_object({}) do |alias_attr, hash|
279
+ hash[alias_attr.new_name] = alias_attr.old_name
280
+ end
281
+ end
282
+ end
230
283
 
284
+ module DefinedMethods
231
285
  def instance_methods
232
286
  class_introspector
233
287
  .get_class
@@ -247,7 +301,9 @@ module ActiveMocker
247
301
  private
248
302
 
249
303
  def create_method(m, type)
250
- Method.new(m, ReverseParameters.new(class_introspector.get_class.send(type, m).parameters, blocks_as_values: true))
304
+ Method.new(m,
305
+ ReverseParameters.new(class_introspector.get_class.send(type, m).parameters,
306
+ blocks_as_values: true))
251
307
  end
252
308
  end
253
309