active_mocker 0.1.1

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.
@@ -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
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - "2.1.0"
6
+ - "2.1.1"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in active_mocker.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :default => 'specs'
4
+
5
+ task :specs do
6
+ system 'rspec'
7
+ end
@@ -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,5 @@
1
+ require "active_mocker/version"
2
+
3
+ module ActiveMocker
4
+ # Your code goes here...
5
+ 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,12 @@
1
+ module Scope
2
+
3
+ def scope(method_name, proc)
4
+ singleton_class.class_eval do
5
+ params = Reparameterize.call(proc.parameters)
6
+ block = eval("lambda { |#{params}| }")
7
+ define_method(method_name, block)
8
+ end
9
+ end
10
+
11
+ end
12
+
@@ -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
+