active_mocker 1.8.4 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +4 -2
  4. data/lib/active_mocker.rb +9 -25
  5. data/lib/active_mocker/config.rb +26 -46
  6. data/lib/active_mocker/generate.rb +115 -110
  7. data/lib/active_mocker/loaded_mocks.rb +76 -65
  8. data/lib/active_mocker/mock/base.rb +283 -287
  9. data/lib/active_mocker/mock/has_many.rb +2 -0
  10. data/lib/active_mocker/mock_creator.rb +262 -0
  11. data/lib/active_mocker/mock_template.erb +9 -186
  12. data/lib/active_mocker/mock_template/_associations.erb +82 -0
  13. data/lib/active_mocker/mock_template/_attributes.erb +11 -0
  14. data/lib/active_mocker/mock_template/_class_methods.erb +41 -0
  15. data/lib/active_mocker/mock_template/_defined_methods.erb +10 -0
  16. data/lib/active_mocker/mock_template/_modules_constants.erb +10 -0
  17. data/lib/active_mocker/mock_template/_scopes.erb +23 -0
  18. data/lib/active_mocker/null_progress.rb +9 -0
  19. data/lib/active_mocker/output_capture.rb +32 -0
  20. data/lib/active_mocker/parent_class.rb +64 -0
  21. data/lib/active_mocker/progress.rb +13 -0
  22. data/lib/active_mocker/public_methods.rb +15 -23
  23. data/lib/active_mocker/rspec.rb +16 -0
  24. data/lib/active_mocker/rspec_helper.rb +10 -8
  25. data/lib/active_mocker/task.rake +6 -1
  26. data/lib/active_mocker/template_creator.rb +22 -0
  27. data/lib/active_mocker/version.rb +1 -1
  28. metadata +43 -103
  29. data/lib/active_mocker/active_record.rb +0 -74
  30. data/lib/active_mocker/active_record/field.rb +0 -39
  31. data/lib/active_mocker/active_record/relationships.rb +0 -110
  32. data/lib/active_mocker/active_record/schema.rb +0 -81
  33. data/lib/active_mocker/active_record/scope.rb +0 -22
  34. data/lib/active_mocker/active_record/table.rb +0 -26
  35. data/lib/active_mocker/active_record/unknown_class_method.rb +0 -17
  36. data/lib/active_mocker/active_record/unknown_module.rb +0 -30
  37. data/lib/active_mocker/db_to_ruby_type.rb +0 -29
  38. data/lib/active_mocker/file_reader.rb +0 -11
  39. data/lib/active_mocker/model_reader.rb +0 -191
  40. data/lib/active_mocker/model_schema.rb +0 -285
  41. data/lib/active_mocker/model_schema/assemble.rb +0 -220
  42. data/lib/active_mocker/reparameterize.rb +0 -41
  43. data/lib/active_mocker/ruby_parse.rb +0 -68
  44. data/lib/active_mocker/schema_reader.rb +0 -30
  45. data/lib/active_mocker/string_reader.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae228af179be61ae85b6dcacebff1adbad0c2de3
4
- data.tar.gz: d4b1cc0d7d6209bbe2ca6210534e54348746d7ef
3
+ metadata.gz: fb2357b680e38a103a603361d01ca9ed9a67f62f
4
+ data.tar.gz: 0f82aa8aa703d9919650d19d5ff02eac1f4ad6ae
5
5
  SHA512:
