active_mocker 1.3.2 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.md +136 -24
- data/Rakefile +8 -2
- data/active_mocker.gemspec +3 -3
- data/lib/active_mock/association.rb +7 -0
- data/lib/active_mock/base.rb +250 -0
- data/lib/active_mock/collection.rb +52 -0
- data/lib/active_mock/creators.rb +25 -0
- data/lib/active_mock/do_nothing_active_record_methods.rb +51 -0
- data/lib/active_mock/has_and_belongs_to_many.rb +7 -0
- data/lib/active_mock/has_many.rb +54 -0
- data/lib/active_mock/next_id.rb +16 -0
- data/lib/active_mock/object_inspect.rb +39 -0
- data/lib/{active_mocker/collection → active_mock}/queries.rb +26 -19
- data/lib/active_mock/records.rb +81 -0
- data/lib/active_mock/relation.rb +8 -0
- data/lib/active_mocker.rb +3 -1
- data/lib/active_mocker/active_mock.rb +26 -0
- data/lib/active_mocker/active_record.rb +18 -0
- data/lib/active_mocker/active_record/relationships.rb +57 -6
- data/lib/active_mocker/active_record/schema.rb +1 -1
- data/lib/active_mocker/active_record/scope.rb +1 -1
- data/lib/active_mocker/active_record/unknown_class_method.rb +1 -1
- data/lib/active_mocker/active_record/unknown_module.rb +10 -9
- data/lib/active_mocker/db_to_ruby_type.rb +26 -0
- data/lib/active_mocker/field.rb +16 -8
- data/lib/active_mocker/generate.rb +19 -174
- data/lib/active_mocker/loaded_mocks.rb +48 -8
- data/lib/active_mocker/logger.rb +2 -0
- data/lib/active_mocker/mock_template.erb +123 -53
- data/lib/active_mocker/model_reader.rb +42 -13
- data/lib/active_mocker/model_schema.rb +279 -0
- data/lib/active_mocker/model_schema/generate.rb +175 -0
- data/lib/active_mocker/reparameterize.rb +23 -3
- data/lib/active_mocker/table.rb +2 -2
- data/lib/active_mocker/version.rb +1 -1
- data/sample_app_rails_4/Gemfile +1 -1
- data/sample_app_rails_4/app/models/micropost.rb +13 -1
- data/sample_app_rails_4/db/schema.rb +1 -1
- data/sample_app_rails_4/spec/compare_mocker_and_record_spec.rb +194 -7
- data/sample_app_rails_4/spec/micropost_mock_spec.rb +145 -0
- data/sample_app_rails_4/spec/mocks/micropost_mock.rb +81 -55
- data/sample_app_rails_4/spec/mocks/relationship_mock.rb +85 -54
- data/sample_app_rails_4/spec/mocks/user_mock.rb +71 -72
- data/sample_app_rails_4/spec/reload_spec.rb +1 -1
- data/sample_app_rails_4/spec/user_mock_spec.rb +25 -7
- data/spec/lib/acitve_mock/queriable_spec.rb +207 -0
- data/spec/lib/active_mocker/db_to_ruby_type_spec.rb +124 -0
- data/spec/lib/active_mocker/loaded_mocks_spec.rb +167 -0
- data/spec/lib/active_mocker/logger_spec.rb +32 -0
- data/spec/lib/active_mocker/model_reader_spec.rb +79 -28
- data/spec/lib/active_mocker/model_schema/generate_spec.rb +111 -0
- data/spec/lib/active_mocker/model_schema_spec.rb +145 -0
- data/spec/lib/model.rb +2 -1
- data/spec/lib/reparameterize_spec.rb +202 -0
- data/spec/unit_logger.rb +2 -2
- metadata +55 -35
- data/lib/active_hash/ar_api.rb +0 -77
- data/lib/active_hash/init.rb +0 -32
- data/lib/active_mocker/collection/association.rb +0 -12
- data/lib/active_mocker/collection/base.rb +0 -65
- data/lib/active_mocker/collection/relation.rb +0 -11
- data/lib/active_mocker/mock_class_methods.rb +0 -92
- data/lib/active_mocker/mock_instance_methods.rb +0 -84
- data/lib/active_mocker/mock_requires.rb +0 -10
- data/spec/lib/active_mocker/collection.rb +0 -94
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'active_support/core_ext'
|
5
|
+
rescue
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'active_model'
|
10
|
+
require 'active_model/naming'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
require 'active_mocker/logger'
|
14
|
+
require 'active_mock/queries'
|
15
|
+
require 'active_mock/collection'
|
16
|
+
require 'active_mock/association'
|
17
|
+
require 'active_mock/has_many'
|
18
|
+
require 'active_mock/has_and_belongs_to_many'
|
19
|
+
require 'active_mocker/loaded_mocks'
|
20
|
+
require 'active_mock/do_nothing_active_record_methods'
|
21
|
+
require 'active_mock/next_id'
|
22
|
+
require 'active_mock/creators'
|
23
|
+
require 'active_mock/records'
|
24
|
+
require 'active_mock/base'
|
25
|
+
require 'virtus'
|
26
|
+
require 'active_mock/object_inspect'
|
@@ -14,6 +14,24 @@ module ActiveMocker
|
|
14
14
|
extend UnknownModule
|
15
15
|
extend ConstMissing
|
16
16
|
|
17
|
+
def self.table_name=(table_name)
|
18
|
+
@table_name = table_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.table_name
|
22
|
+
@table_name ||= nil
|
23
|
+
@table_name
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.primary_key=(primary_key)
|
27
|
+
@primary_key = primary_key
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.primary_key
|
31
|
+
@primary_key ||= nil
|
32
|
+
@primary_key
|
33
|
+
end
|
34
|
+
|
17
35
|
def self.const_missing(name)
|
18
36
|
# Logger_.debug "ActiveMocker :: Can't can't find Constant #{name} from class #{}."
|
19
37
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'ostruct'
|
2
|
-
|
2
|
+
require 'active_support/core_ext/string'
|
3
3
|
module Relationships
|
4
4
|
|
5
5
|
def self.included(base)
|
@@ -25,26 +25,77 @@ module Relationships
|
|
25
25
|
has_and_belongs_to_many + has_many
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
class Relationship
|
29
|
+
attr_reader :name
|
30
|
+
def initialize(name, options={})
|
31
|
+
@name = name
|
32
|
+
@options = options.reduce(HashWithIndifferentAccess.new, :merge)
|
33
|
+
end
|
34
|
+
|
35
|
+
def options
|
36
|
+
@options.symbolize_keys
|
37
|
+
end
|
38
|
+
|
39
|
+
def through
|
40
|
+
options[:through]
|
41
|
+
end
|
42
|
+
|
43
|
+
def class_name
|
44
|
+
options[:class_name] || name.to_s.camelize.singularize
|
45
|
+
end
|
46
|
+
|
47
|
+
def foreign_key
|
48
|
+
options[:foreign_key] || name.to_s.foreign_key
|
49
|
+
end
|
50
|
+
|
51
|
+
def join_table
|
52
|
+
options[:join_table]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class HasMany < Relationship
|
57
|
+
|
58
|
+
attr_reader :klass_name
|
59
|
+
|
60
|
+
def initialize(name, klass_name, options={})
|
61
|
+
@klass_name = klass_name
|
62
|
+
super(name, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def foreign_key
|
66
|
+
options[:foreign_key] || klass_name.to_s.foreign_key
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
29
70
|
|
30
71
|
def has_many(*args)
|
31
72
|
@has_many ||= []
|
32
|
-
@has_many.push
|
73
|
+
@has_many.push HasMany.new(args.shift, self.name, args)
|
74
|
+
end
|
75
|
+
|
76
|
+
class HasOne < Relationship
|
33
77
|
end
|
34
78
|
|
35
79
|
def has_one(*args)
|
36
80
|
@has_one ||= []
|
37
|
-
@has_one.push
|
81
|
+
@has_one.push HasOne.new(args.shift, args)
|
82
|
+
end
|
83
|
+
|
84
|
+
class BelongsTo < Relationship
|
38
85
|
end
|
39
86
|
|
40
87
|
def belongs_to(*args)
|
41
88
|
@belongs_to ||= []
|
42
|
-
@belongs_to.push
|
89
|
+
@belongs_to.push BelongsTo.new(args.shift, args)
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
class HasAndBelongsToMany < Relationship
|
43
94
|
end
|
44
95
|
|
45
96
|
def has_and_belongs_to_many(*args)
|
46
97
|
@has_and_belongs_to_many ||= []
|
47
|
-
@has_and_belongs_to_many.push
|
98
|
+
@has_and_belongs_to_many.push HasAndBelongsToMany.new(args.shift, args)
|
48
99
|
end
|
49
100
|
|
50
101
|
end
|
@@ -49,7 +49,7 @@ module ActiveMocker
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def create_table(name, options={}, &block)
|
52
|
-
tables << ActiveMocker::Table.new(name, CreateTable.new.instance_eval(&block))
|
52
|
+
tables << ActiveMocker::Table.new(name, options[:id], CreateTable.new.instance_eval(&block))
|
53
53
|
end
|
54
54
|
|
55
55
|
def method_missing(meth, *args)
|
@@ -2,7 +2,7 @@ module Scope
|
|
2
2
|
|
3
3
|
def scope(method_name, proc)
|
4
4
|
singleton_class.class_eval do
|
5
|
-
params = Reparameterize.call(proc.parameters)
|
5
|
+
params = ActiveMocker::Reparameterize.call(proc.parameters)
|
6
6
|
block = eval("lambda { |#{params}| }")
|
7
7
|
define_method(method_name, block)
|
8
8
|
end
|
@@ -3,7 +3,7 @@ module ActiveMocker
|
|
3
3
|
module UnknownClassMethod
|
4
4
|
|
5
5
|
def method_missing(meth, *args)
|
6
|
-
Logger.debug "ActiveMocker :: #{meth} called from class #{self.name} is unknown and will not be available in mock
|
6
|
+
Logger.debug "ActiveMocker :: DEBUG :: #{meth} called from class #{self.name} is unknown and will not be available in mock.\n"
|
7
7
|
end
|
8
8
|
|
9
9
|
end
|
@@ -3,20 +3,21 @@ module ActiveMocker
|
|
3
3
|
module UnknownModule
|
4
4
|
|
5
5
|
def include(_module)
|
6
|
-
|
7
|
-
super _module
|
8
|
-
rescue => e
|
9
|
-
Logger.debug e
|
10
|
-
Logger.debug "ActiveMocker :: Can't include module #{_module} from class #{self.name}.\n #{caller}"
|
11
|
-
|
12
|
-
end
|
6
|
+
try_and_log('include', _module)
|
13
7
|
end
|
14
8
|
|
15
9
|
def extend(_module)
|
10
|
+
try_and_log('extend', _module)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def try_and_log(type, name)
|
16
16
|
begin
|
17
17
|
super _module
|
18
|
-
rescue
|
19
|
-
Logger.debug "ActiveMocker :: Can't
|
18
|
+
rescue => e
|
19
|
+
Logger.debug "ActiveMocker :: Debug :: Can't #{type} module #{name} from class #{self.name}.\n\t\t\t\t\t\t\t\t#{caller}\n"
|
20
|
+
Logger.debug "\t\t\t\t\t\t\t\t#{e}"
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveMocker
|
2
|
+
class DBToRubyType
|
3
|
+
|
4
|
+
def self.call(type)
|
5
|
+
case type
|
6
|
+
when :integer
|
7
|
+
Fixnum
|
8
|
+
when :float
|
9
|
+
Float
|
10
|
+
when :decimal
|
11
|
+
BigDecimal
|
12
|
+
when :timestamp, :time
|
13
|
+
Time
|
14
|
+
when :datetime
|
15
|
+
DateTime
|
16
|
+
when :date
|
17
|
+
Date
|
18
|
+
when :text, :string, :binary
|
19
|
+
String
|
20
|
+
when :boolean
|
21
|
+
Axiom::Types::Boolean
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/active_mocker/field.rb
CHANGED
@@ -7,9 +7,12 @@ module ActiveMocker
|
|
7
7
|
def initialize(name, type, options)
|
8
8
|
@name = name
|
9
9
|
@type = type
|
10
|
-
@
|
11
|
-
options
|
12
|
-
|
10
|
+
@primary_key
|
11
|
+
@options = options.first || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def primary_key
|
15
|
+
@primary_key
|
13
16
|
end
|
14
17
|
|
15
18
|
def to_h
|
@@ -18,11 +21,16 @@ module ActiveMocker
|
|
18
21
|
|
19
22
|
alias_method :to_hash, :to_h
|
20
23
|
|
21
|
-
def
|
22
|
-
options
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def default
|
25
|
+
options[:default]
|
26
|
+
end
|
27
|
+
|
28
|
+
def precision
|
29
|
+
options[:precision]
|
30
|
+
end
|
31
|
+
|
32
|
+
def scale
|
33
|
+
options[:scale]
|
26
34
|
end
|
27
35
|
|
28
36
|
end
|
@@ -31,192 +31,37 @@ class Generate
|
|
31
31
|
"#{model_name}Mock".constantize
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
|
36
|
-
@model_definition_table = table
|
37
|
-
@model_definition = ModelReader.new({model_dir: model_dir, file_reader: model_file_reader}).parse(table_to_model_file(table))
|
38
|
-
end
|
39
|
-
|
40
|
-
def table_to_model_file(table)
|
41
|
-
table.singularize
|
42
|
-
end
|
43
|
-
|
44
|
-
def table_to_class_name(table)
|
45
|
-
table.camelize.singularize
|
46
|
-
end
|
47
|
-
|
48
|
-
def schema_reader
|
49
|
-
SchemaReader.new({schema_file: schema_file, file_reader: schema_file_reader}).search(nil)
|
50
|
-
end
|
51
|
-
|
52
|
-
def tables
|
53
|
-
schema_reader
|
34
|
+
def generate_model_schema
|
35
|
+
ActiveMocker::ModelSchema::Generate.new(schema_file: schema_file, models_dir: model_dir, logger: logger).run
|
54
36
|
end
|
55
37
|
|
56
38
|
def create_template
|
57
39
|
mocks_created = 0
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
mock_template.attribute_names = table.column_names
|
64
|
-
mock_template.attributes = field_type_to_class(table.fields)
|
65
|
-
mock_template.default_attributes =default_attr_values(table.fields)
|
66
|
-
|
67
|
-
# Model associations
|
68
|
-
mock_template.single_associations = model_definition(table.name).single_relationships
|
69
|
-
mock_template.collection_associations = model_definition(table.name).collections
|
70
|
-
mock_template.association_names = [*model_definition(table.name).single_relationships, *model_definition(table.name).collections]
|
71
|
-
mock_template.associations = associations(mock_template.association_names)
|
72
|
-
|
73
|
-
# Model Methods
|
74
|
-
mock_template.instance_methods = instance_methods(table.name).methods
|
75
|
-
mock_template.model_instance_methods = instance_methods(table.name).model_instance_methods
|
76
|
-
mock_template.class_methods = class_methods(table.name).methods
|
77
|
-
mock_template.model_class_methods = class_methods(table.name).model_class_methods
|
78
|
-
|
79
|
-
klass_str = mock_template.render( File.open(File.join(File.expand_path('../', __FILE__), 'mock_template.erb')).read)
|
40
|
+
models = generate_model_schema
|
41
|
+
models.each do |model|
|
42
|
+
# begin
|
43
|
+
klass_str = ''
|
44
|
+
klass_str = model.render(File.open(File.join(File.expand_path('../', __FILE__), 'mock_template.erb')).read, mock_append_name)
|
80
45
|
FileUtils::mkdir_p mock_dir unless File.directory? mock_dir
|
81
|
-
File.open(File.join(mock_dir,"#{
|
82
|
-
logger.info "saving mock #{
|
83
|
-
|
84
|
-
rescue Exception => exception
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
46
|
+
File.open(File.join(mock_dir,"#{model.table_name.singularize}_mock.rb"), 'w').write(klass_str)
|
47
|
+
logger.info "saving mock #{model.class_name} to #{mock_dir}"
|
48
|
+
|
49
|
+
# rescue Exception => exception
|
50
|
+
# logger.debug $!.backtrace
|
51
|
+
# logger.debug exception
|
52
|
+
# logger.info "failed to load #{model} model"
|
53
|
+
# next
|
54
|
+
# end
|
90
55
|
mocks_created += 1
|
91
56
|
|
92
57
|
end
|
93
|
-
logger.info "Generated #{mocks_created} of #{
|
94
|
-
end
|
95
|
-
|
96
|
-
def field_type_to_class(fields)
|
97
|
-
fields.map do |field|
|
98
|
-
field.type = case field.type
|
99
|
-
when :integer then
|
100
|
-
Fixnum
|
101
|
-
when :float then
|
102
|
-
Float
|
103
|
-
when :decimal then
|
104
|
-
BigDecimal
|
105
|
-
when :timestamp, :time then
|
106
|
-
Time
|
107
|
-
when :datetime then
|
108
|
-
DateTime
|
109
|
-
when :date then
|
110
|
-
Date
|
111
|
-
when :text, :string, :binary then
|
112
|
-
String
|
113
|
-
when :boolean then
|
114
|
-
::Virtus::Attribute::Boolean
|
115
|
-
end
|
116
|
-
field
|
117
|
-
end
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
def mock_class_name(table_name)
|
122
|
-
"#{table_to_class_name(table_name)}Mock"
|
123
|
-
end
|
124
|
-
|
125
|
-
def associations(names)
|
126
|
-
hash = {}
|
127
|
-
names.each do |name|
|
128
|
-
hash[name] = nil
|
129
|
-
end
|
130
|
-
hash
|
131
|
-
end
|
132
|
-
|
133
|
-
def default_attr_values(fields)
|
134
|
-
attributes = {}
|
135
|
-
fields.each do |f|
|
136
|
-
if f.options[:default].nil?
|
137
|
-
attributes[f.name] = nil
|
138
|
-
else
|
139
|
-
value = f.default.class == String ? f.default : f.default
|
140
|
-
attributes[f.name] = value
|
141
|
-
end
|
142
|
-
end
|
143
|
-
attributes
|
144
|
-
end
|
145
|
-
|
146
|
-
def instance_methods(table_name)
|
147
|
-
model_instance_methods = []
|
148
|
-
instance_methods = Methods.new
|
149
|
-
instance_methods.methods = model_definition(table_name).instance_methods_with_arguments.map do |method|
|
150
|
-
m = method.keys.first.to_s
|
151
|
-
if m == :attributes
|
152
|
-
logger.warn "ActiveMocker Depends on the #attributes method. It will not be redefined for the model."
|
153
|
-
next
|
154
|
-
end
|
155
|
-
params = Reparameterize.call(method.values.first)
|
156
|
-
params_pass = Reparameterize.call(method.values.first, true)
|
157
|
-
|
158
|
-
instance_method = Method.new
|
159
|
-
instance_method.method = m
|
160
|
-
instance_method.params = params
|
161
|
-
|
162
|
-
instance_method.params_pass = params_pass
|
163
|
-
model_instance_methods << m
|
164
|
-
instance_method
|
165
|
-
end
|
166
|
-
instance_methods.model_instance_methods = {}
|
167
|
-
model_instance_methods.each{|meth| instance_methods.model_instance_methods[meth] = :not_implemented }
|
168
|
-
instance_methods
|
169
|
-
end
|
170
|
-
|
171
|
-
def class_methods(table_name)
|
172
|
-
model_class_methods = []
|
173
|
-
class_methods = Methods.new
|
174
|
-
class_methods.methods = model_definition(table_name).class_methods_with_arguments.map do |method|
|
175
|
-
m = method.keys.first.to_s
|
176
|
-
params = Reparameterize.call(method.values.first)
|
177
|
-
params_pass = Reparameterize.call(method.values.first, true)
|
178
|
-
|
179
|
-
class_method = Method.new
|
180
|
-
class_method.method = m
|
181
|
-
class_method.params = params
|
182
|
-
class_method.params_pass = params_pass
|
183
|
-
model_class_methods << m
|
184
|
-
class_method
|
185
|
-
end
|
186
|
-
class_methods.model_class_methods = {}
|
187
|
-
model_class_methods.each { |meth| class_methods.model_class_methods[meth] = :not_implemented }
|
188
|
-
class_methods
|
189
|
-
end
|
190
|
-
|
191
|
-
class Method
|
192
|
-
attr_accessor :method, :params, :params_pass
|
58
|
+
logger.info "Generated #{mocks_created} of #{models.count} mocks"
|
193
59
|
end
|
194
60
|
|
195
|
-
|
196
|
-
|
61
|
+
def mock_append_name
|
62
|
+
'Mock'
|
197
63
|
end
|
198
64
|
|
199
|
-
class MockTemplate
|
200
|
-
attr_accessor :attributes,
|
201
|
-
:single_associations,
|
202
|
-
:collection_associations,
|
203
|
-
:class_name,
|
204
|
-
:association_names,
|
205
|
-
:attribute_names,
|
206
|
-
:column_names,
|
207
|
-
:instance_methods,
|
208
|
-
:class_methods,
|
209
|
-
:model_instance_methods,
|
210
|
-
:model_class_methods,
|
211
|
-
:default_attributes,
|
212
|
-
:associations
|
213
|
-
|
214
|
-
def render(template)
|
215
|
-
ERB.new(template, nil, '-').result(binding)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
|
220
65
|
end
|
221
66
|
end
|
222
67
|
|