active_mocker 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +7 -0
- data/active_mocker.gemspec +30 -0
- data/lib/active_mocker.rb +5 -0
- data/lib/active_mocker/active_record.rb +12 -0
- data/lib/active_mocker/active_record/relationships.rb +34 -0
- data/lib/active_mocker/active_record/schema.rb +81 -0
- data/lib/active_mocker/active_record/scope.rb +12 -0
- data/lib/active_mocker/base.rb +170 -0
- data/lib/active_mocker/field.rb +28 -0
- data/lib/active_mocker/model_reader.rb +63 -0
- data/lib/active_mocker/reparameterize.rb +21 -0
- data/lib/active_mocker/schema_reader.rb +46 -0
- data/lib/active_mocker/table.rb +22 -0
- data/lib/active_mocker/version.rb +3 -0
- data/lib/file_reader.rb +7 -0
- data/lib/string_reader.rb +9 -0
- data/spec/lib/active_mocker/active_record/schema_spec.rb +2721 -0
- data/spec/lib/active_mocker/base_spec.rb +220 -0
- data/spec/lib/active_mocker/model_reader_spec.rb +126 -0
- data/spec/lib/active_mocker/schema_reader_spec.rb +124 -0
- data/spec/lib/model.rb +28 -0
- data/spec/lib/person.rb +9 -0
- data/spec/lib/schema.rb +40 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a57ab19178452d40493f706844efc26d8381d0b1
|
4
|
+
data.tar.gz: 360196e9eccecb12fef06ca111e002bfdd1cb5a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ff22e9d0e5bef978329f85385e6865dcce9803a10a703de790ce2682f7715efda58b017007a05b4ab4e0d3ac7d24a2fb9c6255d078d9a9e974ca04f0f3029f16
|
7
|
+
data.tar.gz: 6b94c9d8b9025619a45f8991cb7592a5c43dd44258822405726cbfcdffc4730eaddbd94687e02842cb5ed219c7f08d8136ad501dd771820c30748f6aa5e61c7e
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Dustin Zeisler
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# ActiveMocker
|
2
|
+
[![Build Status](https://travis-ci.org/zeisler/active_mocker.png?branch=master)](https://travis-ci.org/zeisler/active_mocker)
|
3
|
+
Create mocks from active record models without loading rails or running a datebase
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'active_mocker'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install active_mocker
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( http://github.com/<my-github-username>/active_mocker/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_mocker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "active_mocker"
|
8
|
+
spec.version = ActiveMocker::VERSION
|
9
|
+
spec.authors = ["Dustin Zeisler"]
|
10
|
+
spec.email = ["dustin@zive.me"]
|
11
|
+
spec.summary = %q{Create mocks from active record models without loading rails or running a database}
|
12
|
+
spec.description = %q{Create mocks from active record models without loading rails or running a database. The Mocks methods have the same arguments as the AR model and if they change you get a error in your test.}
|
13
|
+
spec.homepage = "https://github.com/zeisler/active_mocker"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake", "~>10.1"
|
23
|
+
spec.add_development_dependency "rspec", "~>2.14"
|
24
|
+
spec.add_development_dependency "i18n", "~>0.6"
|
25
|
+
spec.add_development_dependency "activesupport", "~>4.0"
|
26
|
+
|
27
|
+
#spec.add_development_dependency "debase", "~>0.0"
|
28
|
+
#spec.add_development_dependency "ruby-debug-ide", "~>0.4"
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift File.expand_path('../../', __FILE__)
|
2
|
+
require 'active_mocker/active_record/scope'
|
3
|
+
require 'active_mocker/active_record/relationships'
|
4
|
+
|
5
|
+
module ActiveMocker
|
6
|
+
module ActiveRecord
|
7
|
+
class Base
|
8
|
+
extend Scope
|
9
|
+
extend Relationships
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Relationships
|
4
|
+
|
5
|
+
def relationships
|
6
|
+
OpenStruct.new({has_many: @has_many ||= [],
|
7
|
+
has_one: @has_one ||= [],
|
8
|
+
belongs_to: @belongs_to ||= [],
|
9
|
+
has_and_belongs_to_many: @has_and_belongs_to_many ||= []})
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def has_many(*args)
|
15
|
+
@has_many ||= []
|
16
|
+
@has_many.push args
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_one(*args)
|
20
|
+
@has_one ||= []
|
21
|
+
@has_one.push args
|
22
|
+
end
|
23
|
+
|
24
|
+
def belongs_to(*args)
|
25
|
+
@belongs_to ||= []
|
26
|
+
@belongs_to.push args
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_and_belongs_to_many(*args)
|
30
|
+
@has_and_belongs_to_many ||= []
|
31
|
+
@has_and_belongs_to_many.push args
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ActiveMocker
|
2
|
+
module ActiveRecord
|
3
|
+
|
4
|
+
class Schema
|
5
|
+
|
6
|
+
def self.define(version: version, &block)
|
7
|
+
search_result = search_cache(@table_search)
|
8
|
+
search_result unless search_result.nil?
|
9
|
+
schema = parse
|
10
|
+
schema.instance_eval(&block)
|
11
|
+
add_to_cache schema.tables.first
|
12
|
+
schema.tables.first
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.parse
|
16
|
+
SchemaParser.new(@table_search)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.add_to_cache(table)
|
20
|
+
@@tables_cache ||= []
|
21
|
+
@@tables_cache << table unless table.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.search_cache(table_name)
|
25
|
+
@@tables_cache ||= []
|
26
|
+
@@tables_cache.find do |h|
|
27
|
+
h.name == table_name
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.clear_cache
|
32
|
+
@@tables_cache = []
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.search(table_name)
|
36
|
+
@table_search = table_name
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class SchemaParser
|
42
|
+
|
43
|
+
attr_reader :tables, :table_search
|
44
|
+
|
45
|
+
def initialize(table_search)
|
46
|
+
@table_search = table_search
|
47
|
+
@tables = []
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_table(name, options={}, &block)
|
52
|
+
tables << ActiveMocker::Table.new(name, CreateTable.new.instance_eval(&block)) if name == table_search
|
53
|
+
end
|
54
|
+
|
55
|
+
def method_missing(meth, *args)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class CreateTable
|
62
|
+
|
63
|
+
attr_reader :fields
|
64
|
+
|
65
|
+
def initialize
|
66
|
+
@fields = []
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_missing(meth, *args)
|
70
|
+
base_field meth, args
|
71
|
+
end
|
72
|
+
|
73
|
+
def base_field(type, args)
|
74
|
+
fields << Field.new(name: args.shift, type: type, options: args)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module ActiveMocker
|
2
|
+
|
3
|
+
#TODO DRY up method creation
|
4
|
+
#TODO have instance variable array for instance method
|
5
|
+
#TODO have class variable array for class method
|
6
|
+
#TODO enable support for active_hash as base class
|
7
|
+
#TODO work on options interface
|
8
|
+
|
9
|
+
class Base
|
10
|
+
|
11
|
+
attr_reader :model_name,
|
12
|
+
:model_options,
|
13
|
+
:options_schema,
|
14
|
+
:mass_assignment,
|
15
|
+
:model_relationships,
|
16
|
+
:schema_attributes,
|
17
|
+
:model_methods
|
18
|
+
|
19
|
+
def initialize(options={})
|
20
|
+
@schema_attributes = options.fetch(:schema_attributes, true)
|
21
|
+
@model_relationships = options.fetch(:model_relationships, true)
|
22
|
+
@model_methods = options.fetch(:model_methods, true)
|
23
|
+
@mass_assignment = options.fetch(:mass_assignment, true)
|
24
|
+
@model_options = options[:model]
|
25
|
+
@options_schema = options[:schema]
|
26
|
+
end
|
27
|
+
|
28
|
+
def mock(model_name)
|
29
|
+
@model_name = model_name
|
30
|
+
mock_class
|
31
|
+
end
|
32
|
+
|
33
|
+
def model_definition
|
34
|
+
return @model_definition unless @model_definition.nil?
|
35
|
+
@model_definition = ModelReader.new(model_options).parse(model_file_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def model_file_name
|
39
|
+
model_name.tableize.singularize
|
40
|
+
end
|
41
|
+
|
42
|
+
def table_definition
|
43
|
+
table_name = model_name.tableize
|
44
|
+
table = SchemaReader.new(options_schema).search(table_name)
|
45
|
+
raise "#{table_name} table not found." if table.nil?
|
46
|
+
return table
|
47
|
+
end
|
48
|
+
|
49
|
+
def mock_class
|
50
|
+
add_method_mock_of
|
51
|
+
add_instance_methods if model_methods
|
52
|
+
add_mock_instance_method if model_methods
|
53
|
+
add_relationships if model_relationships
|
54
|
+
add_class_methods if model_methods
|
55
|
+
add_column_names_method if schema_attributes
|
56
|
+
add_table_attributes if schema_attributes
|
57
|
+
create_initializer if mass_assignment
|
58
|
+
return @klass
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_initializer
|
62
|
+
klass = create_klass
|
63
|
+
klass.instance_eval do
|
64
|
+
define_method('initialize') do |options={}|
|
65
|
+
options.each {|method, value| send("#{method}=", value)}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_relationships
|
71
|
+
klass = create_klass
|
72
|
+
model_definition.relationships.each do |m|
|
73
|
+
klass.instance_variable_set("@#{m}", nil)
|
74
|
+
klass.class_eval { attr_accessor m }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_method_mock_of
|
79
|
+
klass = create_klass
|
80
|
+
klass.class_variable_set(:@@model_name, model_name)
|
81
|
+
klass.instance_eval do
|
82
|
+
define_method(:mock_of) {klass.class_variable_get :@@model_name}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def add_table_attributes
|
87
|
+
klass = create_klass
|
88
|
+
table_definition.column_names.each do |m|
|
89
|
+
klass.instance_variable_set("@#{m}", nil)
|
90
|
+
klass.class_eval { attr_accessor m }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_instance_methods
|
95
|
+
klass = create_klass
|
96
|
+
model_definition.instance_methods_with_arguments.each do |method|
|
97
|
+
m = method.keys.first
|
98
|
+
params = Reparameterize.call(method.values.first)
|
99
|
+
params_pass = Reparameterize.call(method.values.first, true)
|
100
|
+
klass.instance_variable_set("@#{m}", eval_lambda(params, %Q[raise "##{m} is not Implemented for Class: #{klass.name}"]))
|
101
|
+
block = eval_lambda(params, %Q[ self.class.instance_variable_get("@#{m}").call(#{params_pass})])
|
102
|
+
klass.instance_eval do
|
103
|
+
define_method(m, block)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def eval_lambda(arguments, block)
|
109
|
+
eval(%Q[ ->(#{arguments}){ #{block} }])
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_mock_instance_method
|
113
|
+
klass = create_klass
|
114
|
+
klass.singleton_class.class_eval do
|
115
|
+
define_method(:mock_instance_method) do |method, &block|
|
116
|
+
klass.instance_variable_set("@#{method.to_s}", block)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_class_methods
|
122
|
+
klass = create_klass
|
123
|
+
model_definition.class_methods.each do |m|
|
124
|
+
klass.singleton_class.class_eval do
|
125
|
+
define_method(m) do
|
126
|
+
raise "::#{m} is not Implemented for Class: #{klass.name}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def add_column_names_method
|
133
|
+
klass = create_klass
|
134
|
+
table = table_definition
|
135
|
+
klass.singleton_class.class_eval do
|
136
|
+
define_method(:column_names) do
|
137
|
+
table.column_names
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def create_klass
|
143
|
+
@klass ||= const_class
|
144
|
+
end
|
145
|
+
|
146
|
+
def const_class
|
147
|
+
remove_const(mock_class_name) if class_exists? mock_class_name
|
148
|
+
return Object.const_set(mock_class_name, Class.new) unless Object.const_defined?(mock_class_name)
|
149
|
+
return Object.const_get(mock_class_name, false)
|
150
|
+
end
|
151
|
+
|
152
|
+
def remove_const(class_name)
|
153
|
+
Object.send(:remove_const, class_name)
|
154
|
+
end
|
155
|
+
|
156
|
+
def class_exists?(class_name)
|
157
|
+
klass = Module.const_get(class_name)
|
158
|
+
return klass.is_a?(Class)
|
159
|
+
rescue NameError
|
160
|
+
return false
|
161
|
+
end
|
162
|
+
|
163
|
+
def mock_class_name
|
164
|
+
"#{model_name}Mock"
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|