6
- metadata.gz: b68c2749a6ec8ef1c1617345bca88413cc22ca5f2ff4b7feadd9120d38a2dea9839fc6fc1352b336d966d93119b67b3e330d1b7d2f5dc1092bd16cf5f5e26628
7
- data.tar.gz: 01f7f45c33a3ec713045d38114653bf5a345b27836ff9ed3ced1a222528e3d50e0cbaf5289ea426097eda7209bee880d11db22c34bc87d164f7cc45b6d57335e
6
+ metadata.gz: ed04ff66eb99a25b4930262cdda6e124b26df1db6e2177e8f80ea20ef55d81ef8233dbdfda54b5c99dc9edb8454a8f5210ea57fe33cc5a4c76c2cc5b66604cd5
7
+ data.tar.gz: 5417b116dc8afda6894b717e90c2fbfc212a44291aa92a2c717a39887e86e3842301ccd1c813290b9f536851064e4fe0fe4301abc286b451697a2b45ff22986c
data/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## 2.0.0.beta1 - 2015-12-01
5
+ ### Enhancement
6
+ - db/schema.rb is no longer required to generate mocks.
7
+ - `ActiveMocker::Config.disable_modules_and_constants=` Non locally defineded Modules are included/extended by default as well as constant declaration. To Disable to feature set to `true`.
8
+ - `MODEL=User rake active_mocker:build` no longer takes a model name to generate just that mock. It now takes a path to a model file. `MODEL=[path-to-model] rake active_mocker:build`
9
+
10
+ ### Removed
11
+ - `log/active_mocker.log` is replaced env `ERROR_VERBOSITY=[0,1,2] rake active_mocker:build` or in Ruby `ActiveMocker::Config.error_verbosity=`
12
+ - Removing undocumented feature of treating children of mocks differently. Remove the ability to sub class a mock and have it for use in that context when creating/finding association.
13
+
14
+ ### Depracating
15
+ - `mock_class` for rspec_helper, use `instead active_mocker.mocks.find('ClassName')`. Will be removed in v2.1
16
+
4
17
  ## 1.8.4 - 2015-10-06
5
18
  ### Fix
6
19
  - Calling scoped method that has not been stubbed raises incorrect error. https://github.com/zeisler/active_mocker/issues/22
