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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +5 -0
- data/lib/active_mocker.rb +7 -6
- data/lib/active_mocker/config.rb +6 -8
- data/lib/active_mocker/deprecated_components/mock_abilities.rb +6 -10
- data/lib/active_mocker/deprecated_components/rspec.rb +2 -1
- data/lib/active_mocker/display_errors.rb +3 -2
- data/lib/active_mocker/error_object.rb +13 -13
- data/lib/active_mocker/file_path_to_ruby_class.rb +2 -3
- data/lib/active_mocker/file_writer.rb +125 -0
- data/lib/active_mocker/generate.rb +56 -71
- data/lib/active_mocker/hash_new_style.rb +2 -1
- data/lib/active_mocker/loaded_mocks.rb +9 -11
- data/lib/active_mocker/mock.rb +28 -26
- data/lib/active_mocker/mock/alias_attribute.rb +19 -0
- data/lib/active_mocker/mock/association.rb +2 -1
- data/lib/active_mocker/mock/base.rb +22 -20
- data/lib/active_mocker/mock/belongs_to.rb +1 -1
- data/lib/active_mocker/mock/collection.rb +6 -6
- data/lib/active_mocker/mock/do_nothing_active_record_methods.rb +4 -7
- data/lib/active_mocker/mock/exceptions.rb +1 -4
- data/lib/active_mocker/mock/has_and_belongs_to_many.rb +2 -1
- data/lib/active_mocker/mock/has_many.rb +6 -7
- data/lib/active_mocker/mock/has_one.rb +2 -2
- data/lib/active_mocker/mock/hash_process.rb +2 -2
- data/lib/active_mocker/mock/mock_relation.rb +1 -0
- data/lib/active_mocker/mock/object_inspect.rb +2 -2
- data/lib/active_mocker/mock/queries.rb +12 -16
- data/lib/active_mocker/mock/records.rb +3 -3
- data/lib/active_mocker/mock/relation.rb +5 -5
- data/lib/active_mocker/mock/single_relation.rb +2 -4
- data/lib/active_mocker/mock/template_methods.rb +3 -5
- data/lib/active_mocker/mock_creator.rb +78 -22
- data/lib/active_mocker/mock_template.erb +1 -0
- data/lib/active_mocker/mock_template/_recreate_class_method_calls.erb +12 -0
- data/lib/active_mocker/null_progress.rb +2 -2
- data/lib/active_mocker/parent_class.rb +4 -2
- data/lib/active_mocker/progress.rb +6 -8
- data/lib/active_mocker/public_methods.rb +3 -2
- data/lib/active_mocker/railtie.rb +3 -3
- data/lib/active_mocker/rspec.rb +2 -1
- data/lib/active_mocker/rspec_helper.rb +4 -3
- data/lib/active_mocker/task.rake +9 -10
- data/lib/active_mocker/template_creator.rb +5 -5
- data/lib/active_mocker/version.rb +2 -1
- 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))
|
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,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
|
66
|
+
where(conditions).map(&:delete).count
|
70
67
|
end
|
71
68
|
|
72
|
-
|
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 #{
|
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 #{
|
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
|
-
|
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 =
|
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,
|
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] =
|
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(
|
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"),
|
67
|
+
erb_template: File.new(File.join(File.dirname(__FILE__), "mock_template.erb"), "r"),
|
65
68
|
binding: binding,
|
66
|
-
post_process:
|
67
|
-
ruby_code = DissociatedIntrospection::RubyCode.build_from_source(str,
|
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
|
-
[
|
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
|
-
|
103
|
-
hash[p] = ERB.new(file.read, nil,
|
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:
|
106
|
-
|
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
|
-
|
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:
|
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] =
|
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
|
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
|
-
|
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,
|
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
|
|