active_mocker 2.1.3 → 2.2.0

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