data/README.md CHANGED
@@ -4,8 +4,10 @@
4
4
  [![Code Climate](https://codeclimate.com/github/zeisler/active_mocker.png)](https://codeclimate.com/github/zeisler/active_mocker)
5
5
  [![Dependency Status](https://gemnasium.com/zeisler/active_mocker.svg)](https://gemnasium.com/zeisler/active_mocker)
6
6
  [![Gitter chat](https://badges.gitter.im/zeisler/active_mocker.png)](https://gitter.im/zeisler/active_mocker)
7
+ [![Gittip](http://img.shields.io/gittip/zeisler.svg)](https://www.gittip.com/zeisler/)
7
8
 
8
- ActiveMocker creates mocks classes from ActiveRecord models. Allowing your test suite to run very fast by not loading Rails or a database. It parses the schema.rb and the defined methods on a model then generates a ruby file that can be included within a test. The mock file can be run by themselves and come with a partial implementation of ActiveRecord. Attributes and associations can be used just the same as in ActiveRecord. Methods will have the correct arguments but raise an NotImplementedError when called. Mocks are regenerated when the schema is modified so your mocks will not go stale; preventing the case where your units tests pass but production code fails.
9
+ ## Description
10
+ ActiveMocker creates mock classes from ActiveRecord models, allowing your test suite to run at breakneck speed. This can be done by not loading Rails or hitting a database. The models are read dynamically and statically so that ActiveMocker can generate a Ruby file to require within a test. The mock file can be run by itself and comes with a partial implementation of ActiveRecord. Attributes and associations can be used the same as in ActiveRecord. Methods have the same argument signature but raise a NotImplementedError when called, allowing you to stub it with a mocking framework, like RSpec. Mocks are regenerated when the schema is modified so your mocks won't go stale, preventing the case where your units tests pass but production code fails.
9
11
 
10
12
  Examples from a real apps
11
13
 
@@ -254,7 +256,7 @@ end
254
256
  ```
255
257
  ### Constants and Modules
256
258
 
257
- * Any locally defined modules will not be included or extended.
259
+ * Any locally defined modules will not be included or extended. It can be disabled by `ActiveMocker::Config.disable_modules_and_constants = true`
258
260
 
259
261
  ---------------
260
262
  ```ruby
data/lib/active_mocker.rb CHANGED
@@ -1,32 +1,16 @@
1
1
  require 'active_mocker/version'
2
-
3
- require 'logger'
4
2
  require 'active_mocker/railtie' if defined?(Rails)
5
3
  require 'ruby-progressbar'
6
4
  require 'forwardable'
7
5
  require 'active_support/all'
8
- require 'singleton'
9
- require 'parser/current'
10
- require 'unparser'
11
- require 'virtus'
12
- require 'attr_permit'
13
- require 'active_mocker/version'
14
- require 'active_mocker/ruby_parse'
15
6
  require 'active_mocker/public_methods'
16
7
  require 'active_mocker/config'
17
- require 'active_mocker/generate'
18
- require 'active_mocker/logger'
19
- require 'active_mocker/active_record/table'
20
- require 'active_mocker/active_record/field'
21
- require 'active_mocker/file_reader'
22
- require 'active_mocker/reparameterize'
23
- require 'active_mocker/active_record'
24
- require 'active_mocker/model_reader'
25
- require 'active_mocker/schema_reader'
26
- require 'active_mocker/active_record/schema'
27
- require 'active_mocker/active_record'
28
- require 'active_mocker/model_reader'
29
- require 'active_mocker/reparameterize'
30
- require 'active_mocker/db_to_ruby_type'
31
- require 'active_mocker/model_schema'
32
- require 'active_mocker/model_schema/assemble'
8
+ require "reverse_parameters"
9
+ require "active_record_schema_scrapper"
10
+ require "dissociated_introspection"
11
+ require "active_mocker/null_progress"
12
+ require "active_mocker/progress"
13
+ require "active_mocker/parent_class"
14
+ require "active_mocker/template_creator"
15
+ require "active_mocker/mock_creator"
16
+ require "active_mocker/generate"
@@ -3,73 +3,53 @@ module ActiveMocker
3
3
  class Config
4
4
  class << self
5
5
 
6
- attr_accessor :schema_file,
7
- :model_dir,
6
+ attr_accessor :model_dir,
8
7
  :mock_dir,
9
- :model_base_classes,
10
- :file_reader,
11
- :build_in_progress,
12
- :log_location,
13
- :clear_log_on_build,
14
- :generate_for_mock
8
+ :single_model_path,
9
+ :progress_bar,
10
+ :error_verbosity,
11
+ :disable_modules_and_constants
12
+ #TODO add disable include/extend of modules
13
+ #TODO disable scope methods
14
+ #disable instance methods, class methods
15
+ # can't disable attribute as of yet
15
16
 
16
17
  def model_base_classes=(val)
17
18
  @model_base_classes = val
18
19
  end
19
20
 
20
- def set
21
+ def set(&block)
21
22
  load_defaults
22
23
  yield self
23
24
  end
24
25
 
25
26
  def load_defaults
26
- @schema_file = nil unless @schema_file
27
- @model_dir = nil unless @model_dir
28
- @mock_dir = nil unless @mock_dir
29
- @model_base_classes = %w[ ActiveRecord::Base ] unless @model_base_classes
30
- @file_reader = FileReader unless @file_reader
31
- @log_location = 'log/active_mocker.log' unless @log_location
32
- @clear_log_on_build = true
33
- @generate_for_mock = ENV['MODEL']
27
+ @error_verbosity = 1
28
+ @progress_bar = true
29
+ @disable_modules_and_constants = false
30
+ @model_dir = nil unless @model_dir
31
+ @mock_dir = nil unless @mock_dir
34
32
  rails_defaults if Object.const_defined?('Rails')
35
33
  end
36
34
 
37
- def logger
38
- default_logger
39
- end
40
-
41
35
  def reset_all
42
- [ :@schema_file,
43
- :@model_dir,
44
- :@mock_dir,
45
- :@model_base_classes,
46
- :@file_reader,
47
- :@logger,
48
- :@schema_file,
49
- :@model_dir,
50
- :@mock_dir].each{|ivar| instance_variable_set(ivar, nil)}
51
- end
52
-
53
- def default_logger
54
- FileUtils.mkdir_p(File.dirname(@log_location)) unless File.directory?(File.dirname(@log_location))
55
- ::Logger.new(@log_location)
36
+ [:model_dir,
37
+ :mock_dir,
38
+ :log_location,
39
+ :single_model_path,
40
+ :progress_bar,
41
+ :error_verbosity
42
+ ].each { |ivar| instance_variable_set("@#{ivar}", nil) }
56
43
  end
57
44
 
58
45
  def rails_defaults
59
- @schema_file = File.join(Rails.root, 'db/schema.rb') unless @schema_file
60
- @model_dir = File.join(Rails.root, 'app/models') unless @model_dir
61
- @mock_dir = File.join(Rails.root, 'spec/mocks') unless @mock_dir
46
+ @model_dir = File.join(Rails.root, 'app/models') unless @model_dir
47
+ @mock_dir = File.join(Rails.root, 'spec/mocks') unless @mock_dir
62
48
  end
63
49
 
64
- def clear_log
65
- if @clear_log_on_build && File.exist?(@log_location)
66
- FileUtils.rm(@log_location)
67
- end
50
+ def progress_class
51
+ @progress_bar ? Progress : NullProgress
68
52
  end
69
-
70
53
  end
71
-
72
54
  end
73
-
74
55
  end
75
-
@@ -1,134 +1,139 @@
1
- require 'ruby-progressbar'
2
- require 'forwardable'
3
1
  module ActiveMocker
4
- class Generate
5
- extend Forwardable
6
-
7
- attr_reader :silence
8
-
9
- def initialize(silence: false)
10
- @silence = silence
11
- Config.clear_log
12
- Config.build_in_progress = true
13
- create_template
14
- Config.build_in_progress = false
15
- end
16
-
17
- private
18
-
19
- def generate_model_schema
20
- ActiveMocker::ModelSchema::Assemble.new(progress: progress).run
21
- end
2
+ class Generate
3
+
4
+ def initialize
5
+ raise ArgumentError, "mock_dir is missing a valued value!" if config.mock_dir.nil? || config.mock_dir.empty?
6
+ create_mock_dir
7
+ raise ArgumentError, "model_dir is missing a valued value!" if config.model_dir.nil? || config.model_dir.empty? || !Dir.exists?(config.model_dir)
8
+ @success_count = 0
9
+ @errors = []
10
+ end
22
11
 
23
- def model_count
24
- @model_count ||= ActiveMocker::ModelSchema::Assemble.new.models.count
25
- end
12
+ # @returns self
13
+ def call
14
+ progress_init
15
+ models_paths.each do |file|
16
+ model_name = model_name(file)
17
+ model = model_name.constantize
18
+ mock_file_name = "#{model_name.underscore}_#{mock_append_name.underscore}.rb"
19
+ mock_file_path = File.join(Config.mock_dir, mock_file_name)
20
+ schema_scrapper = schema_scrapper(model)
21
+ File.open(mock_file_path, 'w') do |file_out|
22
+ begin
23
+ r = create_mock(file, file_out, schema_scrapper)
24
+ collect_errors(mock_file_path, r, schema_scrapper)
25
+ @success_count += 1 if r.completed?
26
+ rescue => e
27
+ rescue_clean_up(e, file_out, model_name)
28
+ end
29
+ end
30
+ progress.increment
31
+ end
32
+ display_errors
33
+ failure_count_message
34
+ self
35
+ end
26
36
 
27
- def progress
28
- return @progress if !@progress.nil? || silence == true
29
- progress_options = {:title => 'Generating Mocks',
30
- :total => model_count * 2,
31
- format: '%t |%b>>%i| %p%%'}
32
- @progress = ProgressBar.create(progress_options)
33
- end
37
+ private
34
38
 
35
- def increment_progress
36
- progress.increment unless silence
37
- end
39
+ attr_reader :success_count, :errors
38
40
 
39
- attr_accessor :mocks_created, :not_valid_models
40
- def create_template
41
- @mocks_created = 0
42
- @not_valid_models = 0
43
- clean_up
44
- generate_model_schema.each do |model|
45
- next unless generate_and_rescue(model)
41
+ def create_mock(file, file_out, schema_scrapper)
42
+ MockCreator.new(file: File.open(file),
43
+ file_out: file_out,
44
+ schema_scrapper: schema_scrapper,
45
+ klasses_to_be_mocked: model_names,
46
+ enabled_partials: enabled_partials).create
46
47
  end
47
- exit_message
48
- end
49
48
 
50
- def generate_and_rescue(model)
51
- begin
52
- raise_if_is_exception!(model)
53
- generate_mock(model)
54
- increase_mocks_created
55
- rescue Exception => exception
56
- log_failed_mock(exception, model)
57
- false
49
+ def collect_errors(mock_file_path, r, schema_scrapper)
50
+ unless r.errors.empty?
51
+ File.delete(mock_file_path)
52
+ errors.concat(r.errors)
53
+ end
54
+ unless schema_scrapper.associations.errors.empty?
55
+ errors.concat(schema_scrapper.associations.errors.uniq(&:message))
56
+ end
57
+ unless schema_scrapper.attributes.errors.empty?
58
+ errors.concat(schema_scrapper.attributes.errors.uniq(&:message))
59
+ end
58
60
  end
59
- end
60
61
 
61
- def increase_mocks_created
62
- @mocks_created += 1
63
- increment_progress
64
- end
65
-
66
- def raise_if_is_exception!(model)
67
- raise model if model.class.ancestors.include?(Exception)
68
- end
62
+ def rescue_clean_up(e, file_out, model_name)
63
+ file_out.close
64
+ File.delete(file_out.path)
65
+ e = OpenStruct.new(message: e.message, class_name: model_name, original_error: e) if e.class <= Exception
66
+ errors << e
67
+ end
69
68
 
70
- def exit_message
71
- progress.finish unless silence
72
- Config.logger.info "Generated #{mocks_created} of #{model_count} mocks."
73
- failed_mocks = (model_count - not_valid_models) - mocks_created
74
- if failed_mocks > 0
75
- puts "#{failed_mocks} mock(s) out of #{model_count} failed. See `log/active_mocker.log` for more info."
69
+ def schema_scrapper(model)
70
+ # if model.respond_to?(:abstract_class?) && model.abstract_class?
71
+ # null_collection = OpenStruct.new(to_a: [], errors: [])
72
+ # OpenStruct.new(associations: null_collection, attributes: null_collection, abstract_class?: true)
73
+ # else
74
+ ActiveRecordSchemaScrapper.new(model: model)
75
+ # end
76
76
  end
77
- end
78
77
 
79
- def generate_mock(model)
80
- klass_str = generate_mock_string(model)
81
- save_mock_file(klass_str, model)
82
- log_save(model)
83
- end
78
+ def display_errors
79
+ errors.flatten.each do |e|
80
+ if config.error_verbosity == 2
81
+ puts "#{e.class_name} has failed:"
82
+ puts e.message
83
+ puts e.original_error.message if e.respond_to? :original_error
84
+ puts e.original_error.backtrace if e.respond_to? :original_error
85
+ puts e.original_error.class.name if e.respond_to? :original_error
86
+ elsif config.error_verbosity == 1
87
+ puts e.message
88
+ end
89
+ end
90
+ end
84
91
 
85
- def log_failed_mock(exception, model)
86
- Config.logger.debug $!.backtrace
87
- Config.logger.debug exception
88
- Config.logger.info "Failed to load #{model.class_name} model."
89
- end
92
+ def failure_count_message
93
+ if config.error_verbosity > 0 && success_count < models_paths.count
94
+ "#{ models_paths.count - success_count } mock(s) out of #{models_paths.count} failed."\
95
+ "To see more detail set error_verbosity = 2 or to mute this error set error_verbosity = 0."
96
+ end
97
+ end
90
98
 
91
- def log_save(model)
92
- Config.logger.info "saving mock #{model.class_name} to #{Config.mock_dir}"
93
- end
99
+ def model_name(file)
100
+ File.basename(file, '.rb').camelize
101
+ end
94
102
 
95
- def save_mock_file(klass_str, model)
96
- File.open(File.join(Config.mock_dir, "#{model.class_name.underscore}_mock.rb"), 'w') do |f|
97
- f.write(klass_str)
103
+ def model_names
104
+ @model_names ||= models_paths.map { |p| model_name(p) }
98
105
  end
99
- end
100
106
 
101
- def generate_mock_string(model)
102
- model.render(File.open(File.join(File.expand_path('../', __FILE__), 'mock_template.erb')).read, mock_append_name)
103
- end
107
+ def progress
108
+ @progress
109
+ end
104
110
 
105
- def clean_up
106
- delete_mocks if delete_mocks?
107
- create_mock_dir
108
- end
111
+ def progress_init
112
+ @progress = config.progress_class.new(models_paths.count)
113
+ end
109
114
 
110
- def delete_mocks
111
- FileUtils.rm Dir.glob(File.join(mock_dir, "*_#{mock_append_name.underscore}.rb"))
112
- end
115
+ def models_paths
116
+ @models_paths ||= Dir.glob(config.single_model_path || File.join(config.model_dir, "*.rb"))
117
+ end
113
118
 
114
- def mock_dir
115
- raise 'ActiveMocker::Config.mock_dir is set to nil!' if Config.mock_dir.nil? || Config.mock_dir.empty?
116
- File.expand_path(Config.mock_dir)
117
- end
119
+ def config
120
+ ActiveMocker::Config
121
+ end
118
122
 
119
- def delete_mocks?
120
- !Config.generate_for_mock && Dir.exists?(mock_dir)
121
- end
123
+ def create_mock_dir
124
+ FileUtils::mkdir_p(config.mock_dir) unless Dir.exists?(config.mock_dir)
125
+ end
122
126
 
123
- def create_mock_dir
124
- FileUtils::mkdir_p(mock_dir) unless Dir.exists?(mock_dir)
125
- end
127
+ def mock_append_name
128
+ 'Mock'
129
+ end
126
130
 
127
- def mock_append_name
128
- 'Mock'
131
+ def enabled_partials
132
+ if config.disable_modules_and_constants
133
+ MockCreator.enabled_partials_default - [*:modules_constants]
134
+ else
135
+ MockCreator.enabled_partials_default
136
+ end
137
+ end
129
138
  end
130
-
131
- end
132
- end
133
-
134
-
139
+ end
@@ -1,91 +1,102 @@
1
1
  module ActiveMocker
2
-
3
2
  class LoadedMocks
4
-
5
3
  class << self
6
4
 
7
- # Input ActiveRecord Model as String returns ActiveMock equivalent class.
8
- # +find('User')+ => UserMock
9
- def find(klass)
10
- class_name_to_mock[klass]
11
- end
5
+ extend Forwardable
6
+ def_delegators :mocks, :find, :delete_all
12
7
 
13
- # Returns Hash key being a string of the active_record class name
14
- # and the value being the mocked class.
15
- # ActiveMocker::LoadedMocks.all
16
- # => {'PersonMock' => PersonMock}
17
- def all
18
- mocks
8
+ # Returns an Enumerable of all currently loaded mocks.
9
+ #
10
+ # ActiveMocker::LoadedMocks.mocks
11
+ # => <Collection @hash: {'Person' => PersonMock}>
12
+ # @return ActiveMocker::LoadedMocks::Collection
13
+ def mocks
14
+ Collection.new(mocks_store.values.each_with_object({}) do |mock_constant, hash|
15
+ hash[mock_constant.send(:mocked_class)] = mock_constant
16
+ end)
19
17
  end
20
18
 
21
- # Calls clear_all for all mocks, which deletes all saved records and removes mock_class/instance_method.
22
- # It will also clear any sub classed mocks from the list
23
- # Method will be deprecated in v2 because mocking is deprecated
24
- def clear_all
25
- all_mocks.each { |m| m.clear_mock }
26
- clear_subclasses
27
- end
19
+ # @deprecated Use {#mocks} instead of this method.
20
+ alias_method :class_name_to_mock, :mocks
28
21
 
29
- # Calls delete_all for all mocks, which deletes all saved records.
30
- #
31
- def delete_all
32
- all_mocks.each { |m| m.delete_all }
33
- end
22
+ # @deprecated Use {#mocks} instead of this method.
23
+ alias_method :all, :mocks
34
24
 
35
- # Returns Hash +{"ActiveRecordModel" => MockVersion}+, key being a string of the active_record class name
36
- # and the value being the mocked class. Any sub classed mocked will override the original mock until clear_all is called.
37
- #
38
- # ActiveMocker::LoadedMocks.class_name_to_mock
39
- # => {'Person' => PersonMock}
40
- def class_name_to_mock
41
- mocks.values.each_with_object({}) do |mock_constant, hash|
42
- hash[mock_constant.send(:mocked_class)] = mock_constant
43
- end.merge(subclasses)
44
- end
25
+ # @deprecated Use {#delete_all} instead of this method.
26
+ alias_method :clear_all, :delete_all
45
27
 
46
- private
28
+ class Collection
47
29
 
48
- def add(mocks_to_add)
49
- mocks.merge!({mocks_to_add.name => mocks_to_add})
50
- end
30
+ include Enumerable
51
31
 
52
- def add_subclass(subclass)
53
- subclasses.merge!({subclass.send(:mocked_class) => subclass})
54
- end
32
+ # @option opts [Hash] hash
33
+ def initialize(hash={})
34
+ @hash = Hash[hash]
35
+ end
55
36
 
56
- def mocks
57
- @mocks ||= {}
58
- end
37
+ extend Forwardable
38
+ def_delegators :hash, :[]=, :[], :each, :to_hash, :to_h
59
39
 
60
- def undefine_all
61
- all_mocks_as_str.each do |n|
62
- Object.send(:remove_const, n) if Object.const_defined?(n)
40
+ # Calls {#delete_all} for all mocks globally, which removes all records that were saved or created.
41
+ # @return [NilClass]
42
+ def delete_all
43
+ mocks.each(&__method__)
63
44
  end
64
- end
65
45
 
66
- def all_mocks_as_str
67
- mocks.keys + subclasses.keys
68
- end
46
+ # @param [Array<Symbol, String, ActiveMocker::Mock>] args an array of ActiveRecord Model Names as Strings or Symbols
47
+ # or of mock object.
48
+ # @return [ActiveMocker::LoadedMocks::Collection] returns ActiveMock equivalent class.
49
+ def slice(*args)
50
+ self.class.new(select { |k, v| get_item(args, k, v) })
51
+ end
69
52
 
70
- def subclasses
71
- @subclasses ||= {}
72
- end
53
+ # Input ActiveRecord Model Name as String or Symbol and it returns everything but that ActiveMock equivalent class.
54
+ # except('User') => [AccountMock, OtherMock]
55
+ # @param [Array<Symbol, String, ActiveMocker::Mock>] args
56
+ # @return ActiveMocker::LoadedMocks::Collection
57
+ def except(*args)
58
+ self.class.new(reject { |k, v| get_item(args, k, v) })
59
+ end
60
+
61
+ # Input ActiveRecord Model Name as String or Symbol returns ActiveMock equivalent class.
62
+ # find('User') => UserMock
63
+ # @param [Symbol, String, ActiveMocker::Mock] item
64
+ # @return ActiveMocker::Mock
65
+ def find(item)
66
+ slice(item).mocks.first
67
+ end
68
+
69
+ # @return [Array<ActiveMocker::Mock>]
70
+ def mocks
71
+ hash.values
72
+ end
73
+ alias_method :values, :mocks
74
+
75
+ private
76
+ attr_reader :hash
77
+
78
+ def get_item(args, k, v)
79
+ args.map do |e|
80
+ if [:to_str, :to_sym].any?{|i| e.respond_to? i}
81
+ e.to_s == k
82
+ else
83
+ e == v
84
+ end
85
+ end.any? { |a| a }
86
+ end
73
87
 
74
- def clear_subclasses
75
- subclasses.clear
76
88
  end
77
89
 
78
- def internal_clear
79
- clear_subclasses
80
- mocks.clear
90
+ private
91
+
92
+ def mocks_store
93
+ @mocks ||= {}
81
94
  end
82
95
 
83
- def all_mocks
84
- mocks.values + subclasses.values
96
+ def add(mocks_to_add)
97
+ mocks_store.merge!({ mocks_to_add.name => mocks_to_add })
85
98
  end
86
-
99
+
87
100
  end
88
-
89
101
  end
90
-
91
102
  end