├── .codeclimate.yml
├── .gitignore
├── .hound.yml
├── .rubocop.yml
├── .travis.yml
├── CHANGELOG.md
├── Cheffile
├── Cheffile.lock
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── Vagrantfile
├── active_mocker.gemspec
├── bin
└── console
├── codeclimate.yml
├── example_rails_app
├── .gitignore
├── .rspec
├── Gemfile
├── README.rdoc
├── Rakefile
├── app
│ ├── assets
│ │ ├── images
│ │ │ └── .keep
│ │ ├── javascripts
│ │ │ └── application.js
│ │ └── stylesheets
│ │ │ └── application.css
│ ├── controllers
│ │ ├── application_controller.rb
│ │ └── concerns
│ │ │ └── .keep
│ ├── helpers
│ │ └── application_helper.rb
│ ├── mailers
│ │ └── .keep
│ ├── models
│ │ ├── .keep
│ │ ├── comment.rb
│ │ ├── concerns
│ │ │ └── .keep
│ │ ├── subscription.rb
│ │ └── user.rb
│ └── views
│ │ └── layouts
│ │ └── application.html.erb
├── bin
│ ├── bundle
│ ├── rails
│ ├── rake
│ └── spring
├── config.ru
├── config
│ ├── application.rb
│ ├── boot.rb
│ ├── database.yml
│ ├── environment.rb
│ ├── environments
│ │ ├── development.rb
│ │ ├── production.rb
│ │ └── test.rb
│ ├── initializers
│ │ ├── assets.rb
│ │ ├── backtrace_silencers.rb
│ │ ├── cookies_serializer.rb
│ │ ├── filter_parameter_logging.rb
│ │ ├── inflections.rb
│ │ ├── mime_types.rb
│ │ ├── session_store.rb
│ │ └── wrap_parameters.rb
│ ├── locales
│ │ └── en.yml
│ ├── routes.rb
│ └── secrets.yml
├── db
│ ├── migrate
│ │ ├── 20140731143902_create_users.rb
│ │ ├── 20140731143955_create_comments.rb
│ │ └── 20140731144123_create_subscriptions.rb
│ ├── schema.rb
│ └── seeds.rb
├── example_rails_app.iml
├── lib
│ ├── assets
│ │ └── .keep
│ ├── subscribe_user.rb
│ └── tasks
│ │ └── .keep
├── log
│ └── .keep
├── public
│ ├── 404.html
│ ├── 422.html
│ ├── 500.html
│ ├── favicon.ico
│ └── robots.txt
├── spec
│ ├── lib
│ │ └── subscribe_user_spec.rb
│ ├── mocks
│ │ ├── comment_mock.rb
│ │ ├── subscription_mock.rb
│ │ └── user_mock.rb
│ ├── rails_helper.rb
│ └── spec_helper.rb
└── vendor
│ └── assets
│ ├── javascripts
│ └── .keep
│ └── stylesheets
│ └── .keep
├── lib
├── active_mocker.rb
└── active_mocker
│ ├── attribute.rb
│ ├── attribute_types
│ ├── enum.rb
│ └── register.rb
│ ├── config.rb
│ ├── display_errors.rb
│ ├── error_object.rb
│ ├── file_path_to_ruby_class.rb
│ ├── file_writer.rb
│ ├── generate.rb
│ ├── hash_new_style.rb
│ ├── inspectable.rb
│ ├── inspectable
│ ├── bigdecimal.rb
│ ├── date.rb
│ ├── dir.rb
│ ├── file.rb
│ ├── pathname.rb
│ ├── struct.rb
│ └── time.rb
│ ├── late_inclusion.rb
│ ├── loaded_mocks.rb
│ ├── loaded_mocks
│ └── features.rb
│ ├── mock.rb
│ ├── mock
│ ├── alias_attribute.rb
│ ├── association.rb
│ ├── base.rb
│ ├── belongs_to.rb
│ ├── collection.rb
│ ├── compatibility
│ │ ├── base
│ │ │ └── ar51.rb
│ │ └── queries
│ │ │ └── ar52.rb
│ ├── do_nothing_active_record_methods.rb
│ ├── exceptions.rb
│ ├── has_and_belongs_to_many.rb
│ ├── has_many.rb
│ ├── has_one.rb
│ ├── hash_process.rb
│ ├── mock_relation.rb
│ ├── mockable_method.rb
│ ├── object_inspect.rb
│ ├── queries.rb
│ ├── records.rb
│ ├── relation.rb
│ ├── single_relation.rb
│ ├── template_methods.rb
│ └── unrepresentable_const_value.rb
│ ├── mock_creator.rb
│ ├── mock_creator
│ ├── associations.rb
│ ├── attributes.rb
│ ├── class_methods.rb
│ ├── defined_methods.rb
│ ├── mock_build_version.rb
│ ├── modules_constants.rb
│ ├── recreate_class_method_calls.rb
│ ├── safe_methods.rb
│ └── scopes.rb
│ ├── mock_template.erb
│ ├── mock_template
│ ├── _associations.erb
│ ├── _attributes.erb
│ ├── _class_methods.erb
│ ├── _defined_methods.erb
│ ├── _mock_build_version.erb
│ ├── _modules_constants.erb
│ ├── _recreate_class_method_calls.erb
│ └── _scopes.erb
│ ├── null_progress.rb
│ ├── parent_class.rb
│ ├── progress.rb
│ ├── public_methods.rb
│ ├── railtie.rb
│ ├── rspec.rb
│ ├── rspec_helper.rb
│ ├── task.rake
│ ├── template_creator.rb
│ └── version.rb
├── log
└── .keep
├── spec
├── gemfile_version_match_spec.rb
├── lib
│ ├── active_mocker
│ │ ├── config_spec.rb
│ │ ├── display_errors_spec.rb
│ │ ├── file_path_to_ruby_class_spec.rb
│ │ ├── generate_spec.rb
│ │ ├── loaded_mocks_spec.rb
│ │ ├── mock
│ │ │ ├── association_spec.rb
│ │ │ ├── base_spec.rb
│ │ │ ├── belongs_to_spec.rb
│ │ │ ├── collection_spec.rb
│ │ │ ├── has_and_belongs_to_many_spec.rb
│ │ │ ├── has_many_shared_example.rb
│ │ │ ├── has_many_spec.rb
│ │ │ ├── hash_process_spec.rb
│ │ │ ├── queriable_shared_example.rb
│ │ │ ├── records_spec.rb
│ │ │ └── relation_spec.rb
│ │ ├── mock_creator_spec.rb
│ │ ├── parent_class_spec.rb
│ │ └── template_creator_spec.rb
│ ├── model_nested.rb
│ ├── models
│ │ ├── model.rb
│ │ ├── non_active_record_model.rb
│ │ └── some_namespace
│ │ │ └── some_module.rb
│ ├── person.rb
│ └── post_methods.rb
├── spec_helper.rb
├── support
│ └── strip_heredoc.rb
└── unit_logger.rb
├── tasks
├── integration.rake
├── setup.rake
└── unit.rake
└── test_rails_app
├── .secret
├── Appraisals
├── Gemfile
├── LICENSE
├── Rakefile
├── app
└── models
│ ├── .keep
│ ├── account.rb
│ ├── api
│ └── customer.rb
│ ├── child_model.rb
│ ├── has_no_parent.rb
│ ├── has_no_table.rb
│ ├── identity.rb
│ ├── micropost.rb
│ ├── micropost
│ └── core.rb
│ ├── relationship.rb
│ └── user.rb
├── bin
├── bundle
├── rails
├── rake
└── rspec
├── config.ru
├── config
├── application.rb
├── boot.rb
├── database.yml
├── environment.rb
├── environments
│ ├── development.rb
│ ├── production.rb
│ └── test.rb
├── initializers
│ ├── backtrace_silencers.rb
│ ├── filter_parameter_logging.rb
│ ├── inflections.rb
│ ├── mime_types.rb
│ ├── secret_token.rb
│ ├── session_store.rb
│ └── wrap_parameters.rb
├── locales
│ └── en.yml
└── routes.rb
├── db
├── migrate
│ └── 20160621215939_create_products.rb
├── schema.rb
└── seeds.rb
├── gemfiles
├── rails_4.2.gemfile
├── rails_4.2.gemfile.lock
├── rails_5.2.gemfile
├── rails_5.2.gemfile.lock
├── rails_6.0.gemfile
└── rails_6.0.gemfile.lock
├── lib
├── post_methods.rb
└── unit_logger.rb
├── log
└── .keep
├── spec
├── account_spec.rb
├── active_record_compatible_api.rb
├── api
│ └── customer_spec.rb
├── child_model_spec.rb
├── clear_after_all_example_spec.rb
├── const_stub_example_spec.rb
├── factories.rb
├── features_spec.rb
├── has_no_table_spec.rb
├── idenity_mock_spec.rb
├── micropost_mock_spec.rb
├── rails_helper.rb
├── rake_task_spec.rb
├── relation_spec.rb
├── spec_helper.rb
├── user_mock_spec.rb
└── user_spec.rb
└── test_rails_4_app.iml
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | ---
2 | engines:
3 | csslint:
4 | enabled: false
5 | duplication:
6 | enabled: true
7 | config:
8 | languages:
9 | - ruby
10 | eslint:
11 | enabled: false
12 | fixme:
13 | enabled: true
14 | rubocop:
15 | enabled: true
16 | ratings:
17 | paths:
18 | - "**.erb"
19 | - "**.rb"
20 | exclude_paths:
21 | - spec/
22 | - test_rails_app/
23 | - example_rails_app/
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
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
18 | sample_app_rails_4/log/*
19 | log/active_mocker.log
20 | test_rails_app/db/development.sqlite3
21 | test_rails_app/log/*
22 | test_rails_app/.idea/*
23 | example_rails_app/.idea/*
24 | .idea/*
25 | cookbooks/*
26 | .vagrant/*
27 | test_rails_app/spec/mocks/*
28 | *.sqlite3
29 |
--------------------------------------------------------------------------------
/.hound.yml:
--------------------------------------------------------------------------------
1 | ruby:
2 | config_file: .rubocop.yml
3 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | TargetRubyVersion: 2.3
3 | DisplayStyleGuide: true
4 | Exclude:
5 | - spec/**/*.rb
6 | - test_rails_app/**/*.rb
7 | Rails:
8 | Enabled: true
9 |
10 |
11 | Metrics/LineLength:
12 | Max: 120
13 |
14 | Layout/AlignParameters:
15 | # Alignment of parameters in multi-line method calls.
16 | #
17 | # The `with_first_parameter` style aligns the following lines along the same
18 | # column as the first parameter.
19 | #
20 | # method_call(a,
21 | # b)
22 | #
23 | # The `with_fixed_indentation` style aligns the following lines with one
24 | # level of indentation relative to the start of the line with the method call.
25 | #
26 | # method_call(a,
27 | # b)
28 | EnforcedStyle: with_first_parameter
29 | SupportedStyles:
30 | - with_first_parameter
31 | - with_fixed_indentation
32 |
33 | # Multi-line method chaining should be done with trailing dots.
34 | Style/DotPosition:
35 | EnforcedStyle: leading
36 | SupportedStyles:
37 | - leading
38 |
39 | Style/Documentation:
40 | Description: 'Document classes and non-namespace modules.'
41 | Enabled: false
42 | Exclude:
43 | - 'spec/**/*'
44 | - 'test/**/*'
45 |
46 | Style/TrailingCommaInArguments:
47 | # If `comma`, the cop requires a comma after the last argument, but only for
48 | # parenthesized method calls where each argument is on its own line.
49 | # If `consistent_comma`, the cop requires a comma after the last argument,
50 | # for all parenthesized method calls with arguments.
51 | EnforcedStyleForMultiline: comma
52 | SupportedStyles:
53 | - comma
54 | - consistent_comma
55 | - no_comma
56 | Style/TrailingCommaInArrayLiteral:
57 | # If `comma`, the cop requires a comma after the last item in an array or
58 | # hash, but only when each item is on its own line.
59 | # If `consistent_comma`, the cop requires a comma after the last item of all
60 | # non-empty array and hash literals.
61 | EnforcedStyleForMultiline: comma
62 | SupportedStyles:
63 | - comma
64 | - consistent_comma
65 | - no_comma
66 | Style/TrailingCommaInHashLiteral:
67 | # If `comma`, the cop requires a comma after the last item in an array or
68 | # hash, but only when each item is on its own line.
69 | # If `consistent_comma`, the cop requires a comma after the last item of all
70 | # non-empty array and hash literals.
71 | EnforcedStyleForMultiline: comma
72 | SupportedStyles:
73 | - comma
74 | - consistent_comma
75 | - no_comma
76 |
77 | Style/StringLiterals:
78 | EnforcedStyle: double_quotes
79 | SupportedStyles:
80 | - single_quotes
81 | - double_quotes
82 | # If true, strings which span multiple lines using \ for continuation must
83 | # use the same type of quotes on each line.
84 | ConsistentQuotesInMultiline: false
85 |
86 | Style/StringLiteralsInInterpolation:
87 | EnforcedStyle: double_quotes
88 | SupportedStyles:
89 | - single_quotes
90 | - double_quotes
91 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.4.7
4 | - 2.5.5
5 | - 2.6.4
6 | gemfile:
7 | - test_rails_app/gemfiles/rails_4.2.gemfile
8 | - test_rails_app/gemfiles/rails_5.2.gemfile
9 | - test_rails_app/gemfiles/rails_6.0.gemfile
10 | env:
11 | global:
12 | TRAVIS: true
13 | sudo: false
14 | cache: bundler
15 | CODECLIMATE_REPO_TOKEN: 11158e372b49d660cd14d15f351b0326e7bcdd29e7e31f271a2055530212f3e3
16 | matrix:
17 | exclude:
18 | - rvm: 2.4.7
19 | gemfile: test_rails_app/gemfiles/rails_6.0.gemfile
20 |
--------------------------------------------------------------------------------
/Cheffile:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 |
4 | site "http://community.opscode.com/api/v1"
5 |
6 | cookbook "apt"
7 | cookbook "build-essential", {}
8 | cookbook "rvm", :github => "fnichol/chef-rvm", :ref => "v0.9.0", "rubies" => ["2.1.7", "2.2.3"]
9 | cookbook "sqlite", {}
10 | cookbook "git", {}
11 |
--------------------------------------------------------------------------------
/Cheffile.lock:
--------------------------------------------------------------------------------
1 | SITE
2 | remote: http://community.opscode.com/api/v1
3 | specs:
4 | apt (2.8.2)
5 | build-essential (2.2.4)
6 | chef_handler (1.2.0)
7 | dmg (2.2.2)
8 | git (4.3.4)
9 | build-essential (>= 0.0.0)
10 | dmg (>= 0.0.0)
11 | windows (>= 0.0.0)
12 | yum-epel (>= 0.0.0)
13 | sqlite (1.1.2)
14 | windows (1.38.2)
15 | chef_handler (>= 0.0.0)
16 | yum (3.8.1)
17 | yum-epel (0.6.3)
18 | yum (~> 3.2)
19 |
20 | GIT
21 | remote: https://github.com/fnichol/chef-rvm
22 | ref: v0.9.0
23 | sha: 4a408e5d6c5a52c37388a799c516430263339849
24 | specs:
25 | rvm (0.9.0)
26 |
27 | DEPENDENCIES
28 | apt (>= 0)
29 | build-essential (>= 0)
30 | git (>= 0)
31 | rvm (>= 0)
32 | sqlite (>= 0)
33 |
34 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | source "https://rubygems.org"
3 | gem "rails"
4 | gem "sqlite3"
5 | gem "appraisal"
6 |
7 | group :development, :test do
8 | gem "rspec"
9 | gem "rspec-rails"
10 | end
11 | gem "codeclimate-test-reporter", require: nil
12 | # Specify your gem's dependencies in active_mocker.gemspec
13 | gemspec
14 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
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.
23 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rubygems"
3 | require "bundler/setup"
4 | require "bundler/gem_tasks"
5 | Dir.glob("tasks/*.rake").each { |r| import r }
6 |
7 | task default: "specs"
8 |
9 | desc "run setup and tests"
10 | task :specs do
11 | Rake::Task["setup"].invoke
12 | Rake::Task["unit"].invoke
13 | Rake::Task["integration"].invoke
14 | end
15 |
16 | desc "run tests"
17 | task :test do
18 | if ENV["TRAVIS"]
19 | require "codeclimate-test-reporter"
20 | CodeClimate::TestReporter.start
21 | end
22 |
23 | Rake::Task["unit"].invoke
24 | Rake::Task["integration"].invoke
25 | end
26 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | # frozen_string_literal: true
3 | # This file originally created at http://rove.io/70b9e033e9d63eea7548469647e3efd3
4 |
5 | # -*- mode: ruby -*-
6 | # vi: set ft=ruby :
7 |
8 | Vagrant.configure("2") do |config|
9 | config.vm.box = "opscode-ubuntu-12.04_chef-11.4.0"
10 | config.vm.box_url = "https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_chef-11.4.0.box"
11 | config.ssh.forward_agent = true
12 |
13 | config.vm.network :forwarded_port, guest: 3000, host: 3000
14 |
15 | config.vm.provision :chef_solo do |chef|
16 | chef.cookbooks_path = ["cookbooks"]
17 | chef.add_recipe :apt
18 | chef.add_recipe "rvm::vagrant"
19 | chef.add_recipe "rvm::system"
20 | chef.add_recipe "sqlite"
21 | chef.add_recipe "git"
22 | chef.json = {
23 | git: {
24 | prefix: "/usr/local",
25 | },
26 | }
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/active_mocker.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | # frozen_string_literal: true
3 | lib = File.expand_path("../lib", __FILE__)
4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5 | require "active_mocker/version"
6 |
7 | Gem::Specification.new do |spec|
8 | spec.name = "active_mocker"
9 | spec.version = ActiveMocker::VERSION
10 | spec.authors = ["Dustin Zeisler"]
11 | spec.email = ["dustin@zeisler.net"]
12 | spec.summary = "Creates stub classes from any ActiveRecord model"
13 | spec.description = "Creates stub classes from any ActiveRecord model. By using stubs in your tests you don't need to load Rails or the database, sometimes resulting in a 10x speed improvement. ActiveMocker analyzes the methods and database columns to generate a Ruby class file. The stub file can be run standalone and comes included with many useful parts of ActiveRecord. Stubbed out methods contain their original argument signatures or ActiveMocker friendly code can be brought over in its entirety. Mocks are regenerated when the schema is modified so your mocks won't go stale, preventing the case where your unit tests pass but production code fails."
14 | spec.homepage = "https://github.com/zeisler/active_mocker"
15 | spec.license = "MIT"
16 |
17 | spec.files = Dir["CHANGELOG.md", "LICENSE.txt", "README.md", "lib/**/*"]
18 |
19 | spec.require_paths = ["lib"]
20 |
21 | spec.required_ruby_version = ">= 2.3"
22 |
23 | spec.add_runtime_dependency "activesupport", ">= 4.2"
24 | spec.add_runtime_dependency "virtus", "~> 1.0"
25 | spec.add_runtime_dependency "ruby-progressbar", "~> 1.7"
26 | spec.add_runtime_dependency "colorize", "~> 0.7", ">= 0.7"
27 | spec.add_runtime_dependency "rake", ">= 10.0"
28 | spec.add_runtime_dependency "reverse_parameters", "~> 1.1", ">= 1.1.1"
29 | spec.add_runtime_dependency "active_record_schema_scrapper", "~> 0.8"
30 | spec.add_runtime_dependency "dissociated_introspection", "~> 0.8", ">= 0.8.4"
31 |
32 | spec.add_development_dependency "bundler", "~> 1.10"
33 | spec.add_development_dependency "rubocop", "~> 0.49.0"
34 | spec.add_development_dependency "rspec", "~> 3.4"
35 | end
36 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require "bundler/setup"
5 | require "active_mocker"
6 |
7 | # You can add fixtures and/or initialization code here to make experimenting
8 | # with your gem easier. You can also use a different console, if you like.
9 |
10 | # (If you use this, don't forget to add pry to your Gemfile!)
11 | # require "pry"
12 | # Pry.start
13 |
14 | require "irb"
15 | IRB.start
16 |
--------------------------------------------------------------------------------
/codeclimate.yml:
--------------------------------------------------------------------------------
1 | languages:
2 | Ruby: true
3 | exclude_paths:
4 | - sample_app_rails_4/**/*
5 | - test_rails_app/**/*
6 | - spec/**/*
7 |
--------------------------------------------------------------------------------
/example_rails_app/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 |
10 | # Ignore the default SQLite database.
11 | /db/*.sqlite3
12 | /db/*.sqlite3-journal
13 |
14 | # Ignore all logfiles and tempfiles.
15 | /log/*.log
16 | /tmp
17 |
--------------------------------------------------------------------------------
/example_rails_app/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --warnings
3 | --require spec_helper
4 |
--------------------------------------------------------------------------------
/example_rails_app/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | source "https://rubygems.org"
3 | gem "rails", "~>4.2"
4 | gem "sqlite3"
5 | group :development, :test do
6 | # gem 'active_mocker', '~>1.7'
7 | gem "active_mocker", path: "../"
8 | gem "rspec-rails", "~> 3.0"
9 | end
10 |
--------------------------------------------------------------------------------
/example_rails_app/README.rdoc:
--------------------------------------------------------------------------------
1 | == README
2 |
3 | This README would normally document whatever steps are necessary to get the
4 | application up and running.
5 |
6 | Things you may want to cover:
7 |
8 | * Ruby version
9 |
10 | * System dependencies
11 |
12 | * Configuration
13 |
14 | * Database creation
15 |
16 | * Database initialization
17 |
18 | * How to run the test suite
19 |
20 | * Services (job queues, cache servers, search engines, etc.)
21 |
22 | * Deployment instructions
23 |
24 | * ...
25 |
26 |
27 | Please feel free to use a different markup language if you do not plan to run
28 | rake doc:app.
29 |
--------------------------------------------------------------------------------
/example_rails_app/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path("../config/application", __FILE__)
6 |
7 | Rails.application.load_tasks
8 |
--------------------------------------------------------------------------------
/example_rails_app/app/assets/images/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/app/assets/images/.keep
--------------------------------------------------------------------------------
/example_rails_app/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6 | //
7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | // compiled file.
9 | //
10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11 | // about supported directives.
12 | //
13 | //= require jquery
14 | //= require jquery_ujs
15 | //= require turbolinks
16 | //= require_tree .
17 |
--------------------------------------------------------------------------------
/example_rails_app/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9 | * compiled file so the styles you add here take precedence over styles defined in any styles
10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11 | * file per style scope.
12 | *
13 | *= require_tree .
14 | *= require_self
15 | */
16 |
--------------------------------------------------------------------------------
/example_rails_app/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class ApplicationController < ActionController::Base
3 | # Prevent CSRF attacks by raising an exception.
4 | # For APIs, you may want to use :null_session instead.
5 | protect_from_forgery with: :exception
6 | end
7 |
--------------------------------------------------------------------------------
/example_rails_app/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/example_rails_app/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ApplicationHelper
3 | end
4 |
--------------------------------------------------------------------------------
/example_rails_app/app/mailers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/app/mailers/.keep
--------------------------------------------------------------------------------
/example_rails_app/app/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/app/models/.keep
--------------------------------------------------------------------------------
/example_rails_app/app/models/comment.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class Comment < ActiveRecord::Base
3 | belongs_to :user
4 | end
5 |
--------------------------------------------------------------------------------
/example_rails_app/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/app/models/concerns/.keep
--------------------------------------------------------------------------------
/example_rails_app/app/models/subscription.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class Subscription < ActiveRecord::Base
3 | belongs_to :user
4 | end
5 |
--------------------------------------------------------------------------------
/example_rails_app/app/models/user.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class User < ActiveRecord::Base
3 | has_many :comments
4 | has_many :subscriptions
5 | end
6 |
--------------------------------------------------------------------------------
/example_rails_app/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ExampleRailsApp
5 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
6 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
7 | <%= csrf_meta_tags %>
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example_rails_app/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4 | load Gem.bin_path("bundler", "bundle")
5 |
--------------------------------------------------------------------------------
/example_rails_app/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | begin
4 | load File.expand_path("../spring", __FILE__)
5 | rescue LoadError
6 | end
7 | APP_PATH = File.expand_path("../../config/application", __FILE__)
8 | require_relative "../config/boot"
9 | require "rails/commands"
10 |
--------------------------------------------------------------------------------
/example_rails_app/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | begin
4 | load File.expand_path("../spring", __FILE__)
5 | rescue LoadError
6 | end
7 | require_relative "../config/boot"
8 | require "rake"
9 | Rake.application.run
10 |
--------------------------------------------------------------------------------
/example_rails_app/bin/spring:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | # This file loads spring without using Bundler, in order to be fast
5 | # It gets overwritten when you run the `spring binstub` command
6 |
7 | unless defined?(Spring)
8 | require "rubygems"
9 | require "bundler"
10 |
11 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m)
12 | ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR)
13 | ENV["GEM_HOME"] = ""
14 | Gem.paths = ENV
15 |
16 | gem "spring", match[1]
17 | require "spring/binstub"
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/example_rails_app/config.ru:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # This file is used by Rack-based servers to start the application.
3 |
4 | require ::File.expand_path("../config/environment", __FILE__)
5 | run Rails.application
6 |
--------------------------------------------------------------------------------
/example_rails_app/config/application.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require File.expand_path("../boot", __FILE__)
3 |
4 | require "rails/all"
5 |
6 | # Require the gems listed in Gemfile, including any gems
7 | # you've limited to :test, :development, or :production.
8 | Bundler.require(*Rails.groups)
9 |
10 | module ExampleRailsApp
11 | class Application < Rails::Application
12 | # Settings in config/environments/* take precedence over those specified here.
13 | # Application configuration should go into files in config/initializers
14 | # -- all .rb files in that directory are automatically loaded.
15 |
16 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
17 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
18 | # config.time_zone = 'Central Time (US & Canada)'
19 |
20 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
21 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
22 | # config.i18n.default_locale = :de
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/example_rails_app/config/boot.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Set up gems listed in the Gemfile.
3 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4 |
5 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
6 |
--------------------------------------------------------------------------------
/example_rails_app/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | #
7 | default: &default
8 | adapter: sqlite3
9 | pool: 5
10 | timeout: 5000
11 |
12 | development:
13 | <<: *default
14 | database: db/development.sqlite3
15 |
16 | # Warning: The database defined as "test" will be erased and
17 | # re-generated from your development database when you run "rake".
18 | # Do not set this db to the same as development or production.
19 | test:
20 | <<: *default
21 | database: db/test.sqlite3
22 |
23 | production:
24 | <<: *default
25 | database: db/production.sqlite3
26 |
--------------------------------------------------------------------------------
/example_rails_app/config/environment.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Load the Rails application.
3 | require File.expand_path("../application", __FILE__)
4 |
5 | # Initialize the Rails application.
6 | Rails.application.initialize!
7 |
--------------------------------------------------------------------------------
/example_rails_app/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | Rails.application.configure do
3 | # Settings specified here will take precedence over those in config/application.rb.
4 |
5 | # In the development environment your application's code is reloaded on
6 | # every request. This slows down response time but is perfect for development
7 | # since you don't have to restart the web server when you make code changes.
8 | config.cache_classes = false
9 |
10 | # Do not eager load code on boot.
11 | config.eager_load = false
12 |
13 | # Show full error reports and disable caching.
14 | config.consider_all_requests_local = true
15 | config.action_controller.perform_caching = false
16 |
17 | # Don't care if the mailer can't send.
18 | config.action_mailer.raise_delivery_errors = false
19 |
20 | # Print deprecation notices to the Rails logger.
21 | config.active_support.deprecation = :log
22 |
23 | # Raise an error on page load if there are pending migrations.
24 | config.active_record.migration_error = :page_load
25 |
26 | # Debug mode disables concatenation and preprocessing of assets.
27 | # This option may cause significant delays in view rendering with a large
28 | # number of complex assets.
29 | config.assets.debug = true
30 |
31 | # Adds additional error checking when serving assets at runtime.
32 | # Checks for improperly declared sprockets dependencies.
33 | # Raises helpful error messages.
34 | config.assets.raise_runtime_errors = true
35 |
36 | # Raises error for missing translations
37 | # config.action_view.raise_on_missing_translations = true
38 | end
39 |
--------------------------------------------------------------------------------
/example_rails_app/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | Rails.application.configure do
3 | # Settings specified here will take precedence over those in config/application.rb.
4 |
5 | # Code is not reloaded between requests.
6 | config.cache_classes = true
7 |
8 | # Eager load code on boot. This eager loads most of Rails and
9 | # your application in memory, allowing both threaded web servers
10 | # and those relying on copy on write to perform better.
11 | # Rake tasks automatically ignore this option for performance.
12 | config.eager_load = true
13 |
14 | # Full error reports are disabled and caching is turned on.
15 | config.consider_all_requests_local = false
16 | config.action_controller.perform_caching = true
17 |
18 | # Enable Rack::Cache to put a simple HTTP cache in front of your application
19 | # Add `rack-cache` to your Gemfile before enabling this.
20 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
21 | # config.action_dispatch.rack_cache = true
22 |
23 | # Disable Rails's static asset server (Apache or nginx will already do this).
24 |
25 | # Compress JavaScripts and CSS.
26 | config.assets.js_compressor = :uglifier
27 | # config.assets.css_compressor = :sass
28 |
29 | # Do not fallback to assets pipeline if a precompiled asset is missed.
30 | config.assets.compile = false
31 |
32 | # Generate digests for assets URLs.
33 | config.assets.digest = true
34 |
35 | # `config.assets.precompile` has moved to config/initializers/assets.rb
36 |
37 | # Specifies the header that your server uses for sending files.
38 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
39 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
40 |
41 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
42 | # config.force_ssl = true
43 |
44 | # Set to :debug to see everything in the log.
45 | config.log_level = :info
46 |
47 | # Prepend all log lines with the following tags.
48 | # config.log_tags = [ :subdomain, :uuid ]
49 |
50 | # Use a different logger for distributed setups.
51 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
52 |
53 | # Use a different cache store in production.
54 | # config.cache_store = :mem_cache_store
55 |
56 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
57 | # config.action_controller.asset_host = "http://assets.example.com"
58 |
59 | # Precompile additional assets.
60 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
61 | # config.assets.precompile += %w( search.js )
62 |
63 | # Ignore bad email addresses and do not raise email delivery errors.
64 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
65 | # config.action_mailer.raise_delivery_errors = false
66 |
67 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
68 | # the I18n.default_locale when a translation cannot be found).
69 | config.i18n.fallbacks = true
70 |
71 | # Send deprecation notices to registered listeners.
72 | config.active_support.deprecation = :notify
73 |
74 | # Disable automatic flushing of the log to improve performance.
75 | # config.autoflush_log = false
76 |
77 | # Use default logging formatter so that PID and timestamp are not suppressed.
78 | config.log_formatter = ::Logger::Formatter.new
79 |
80 | # Do not dump schema after migrations.
81 | config.active_record.dump_schema_after_migration = false
82 | end
83 |
--------------------------------------------------------------------------------
/example_rails_app/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | Rails.application.configure do
3 | # Settings specified here will take precedence over those in config/application.rb.
4 |
5 | # The test environment is used exclusively to run your application's
6 | # test suite. You never need to work with it otherwise. Remember that
7 | # your test database is "scratch space" for the test suite and is wiped
8 | # and recreated between test runs. Don't rely on the data there!
9 | config.cache_classes = true
10 |
11 | # Do not eager load code on boot. This avoids loading your whole application
12 | # just for the purpose of running a single test. If you are using a tool that
13 | # preloads Rails for running tests, you may have to set it to true.
14 | config.eager_load = false
15 |
16 | # Configure static asset server for tests with Cache-Control for performance.
17 | # Show full error reports and disable caching.
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates.
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment.
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Print deprecation notices to the stderr.
33 | config.active_support.deprecation = :stderr
34 |
35 | # Raises error for missing translations
36 | # config.action_view.raise_on_missing_translations = true
37 | end
38 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Version of your assets, change this if you want to expire all your assets.
5 | Rails.application.config.assets.version = "1.0"
6 |
7 | # Precompile additional assets.
8 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
9 | # Rails.application.config.assets.precompile += %w( search.js )
10 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
5 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
6 |
7 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
8 | # Rails.backtrace_cleaner.remove_silencers!
9 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | Rails.application.config.action_dispatch.cookies_serializer = :json
5 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Configure sensitive parameters which will be filtered from the log file.
5 | Rails.application.config.filter_parameters += [:password]
6 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Add new inflection rules using the following format. Inflections
5 | # are locale specific, and you may define rules for as many different
6 | # locales as you wish. All of these examples are active by default:
7 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
8 | # inflect.plural /^(ox)$/i, '\1en'
9 | # inflect.singular /^(ox)en/i, '\1'
10 | # inflect.irregular 'person', 'people'
11 | # inflect.uncountable %w( fish sheep )
12 | # end
13 |
14 | # These inflection rules are supported but not enabled by default:
15 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
16 | # inflect.acronym 'RESTful'
17 | # end
18 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Add new mime types for use in respond_to blocks:
5 | # Mime::Type.register "text/richtext", :rtf
6 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | Rails.application.config.session_store :cookie_store, key: "_example_rails_app_session"
5 |
--------------------------------------------------------------------------------
/example_rails_app/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # This file contains settings for ActionController::ParamsWrapper which
5 | # is enabled by default.
6 |
7 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
8 | ActiveSupport.on_load(:action_controller) do
9 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
10 | end
11 |
12 | # To enable root element in JSON for ActiveRecord objects.
13 | # ActiveSupport.on_load(:active_record) do
14 | # self.include_root_in_json = true
15 | # end
16 |
--------------------------------------------------------------------------------
/example_rails_app/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
--------------------------------------------------------------------------------
/example_rails_app/config/routes.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | Rails.application.routes.draw do
3 | # The priority is based upon order of creation: first created -> highest priority.
4 | # See how all your routes lay out with "rake routes".
5 |
6 | # You can have the root of your site routed with "root"
7 | # root 'welcome#index'
8 |
9 | # Example of regular route:
10 | # get 'products/:id' => 'catalog#view'
11 |
12 | # Example of named route that can be invoked with purchase_url(id: product.id)
13 | # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
14 |
15 | # Example resource route (maps HTTP verbs to controller actions automatically):
16 | # resources :products
17 |
18 | # Example resource route with options:
19 | # resources :products do
20 | # member do
21 | # get 'short'
22 | # post 'toggle'
23 | # end
24 | #
25 | # collection do
26 | # get 'sold'
27 | # end
28 | # end
29 |
30 | # Example resource route with sub-resources:
31 | # resources :products do
32 | # resources :comments, :sales
33 | # resource :seller
34 | # end
35 |
36 | # Example resource route with more complex sub-resources:
37 | # resources :products do
38 | # resources :comments
39 | # resources :sales do
40 | # get 'recent', on: :collection
41 | # end
42 | # end
43 |
44 | # Example resource route with concerns:
45 | # concern :toggleable do
46 | # post 'toggle'
47 | # end
48 | # resources :posts, concerns: :toggleable
49 | # resources :photos, concerns: :toggleable
50 |
51 | # Example resource route within a namespace:
52 | # namespace :admin do
53 | # # Directs /admin/products/* to Admin::ProductsController
54 | # # (app/controllers/admin/products_controller.rb)
55 | # resources :products
56 | # end
57 | end
58 |
--------------------------------------------------------------------------------
/example_rails_app/config/secrets.yml:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key is used for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 |
6 | # Make sure the secret is at least 30 characters and all random,
7 | # no regular words or you'll be exposed to dictionary attacks.
8 | # You can use `rake secret` to generate a secure secret key.
9 |
10 | # Make sure the secrets in this file are kept private
11 | # if you're sharing your code publicly.
12 |
13 | development:
14 | secret_key_base: a2dc302bb4671539b54a76a4d96189a12465ea63b2acb2ebf570e5ae90c0af60621d1dae0937eb16f011f97a6dc27a356cae450cd0d1ecea6b5226542c7392cb
15 |
16 | test:
17 | secret_key_base: 4ee7095421864869816c474292a05a760647f06468a3363fdf9a1f41387d9787e058264c8da775f1ed80bf603dbe64ef58cd5dbf26b51cf09109c678a5ca3b50
18 |
19 | # Do not keep production secrets in the repository,
20 | # instead read values from the environment.
21 | production:
22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
23 |
--------------------------------------------------------------------------------
/example_rails_app/db/migrate/20140731143902_create_users.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class CreateUsers < ActiveRecord::Migration
3 | def change
4 | create_table :users do |t|
5 | t.string :name
6 | t.integer :age
7 | t.boolean :admin
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/example_rails_app/db/migrate/20140731143955_create_comments.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class CreateComments < ActiveRecord::Migration
3 | def change
4 | create_table :comments do |t|
5 | t.integer :user_id
6 | t.string :text
7 | t.integer :votes
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/example_rails_app/db/migrate/20140731144123_create_subscriptions.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class CreateSubscriptions < ActiveRecord::Migration
3 | def change
4 | create_table :subscriptions do |t|
5 | t.string :type
6 | t.integer :user_id
7 | t.boolean :active
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/example_rails_app/db/schema.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 | # frozen_string_literal: true
3 | # This file is auto-generated from the current state of the database. Instead
4 | # of editing this file, please use the migrations feature of Active Record to
5 | # incrementally modify your database, and then regenerate this schema definition.
6 | #
7 | # Note that this schema.rb definition is the authoritative source for your
8 | # database schema. If you need to create the application database on another
9 | # system, you should be using db:schema:load, not running all the migrations
10 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
11 | # you'll amass, the slower it'll run and the greater likelihood for issues).
12 | #
13 | # It's strongly recommended that you check this file into your version control system.
14 |
15 | ActiveRecord::Schema.define(version: 20_140_731_144_123) do
16 | create_table "comments", force: true do |t|
17 | t.integer "user_id"
18 | t.string "text"
19 | t.integer "votes"
20 | t.datetime "created_at"
21 | t.datetime "updated_at"
22 | end
23 |
24 | create_table "subscriptions", force: true do |t|
25 | t.string "kind"
26 | t.integer "user_id"
27 | t.boolean "active"
28 | t.datetime "created_at"
29 | t.datetime "updated_at"
30 | end
31 |
32 | create_table "users", force: true do |t|
33 | t.string "name"
34 | t.integer "age"
35 | t.boolean "admin"
36 | t.datetime "created_at"
37 | t.datetime "updated_at"
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/example_rails_app/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # This file should contain all the record creation needed to seed the database with its default values.
3 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
4 | #
5 | # Examples:
6 | #
7 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
8 | # Mayor.create(name: 'Emanuel', city: cities.first)
9 |
--------------------------------------------------------------------------------
/example_rails_app/example_rails_app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/example_rails_app/lib/assets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/lib/assets/.keep
--------------------------------------------------------------------------------
/example_rails_app/lib/subscribe_user.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class SubscribeUser
3 | attr_accessor :user
4 |
5 | def initialize(user: user)
6 | @user = user
7 | end
8 |
9 | def with_yearly
10 | Subscription.create(user: user, kind: "yearly")
11 | end
12 |
13 | def with_monthly
14 | Subscription.create(user: user, kind: "monthly")
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/example_rails_app/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/lib/tasks/.keep
--------------------------------------------------------------------------------
/example_rails_app/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/log/.keep
--------------------------------------------------------------------------------
/example_rails_app/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/example_rails_app/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/example_rails_app/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/example_rails_app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/public/favicon.ico
--------------------------------------------------------------------------------
/example_rails_app/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/example_rails_app/spec/lib/subscribe_user_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "lib/subscribe_user"
4 | require "spec/mocks/user_mock"
5 | require "spec/mocks/subscription_mock"
6 |
7 | RSpec.describe SubscribeUser, active_mocker: true do
8 | let(:user) { User.create }
9 |
10 | subject { described_class.new(user: user) }
11 |
12 | describe "with_yearly" do
13 | it do
14 | subject.with_yearly
15 | expect(
16 | Subscription.where(user: user,
17 | kind: "yearly").count,
18 | ).to eq 1
19 | end
20 | end
21 |
22 | describe "with_monthly" do
23 | it do
24 | subject.with_monthly
25 | expect(Subscription.where(user: user, kind: "monthly").count).to eq 1
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/example_rails_app/spec/mocks/comment_mock.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "active_mocker/mock"
3 |
4 | class CommentMock < ActiveMocker::Mock::Base
5 | created_with("2.0.0-alpha.0")
6 | # _modules_constants.erb
7 |
8 | # _class_methods.erb
9 | class << self
10 | def attributes
11 | @attributes ||= HashWithIndifferentAccess.new("id" => nil, "user_id" => nil, "text" => nil, "votes" => nil, "created_at" => nil, "updated_at" => nil).merge(super)
12 | end
13 |
14 | def types
15 | @types ||= ActiveMocker::HashProcess.new({ id: Fixnum, user_id: Fixnum, text: String, votes: Fixnum, created_at: DateTime, updated_at: DateTime }, method(:build_type)).merge(super)
16 | end
17 |
18 | def associations
19 | @associations ||= { user: nil }.merge(super)
20 | end
21 |
22 | def associations_by_class
23 | @associations_by_class ||= { User: { belongs_to: [:user] } }.merge(super)
24 | end
25 |
26 | def mocked_class
27 | "Comment"
28 | end
29 |
30 | private :mocked_class
31 |
32 | def attribute_names
33 | @attribute_names ||= %w(id user_id text votes created_at updated_at) | super
34 | end
35 |
36 | def primary_key
37 | "id"
38 | end
39 |
40 | def abstract_class?
41 | false
42 | end
43 |
44 | def table_name
45 | "comments" || super
46 | end
47 | end
48 | # _attributes.erb
49 | def id
50 | read_attribute(:id)
51 | end
52 |
53 | def id=(val)
54 | write_attribute(:id, val)
55 | end
56 |
57 | def user_id
58 | read_attribute(:user_id)
59 | end
60 |
61 | def user_id=(val)
62 | write_attribute(:user_id, val)
63 | end
64 |
65 | def text
66 | read_attribute(:text)
67 | end
68 |
69 | def text=(val)
70 | write_attribute(:text, val)
71 | end
72 |
73 | def votes
74 | read_attribute(:votes)
75 | end
76 |
77 | def votes=(val)
78 | write_attribute(:votes, val)
79 | end
80 |
81 | def created_at
82 | read_attribute(:created_at)
83 | end
84 |
85 | def created_at=(val)
86 | write_attribute(:created_at, val)
87 | end
88 |
89 | def updated_at
90 | read_attribute(:updated_at)
91 | end
92 |
93 | def updated_at=(val)
94 | write_attribute(:updated_at, val)
95 | end
96 |
97 | # _associations.erb
98 |
99 | # belongs_to
100 | def user
101 | read_association(:user) || write_association(:user, classes("User").try { |k| k.find_by(id: user_id) })
102 | end
103 |
104 | def user=(val)
105 | write_association(:user, val)
106 | ActiveMocker::BelongsTo.new(val, child_self: self, foreign_key: :user_id).item
107 | end
108 |
109 | def build_user(attributes = {}, &block)
110 | association = classes("User").try(:new, attributes, &block)
111 | write_association(:user, association) unless association.nil?
112 | end
113 |
114 | def create_user(attributes = {}, &block)
115 | association = classes("User").try(:create, attributes, &block)
116 | write_association(:user, association) unless association.nil?
117 | end
118 | alias create_user! create_user
119 |
120 | # _scopes.erb
121 | module Scopes
122 | include ActiveMocker::Base::Scopes
123 | end
124 |
125 | extend Scopes
126 |
127 | class ScopeRelation < ActiveMocker::Association
128 | include CommentMock::Scopes
129 | end
130 |
131 | def self.__new_relation__(collection)
132 | CommentMock::ScopeRelation.new(collection)
133 | end
134 |
135 | private_class_method :__new_relation__
136 | end
137 |
--------------------------------------------------------------------------------
/example_rails_app/spec/mocks/subscription_mock.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "active_mocker/mock"
3 |
4 | class SubscriptionMock < ActiveMocker::Base
5 | created_with("2.0.0-alpha.0")
6 | # _modules_constants.erb
7 |
8 | # _class_methods.erb
9 | class << self
10 | def attributes
11 | @attributes ||= HashWithIndifferentAccess.new("id" => nil, "kind" => nil, "user_id" => nil, "active" => nil, "created_at" => nil, "updated_at" => nil).merge(super)
12 | end
13 |
14 | def types
15 | @types ||= ActiveMocker::HashProcess.new({ id: Fixnum, kind: String, user_id: Fixnum, active: Axiom::Types::Boolean, created_at: DateTime, updated_at: DateTime }, method(:build_type)).merge(super)
16 | end
17 |
18 | def associations
19 | @associations ||= { user: nil }.merge(super)
20 | end
21 |
22 | def associations_by_class
23 | @associations_by_class ||= { User: { belongs_to: [:user] } }.merge(super)
24 | end
25 |
26 | def mocked_class
27 | "Subscription"
28 | end
29 |
30 | private :mocked_class
31 |
32 | def attribute_names
33 | @attribute_names ||= %w(id kind user_id active created_at updated_at) | super
34 | end
35 |
36 | def primary_key
37 | "id"
38 | end
39 |
40 | def abstract_class?
41 | false
42 | end
43 |
44 | def table_name
45 | "subscriptions" || super
46 | end
47 | end
48 | # _attributes.erb
49 | def id
50 | read_attribute(:id)
51 | end
52 |
53 | def id=(val)
54 | write_attribute(:id, val)
55 | end
56 |
57 | def kind
58 | read_attribute(:kind)
59 | end
60 |
61 | def kind=(val)
62 | write_attribute(:kind, val)
63 | end
64 |
65 | def user_id
66 | read_attribute(:user_id)
67 | end
68 |
69 | def user_id=(val)
70 | write_attribute(:user_id, val)
71 | end
72 |
73 | def active
74 | read_attribute(:active)
75 | end
76 |
77 | def active=(val)
78 | write_attribute(:active, val)
79 | end
80 |
81 | def created_at
82 | read_attribute(:created_at)
83 | end
84 |
85 | def created_at=(val)
86 | write_attribute(:created_at, val)
87 | end
88 |
89 | def updated_at
90 | read_attribute(:updated_at)
91 | end
92 |
93 | def updated_at=(val)
94 | write_attribute(:updated_at, val)
95 | end
96 |
97 | # _associations.erb
98 |
99 | # belongs_to
100 | def user
101 | read_association(:user) || write_association(:user, classes("User").try { |k| k.find_by(id: user_id) })
102 | end
103 |
104 | def user=(val)
105 | write_association(:user, val)
106 | ActiveMocker::BelongsTo.new(val, child_self: self, foreign_key: :user_id).item
107 | end
108 |
109 | def build_user(attributes = {}, &block)
110 | association = classes("User").try(:new, attributes, &block)
111 | write_association(:user, association) unless association.nil?
112 | end
113 |
114 | def create_user(attributes = {}, &block)
115 | association = classes("User").try(:create, attributes, &block)
116 | write_association(:user, association) unless association.nil?
117 | end
118 | alias create_user! create_user
119 |
120 | # _scopes.erb
121 | module Scopes
122 | include ActiveMocker::Base::Scopes
123 | end
124 |
125 | extend Scopes
126 |
127 | class ScopeRelation < ActiveMocker::Association
128 | include SubscriptionMock::Scopes
129 | end
130 |
131 | def self.__new_relation__(collection)
132 | SubscriptionMock::ScopeRelation.new(collection)
133 | end
134 |
135 | private_class_method :__new_relation__
136 | end
137 |
--------------------------------------------------------------------------------
/example_rails_app/spec/mocks/user_mock.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "active_mocker/mock"
3 |
4 | class UserMock < ActiveMocker::Base
5 | created_with("2.0.0-alpha.0")
6 | # _modules_constants.erb
7 |
8 | # _class_methods.erb
9 | class << self
10 | def attributes
11 | @attributes ||= HashWithIndifferentAccess.new("id" => nil, "name" => nil, "age" => nil, "admin" => nil, "created_at" => nil, "updated_at" => nil).merge(super)
12 | end
13 |
14 | def types
15 | @types ||= ActiveMocker::HashProcess.new({ id: Fixnum, name: String, age: Fixnum, admin: Axiom::Types::Boolean, created_at: DateTime, updated_at: DateTime }, method(:build_type)).merge(super)
16 | end
17 |
18 | def associations
19 | @associations ||= { comments: nil, subscriptions: nil }.merge(super)
20 | end
21 |
22 | def associations_by_class
23 | @associations_by_class ||= { Comment: { has_many: [:comments] }, Subscription: { has_many: [:subscriptions] } }.merge(super)
24 | end
25 |
26 | def mocked_class
27 | "User"
28 | end
29 |
30 | private :mocked_class
31 |
32 | def attribute_names
33 | @attribute_names ||= %w(id name age admin created_at updated_at) | super
34 | end
35 |
36 | def primary_key
37 | "id"
38 | end
39 |
40 | def abstract_class?
41 | false
42 | end
43 |
44 | def table_name
45 | "users" || super
46 | end
47 | end
48 | # _attributes.erb
49 | def id
50 | read_attribute(:id)
51 | end
52 |
53 | def id=(val)
54 | write_attribute(:id, val)
55 | end
56 |
57 | def name
58 | read_attribute(:name)
59 | end
60 |
61 | def name=(val)
62 | write_attribute(:name, val)
63 | end
64 |
65 | def age
66 | read_attribute(:age)
67 | end
68 |
69 | def age=(val)
70 | write_attribute(:age, val)
71 | end
72 |
73 | def admin
74 | read_attribute(:admin)
75 | end
76 |
77 | def admin=(val)
78 | write_attribute(:admin, val)
79 | end
80 |
81 | def created_at
82 | read_attribute(:created_at)
83 | end
84 |
85 | def created_at=(val)
86 | write_attribute(:created_at, val)
87 | end
88 |
89 | def updated_at
90 | read_attribute(:updated_at)
91 | end
92 |
93 | def updated_at=(val)
94 | write_attribute(:updated_at, val)
95 | end
96 |
97 | # _associations.erb
98 |
99 | # has_many
100 | def comments
101 | read_association(:comments, -> { ActiveMocker::HasMany.new([], foreign_key: "user_id", foreign_id: id, relation_class: classes("Comment"), source: "") })
102 | end
103 |
104 | def comments=(val)
105 | write_association(:comments, ActiveMocker::HasMany.new(val, foreign_key: "user_id", foreign_id: id, relation_class: classes("Comment"), source: ""))
106 | end
107 |
108 | def subscriptions
109 | read_association(:subscriptions, -> { ActiveMocker::HasMany.new([], foreign_key: "user_id", foreign_id: id, relation_class: classes("Subscription"), source: "") })
110 | end
111 |
112 | def subscriptions=(val)
113 | write_association(:subscriptions, ActiveMocker::HasMany.new(val, foreign_key: "user_id", foreign_id: id, relation_class: classes("Subscription"), source: ""))
114 | end
115 |
116 | # _scopes.erb
117 | module Scopes
118 | include ActiveMocker::Base::Scopes
119 | end
120 |
121 | extend Scopes
122 |
123 | class ScopeRelation < ActiveMocker::Association
124 | include UserMock::Scopes
125 | end
126 |
127 | def self.__new_relation__(collection)
128 | UserMock::ScopeRelation.new(collection)
129 | end
130 |
131 | private_class_method :__new_relation__
132 | end
133 |
--------------------------------------------------------------------------------
/example_rails_app/spec/rails_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | ENV["RAILS_ENV"] ||= "test"
3 | require "spec_helper"
4 | require File.expand_path("../../config/environment", __FILE__)
5 | require "rspec/rails"
6 |
7 | Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
8 |
9 | ActiveRecord::Migration.maintain_test_schema!
10 |
11 | RSpec.configure do |config|
12 | config.use_transactional_fixtures = true
13 |
14 | config.infer_spec_type_from_file_location!
15 | end
16 |
--------------------------------------------------------------------------------
/example_rails_app/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | $VERBOSE = nil # This removes ruby warnings
3 | require "active_mocker/rspec_helper"
4 | $LOAD_PATH.unshift File.join(File.expand_path("../../", __FILE__)) # add root of app to path
5 | RSpec.configure do |config|
6 | config.order = "random"
7 | config.mock_framework = :rspec
8 | config.disable_monkey_patching!
9 | config.mock_with :rspec do |mocks|
10 | mocks.syntax = :expect
11 | mocks.verify_doubled_constant_names = true
12 | mocks.verify_partial_doubles = true
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/example_rails_app/vendor/assets/javascripts/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/vendor/assets/javascripts/.keep
--------------------------------------------------------------------------------
/example_rails_app/vendor/assets/stylesheets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/example_rails_app/vendor/assets/stylesheets/.keep
--------------------------------------------------------------------------------
/lib/active_mocker.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # _ _ __ __ _
3 | # /\ | | (_) | \/ | | |
4 | # / \ ___| |_ ___ _____| \ / | ___ ___| | _____ _ __
5 | # / /\ \ / __| __| \ \ / / _ \ |\/| |/ _ \ / __| |/ / _ \ '__|
6 | # / ____ \ (__| |_| |\ V / __/ | | | (_) | (__| < __/ |
7 | # /_/ \_\___|\__|_| \_/ \___|_| |_|\___/ \___|_|\_\___|_|
8 | #
9 | # By Dustin Zeisler
10 |
11 | require "rubygems"
12 | require "active_mocker/version"
13 | require "active_mocker/railtie" if defined?(Rails)
14 | require "forwardable"
15 | require "active_support/all"
16 | require "active_mocker/public_methods"
17 | require "active_mocker/config"
18 | require "reverse_parameters"
19 | require "active_record_schema_scrapper"
20 | require "dissociated_introspection"
21 | require "active_mocker/file_path_to_ruby_class"
22 | require "active_mocker/hash_new_style"
23 | require "active_mocker/null_progress"
24 | require "active_mocker/progress"
25 | require "active_mocker/parent_class"
26 | require "active_mocker/template_creator"
27 | require "active_mocker/mock_creator"
28 | require "active_mocker/mock_creator/associations"
29 | require "active_mocker/mock_creator/attributes"
30 | require "active_mocker/mock_creator/class_methods"
31 | require "active_mocker/mock_creator/defined_methods"
32 | require "active_mocker/mock_creator/modules_constants"
33 | require "active_mocker/mock_creator/recreate_class_method_calls"
34 | require "active_mocker/mock_creator/scopes"
35 | require "active_mocker/mock_creator/mock_build_version"
36 | require "active_mocker/error_object"
37 | require "active_mocker/display_errors"
38 | require "active_mocker/generate"
39 | require "active_mocker/attribute_types/register"
40 | require "active_mocker/attribute_types/enum"
41 | require "active_mocker/attribute"
42 | require "active_mocker/late_inclusion"
43 |
--------------------------------------------------------------------------------
/lib/active_mocker/attribute.rb:
--------------------------------------------------------------------------------
1 | ActiveRecordSchemaScrapper::Attribute.attribute :attribute_writer, String
2 | ActiveRecordSchemaScrapper::Attribute.attribute :attribute_reader, String
3 |
--------------------------------------------------------------------------------
/lib/active_mocker/attribute_types/enum.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "virtus"
3 |
4 | module ActiveMocker
5 | module AttributeTypes
6 | class Enum < Virtus::Attribute
7 | class << self
8 | def build(db_value_type:, table_name:, attribute:, enums:, ignore_value: false)
9 | klass = Class.new(ActiveMocker::AttributeTypes::Enum)
10 | klass.table_name = table_name.to_sym
11 | klass.attribute = attribute.to_sym
12 | klass.ignore_value = ignore_value
13 | enums = if enums.is_a?(Array)
14 | enums.each_with_object({}).with_index { |(k, h), i| h[k] = i }
15 | else
16 | enums
17 | end
18 | klass.key_type = String
19 | klass.db_value_type = db_value_type
20 | klass.enums = Hash[enums.map do |k, v|
21 | [Virtus::Attribute.build(klass.key_type).coerce(k),
22 | Virtus::Attribute.build(klass.db_value_type).coerce(v)]
23 | end]
24 | klass
25 | end
26 |
27 | def to_s
28 | "ActiveMocker::AttributeTypes::Enum.build(ignore_value: #{ignore_value}, db_value_type: #{db_value_type}, table_name: :#{table_name}, attribute: :#{attribute}, enums: #{enums.inspect})"
29 | end
30 |
31 | attr_accessor :enums, :table_name, :attribute, :db_value_type, :key_type, :ignore_value
32 | end
33 |
34 | def coerce(key)
35 | return if key.nil?
36 | coerced_key = key_type.coerce(key)
37 | if key && self.class.enums.key?(coerced_key)
38 | if self.class.ignore_value
39 | coerced_key
40 | else
41 | get_value(key)
42 | end
43 | else
44 | raise ArgumentError, "'#{coerced_key}' is not a valid #{self.class.attribute}"
45 | end
46 | end
47 |
48 | def get_key(value)
49 | self.class.enums.invert[db_value_type.coerce(value)]
50 | end
51 |
52 | def get_value(key)
53 | self.class.enums[key_type.coerce(key)]
54 | end
55 |
56 | def key_type
57 | Virtus::Attribute.build(self.class.key_type)
58 | end
59 |
60 | def db_value_type
61 | Virtus::Attribute.build(self.class.db_value_type)
62 | end
63 | end
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/lib/active_mocker/attribute_types/register.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | ActiveRecordSchemaScrapper::Attributes.register_type(name: :enum, klass: String)
3 |
--------------------------------------------------------------------------------
/lib/active_mocker/config.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class Config
4 | class << self
5 | attr_accessor :model_dir,
6 | :mock_dir,
7 | :single_model_path,
8 | :progress_bar,
9 | :error_verbosity,
10 | :disable_modules_and_constants,
11 | :mock_append_name
12 |
13 | attr_writer :model_base_classes
14 |
15 | # @see ActiveMocker#configure
16 | def set
17 | load_defaults
18 | yield self
19 | end
20 |
21 | def load_defaults
22 | @error_verbosity = 1
23 | @progress_bar = true
24 | @disable_modules_and_constants = false
25 | @model_dir = nil unless @model_dir
26 | @mock_dir = nil unless @mock_dir
27 | @mock_append_name = "Mock"
28 | rails_defaults if Object.const_defined?("Rails")
29 | end
30 |
31 | def reset_all
32 | [:model_dir,
33 | :mock_dir,
34 | :log_location,
35 | :single_model_path,
36 | :progress_bar,
37 | :error_verbosity,
38 | :mock_append_name,
39 | ].each { |ivar| instance_variable_set("@#{ivar}", nil) }
40 | end
41 |
42 | def rails_defaults
43 | @model_dir = File.join(Rails.root, "app/models") unless @model_dir
44 | @mock_dir = File.join(Rails.root, "spec/mocks") unless @mock_dir
45 | end
46 |
47 | def progress_class
48 | @progress_bar ? Progress : NullProgress
49 | end
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/lib/active_mocker/display_errors.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "colorize"
3 | module ActiveMocker
4 | class DisplayErrors
5 | attr_reader :errors, :model_count, :out
6 | attr_accessor :success_count, :failed_models
7 |
8 | def initialize(model_count, out: STDERR)
9 | @errors = []
10 | @success_count = 0
11 | @model_count = model_count
12 | @failed_models = []
13 | @out = out
14 | end
15 |
16 | def add(errors)
17 | @errors.concat([*errors])
18 | end
19 |
20 | def wrap_errors(errors, model_name, type: nil)
21 | add errors.map { |e| ErrorObject.build_from(object: e, class_name: model_name, type: type ? type : e.try(:type)) }
22 | end
23 |
24 | def wrap_an_exception(e, model_name)
25 | add ErrorObject.build_from(exception: e, class_name: model_name)
26 | end
27 |
28 | def uniq_errors
29 | @uniq_errors ||= errors.flatten.compact.uniq.sort_by(&:class_name)
30 | end
31 |
32 | def any_errors?
33 | uniq_errors.count > 0
34 | end
35 |
36 | def display_errors
37 | uniq_errors.each do |e|
38 | next unless ENV["DEBUG"] || !(e.level == :debug)
39 |
40 | display_verbosity_three(e) || display_verbosity_two(e)
41 | end
42 |
43 | display_verbosity_one
44 | end
45 |
46 | def error_summary
47 | display "errors: #{error_count}, warn: #{warn}, info: #{info}"
48 | display "Failed models: #{failed_models.join(", ")}" if failed_models.count > 0
49 | end
50 |
51 | def number_models_mocked
52 | if success_count < model_count || any_errors?
53 | display "Mocked #{success_count} ActiveRecord #{plural("Model", success_count)} out of #{model_count} #{plural("file", model_count)}."
54 | end
55 | end
56 |
57 | private
58 |
59 | def plural(string, count, plural="s")
60 | count > 1 || count.zero? ? "#{string}#{plural}" : string
61 | end
62 |
63 | def display(msg)
64 | out.puts(msg)
65 | end
66 |
67 | def display_verbosity_three(error)
68 | return unless ActiveMocker::Config.error_verbosity == 3
69 |
70 | display_error_header(error)
71 | display error.level
72 |
73 | display_original_error(error)
74 | end
75 |
76 | def display_original_error(e)
77 | original = e.original_error
78 | return unless original
79 |
80 | display original.message.colorize(e.level_color)
81 | display original.backtrace
82 | display original.class.name.colorize(e.level_color)
83 | end
84 |
85 | def display_verbosity_two(e)
86 | return unless ActiveMocker::Config.error_verbosity == 2
87 |
88 | display_error_header(e)
89 | end
90 |
91 | def display_error_header(e)
92 | display "#{e.class_name} has the following errors:"
93 | display e.message.colorize(e.level_color)
94 | end
95 |
96 | def display_verbosity_one
97 | return unless ActiveMocker::Config.error_verbosity > 0
98 |
99 | error_summary if any_errors?
100 |
101 | number_models_mocked
102 |
103 | return unless any_errors?
104 | display "To see more/less detail set ERROR_VERBOSITY = 0, 1, 2, 3"
105 | end
106 |
107 | def error_count
108 | errors_for(:red)
109 | end
110 |
111 | def warn
112 | errors_for(:yellow)
113 | end
114 |
115 | def info
116 | errors_for(:default)
117 | end
118 |
119 | def errors_for(level)
120 | uniq_errors.count { |e| [level].include? e.level_color }
121 | end
122 | end
123 | end
124 |
--------------------------------------------------------------------------------
/lib/active_mocker/error_object.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class ErrorObject
4 | attr_reader :message, :level, :original_error, :type, :class_name
5 |
6 | def initialize(level: :warn, message:, class_name:, type:, original_error: nil)
7 | @level = level
8 | @message = message
9 | @class_name = class_name
10 | @type = type
11 | @original_error = original_error
12 | end
13 |
14 | def self.build_from(object: nil, exception: nil, class_name: nil, type: nil)
15 | if object
16 | args = [:message, :original_error, :level, :type, :class_name].each_with_object({}) do |meth, hash|
17 | hash[meth] = object.public_send(meth) if object.respond_to? meth
18 | end
19 | args[:type] = type unless type.nil?
20 | args[:class_name] = class_name unless class_name.nil?
21 | return new(args)
22 | elsif exception && class_name
23 | return new(message: exception.message,
24 | class_name: class_name,
25 | original_error: exception,
26 | type: type ? type : :standard_error)
27 | end
28 | raise ArgumentError
29 | end
30 |
31 | def original_error?
32 | !original_error.nil?
33 | end
34 |
35 | def level_color
36 | case level
37 | when :standard_error, :fatal, :error
38 | :red
39 | when :warn
40 | :yellow
41 | when :info
42 | :default
43 | end
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/lib/active_mocker/file_path_to_ruby_class.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class FilePathToRubyClass
4 | attr_reader :class_path, :base_path
5 |
6 | def initialize(base_path:, class_path:)
7 | @base_path = base_path
8 | @class_path = class_path
9 | end
10 |
11 | def to_s
12 | File.basename(class_path.gsub(base_path + "/", "").split("/").map(&:camelize).join("::"), ".rb")
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/active_mocker/file_writer.rb:
--------------------------------------------------------------------------------
1 | module ActiveMocker
2 | class FileWriter
3 | include Virtus.model
4 | delegate :name, to: :model, prefix: true
5 |
6 | attribute :model, Object
7 | attribute :file, String
8 | attribute :display_errors
9 | attribute :config
10 | attribute :model_names, Array
11 |
12 | def write!
13 | assure_dir_path_exists!
14 |
15 | safe_write { |f| process!(f) }
16 | end
17 |
18 | private
19 |
20 | def process!(file_out)
21 | result = create_mock(file_out, model)
22 | status = collect_errors(result.errors)
23 |
24 | ok = result.completed? && status.successful?
25 | return unless ok
26 |
27 | display_errors.success_count += 1
28 | end
29 |
30 | def safe_write
31 | File.open(mock_file_path, "w") do |file_out|
32 | begin
33 | yield file_out
34 | rescue StandardError => e
35 | rescue_clean_up(e, file_out)
36 | end
37 | end
38 | end
39 |
40 | def rescue_clean_up(e, file_out)
41 | display_errors.failed_models << model_name
42 | file_out.close unless file_out.closed?
43 | File.delete(file_out.path) if File.exist?(file_out.path)
44 | display_errors.wrap_an_exception(e, model_name)
45 | end
46 |
47 | def scrapper
48 | @scrapper ||= ActiveRecordSchemaScrapper.new(model: model)
49 | end
50 |
51 | def mock_file_path
52 | File.join(Config.mock_dir, mock_file_name)
53 | end
54 |
55 | def mock_file_name
56 | "#{model_name.underscore}_#{config.mock_append_name.underscore}.rb"
57 | end
58 |
59 | def assure_dir_path_exists!
60 | unless File.exist?(File.dirname(mock_file_path))
61 | FileUtils.mkdir_p(File.dirname(mock_file_path))
62 | end
63 | end
64 |
65 | def create_mock(file_out, model)
66 | MockCreator.new(file: File.open(file),
67 | file_out: file_out,
68 | schema_scrapper: scrapper,
69 | klasses_to_be_mocked: model_names,
70 | enabled_partials: enabled_partials,
71 | mock_append_name: config.mock_append_name,
72 | active_record_model: model).create
73 | end
74 |
75 | OtherErrors = Struct.new(:successful?)
76 |
77 | def collect_errors(create_mock_errors)
78 | add_errors!
79 |
80 | if create_mock_errors.present? || schema.attribute_errors?
81 | display_errors.failed_models << model_name
82 | File.delete(mock_file_path) if File.exist?(mock_file_path)
83 | display_errors.add(create_mock_errors)
84 | OtherErrors.new(false)
85 | else
86 | OtherErrors.new(true)
87 | end
88 | end
89 |
90 | def add_errors!
91 | add_error(schema.association_errors, :associations)
92 | add_error(schema.attribute_errors, :attributes)
93 | end
94 |
95 | def add_error(error, type)
96 | display_errors.wrap_errors(error, model_name, type: type)
97 | end
98 |
99 | def enabled_partials
100 | if config.disable_modules_and_constants
101 | MockCreator::ENABLED_PARTIALS_DEFAULT - [*:modules_constants]
102 | else
103 | MockCreator::ENABLED_PARTIALS_DEFAULT
104 | end
105 | end
106 |
107 | def schema
108 | @schema ||= Schema.new(ActiveRecordSchemaScrapper.new(model: model))
109 | end
110 |
111 | class Schema < SimpleDelegator
112 | def attribute_errors?
113 | attribute_errors.any? { |e| e.level == :error }
114 | end
115 |
116 | def association_errors
117 | associations.errors
118 | end
119 |
120 | def attribute_errors
121 | attributes.errors
122 | end
123 | end
124 | end
125 | end
126 |
--------------------------------------------------------------------------------
/lib/active_mocker/generate.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require_relative "file_writer"
3 |
4 | module ActiveMocker
5 | class Generate
6 | def initialize
7 | check_directory!(:mock_dir)
8 | create_mock_dir
9 | check_directory!(:model_dir)
10 | raise_missing_arg(:model_dir) unless Dir.exist?(config.model_dir)
11 |
12 | @display_errors = DisplayErrors.new(models_paths.count)
13 | end
14 |
15 | # @return self
16 | def call
17 | clean_up
18 | progress_init
19 |
20 | active_record_models_with_files.each do |model, file|
21 | write_file(model, file)
22 |
23 | progress.increment
24 | end
25 |
26 | display_errors.display_errors
27 | self
28 | end
29 |
30 | def active_record_models
31 | @active_record_models ||= active_record_models_with_files.map(&:first)
32 | end
33 |
34 | private
35 |
36 | attr_reader :display_errors, :progress
37 |
38 | def check_directory!(type)
39 | value = config.send(type)
40 |
41 | if value.nil? || value.empty?
42 | raise_missing_arg(type)
43 | end
44 | end
45 |
46 | def raise_missing_arg(type)
47 | raise ArgumentError, "#{type} is missing a valued value!"
48 | end
49 |
50 | def write_file(model, file)
51 | writer = FileWriter.new(
52 | model: model,
53 | file: file,
54 | display_errors: display_errors,
55 | config: config,
56 | model_names: model_names)
57 |
58 | writer.write!
59 | end
60 |
61 | def progress_init
62 | @progress = config.progress_class.create(active_record_models.count)
63 | end
64 |
65 | def model_names
66 | @model_names ||= active_record_models.map(&:name)
67 | end
68 |
69 | def active_record_models_with_files
70 | @active_record_models_with_files ||= models_paths.map do |file|
71 | model = constant_from(model_name_from(file))
72 | [model, file] if model
73 | end.compact
74 | end
75 |
76 | def models_paths
77 | @models_paths ||= Dir.glob(config.single_model_path || File.join(config.model_dir, "**/*.rb"))
78 | end
79 |
80 | def constant_from(model_name)
81 | constant = model_name.constantize
82 | return unless constant.ancestors.include?(ActiveRecord::Base)
83 | constant
84 | rescue NameError, LoadError => e
85 | display_errors.wrap_an_exception(e, model_name)
86 | nil
87 | end
88 |
89 | def model_name_from(file)
90 | FilePathToRubyClass.new(
91 | base_path: config.model_dir,
92 | class_path: file
93 | ).to_s
94 | end
95 |
96 | def config
97 | ActiveMocker::Config
98 | end
99 |
100 | def create_mock_dir
101 | FileUtils.mkdir_p(config.mock_dir) unless Dir.exist?(config.mock_dir)
102 | end
103 |
104 | def clean_up
105 | delete_mocks unless config.single_model_path
106 | end
107 |
108 | def delete_mocks
109 | FileUtils.rm Dir.glob(File.join(config.mock_dir, "/**/*_#{config.mock_append_name.underscore}.rb"))
110 | end
111 | end
112 | end
113 |
--------------------------------------------------------------------------------
/lib/active_mocker/hash_new_style.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class HashNewStyle < Hash
4 | def inspect
5 | "{ " + map { |name, type| "#{name}: #{type}" }.join(", ") + " }"
6 | end
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "active_mocker/inspectable/bigdecimal"
3 | require "active_mocker/inspectable/date"
4 | require "active_mocker/inspectable/dir"
5 | require "active_mocker/inspectable/file"
6 | require "active_mocker/inspectable/pathname"
7 | require "active_mocker/inspectable/struct"
8 | require "active_mocker/inspectable/time"
9 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable/bigdecimal.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Inspectable
4 | refine BigDecimal do
5 | def inspect
6 | "BigDecimal(\"%s\")" % to_s('F')
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable/date.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Inspectable
4 | refine Date do
5 | def inspect
6 | "Date.new(%s, %s, %s)" % [year, month, day]
7 | end
8 | end
9 |
10 | refine DateTime do
11 | def inspect
12 | strftime("DateTime.new(%Y, %-m, %-d, %-H, %-M, %-S, \"%:z\")")
13 | end
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable/dir.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Inspectable
4 | refine Dir do
5 | def inspect
6 | "Dir.new(#{path.inspect})"
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable/file.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Inspectable
4 | refine Dir do
5 | def File
6 | "File.new(#{path.inspect})"
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable/pathname.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Inspectable
4 | refine Pathname do
5 | def inspect
6 | "Pathname(#{to_s.inspect})"
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable/struct.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Inspectable
4 | refine Struct do
5 | def inspect
6 | "%s.new(%s)" % [self.class.name, values.map(&:inspectable).join(", ")]
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/inspectable/time.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Inspectable
4 | refine Time do
5 | def inspect
6 | strftime("Time.new(%Y, %-m, %-d, %-H, %-M, %-S, \"%:z\")")
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/late_inclusion.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module ActiveMocker
4 | module LateInclusion
5 | module Extension
6 | def prepended(const)
7 | if const.respond_to?(:__extended_onto__)
8 | const.__extended_onto__.each do |ex|
9 | ex.extend self
10 | end
11 | end
12 |
13 | if const.respond_to?(:__included_onto__)
14 | const.__included_onto__.each do |ex|
15 | ex.prepend self
16 | end
17 | end
18 | end
19 | end
20 |
21 | def extended(const)
22 | __extended_onto__ << const
23 | end
24 |
25 | def __extended_onto__
26 | @__extended_onto__ ||= []
27 | end
28 |
29 | def included(const)
30 | __included_onto__ << const
31 | end
32 |
33 | def __included_onto__
34 | @__included_onto__ ||= []
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/active_mocker/loaded_mocks.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "forwardable"
4 | require_relative "loaded_mocks/features"
5 |
6 | module ActiveMocker
7 | class LoadedMocks
8 | class << self
9 | extend Forwardable
10 | def_delegators :mocks, :find, :delete_all
11 |
12 | # Returns an Enumerable of all currently loaded mocks.
13 | #
14 | # ActiveMocker::LoadedMocks.mocks
15 | # => PersonMock}>
16 | # @return ActiveMocker::LoadedMocks::Collection
17 | def mocks
18 | Collection.new(mocks_store.values.each_with_object({}) do |mock_constant, hash|
19 | hash[mock_constant.send(:mocked_class)] = mock_constant
20 | end)
21 | end
22 |
23 | # @deprecated Use {#mocks} instead of this method.
24 | alias class_name_to_mock mocks
25 |
26 | # @deprecated Use {#mocks} instead of this method.
27 | alias all mocks
28 |
29 | # @deprecated Use {#delete_all} instead of this method.
30 | alias clear_all delete_all
31 |
32 | def features
33 | @features ||= Features.instance
34 | end
35 |
36 | class Collection
37 | include Enumerable
38 |
39 | # @option opts [Hash] hash
40 | def initialize(hash = {})
41 | @hash = Hash[hash]
42 | end
43 |
44 | extend Forwardable
45 | def_delegators :hash, :[]=, :[], :each, :to_hash, :to_h
46 |
47 | # Calls {#delete_all} for all mocks globally, which removes all records that were saved or created.
48 | # @return [NilClass]
49 | def delete_all
50 | mocks.each(&__method__)
51 | end
52 |
53 | # @param [Array] args an array of ActiveRecord Model Names as Strings or Symbols
54 | # or of mock object.
55 | # @return [ActiveMocker::LoadedMocks::Collection] returns ActiveMock equivalent class.
56 | def slice(*args)
57 | self.class.new(select { |k, v| get_item(args, k, v) })
58 | end
59 |
60 | # Input ActiveRecord Model Name as String or Symbol and it returns everything but that ActiveMock equivalent class.
61 | # except('User') => [AccountMock, OtherMock]
62 | # @param [Array] args
63 | # @return ActiveMocker::LoadedMocks::Collection
64 | def except(*args)
65 | self.class.new(reject { |k, v| get_item(args, k, v) })
66 | end
67 |
68 | # Input ActiveRecord Model Name as String or Symbol returns ActiveMock equivalent class.
69 | # find('User') => UserMock
70 | # @param [Symbol, String, ActiveMocker::Mock] item
71 | # @return ActiveMocker::Mock
72 | def find(item)
73 | slice(item).mocks.first
74 | end
75 |
76 | # @return [Array]
77 | def mocks
78 | hash.values
79 | end
80 | alias values mocks
81 |
82 | private
83 |
84 | attr_reader :hash
85 |
86 | def get_item(args, k, v)
87 | args.map do |e|
88 | if [:to_str, :to_sym].any? { |i| e.respond_to? i }
89 | e.to_s == k
90 | else
91 | e == v
92 | end
93 | end.any? { |a| a }
94 | end
95 | end
96 |
97 | private
98 |
99 | def mocks_store
100 | @mocks ||= {}
101 | end
102 |
103 | def add(mocks_to_add)
104 | mocks_store.merge!(mocks_to_add.name => mocks_to_add)
105 | end
106 | end
107 | end
108 | end
109 |
--------------------------------------------------------------------------------
/lib/active_mocker/loaded_mocks/features.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "singleton"
3 | require "active_mocker/mock/exceptions"
4 |
5 | module ActiveMocker
6 | class LoadedMocks
7 | class Features
8 | include Singleton
9 | STUB_ACTIVE_RECORD_EXCEPTIONS = {
10 | "ActiveRecord::RecordNotFound" => ActiveMocker::RecordNotFound,
11 | "ActiveRecord::RecordNotUnique" => ActiveMocker::RecordNotUnique,
12 | "ActiveRecord::UnknownAttributeError" => ActiveMocker::UnknownAttributeError,
13 | }
14 | DEFAULTS = {
15 | timestamps: false,
16 | delete_all_before_example: false,
17 | stub_active_record_exceptions: STUB_ACTIVE_RECORD_EXCEPTIONS,
18 | }.freeze
19 |
20 | def initialize
21 | reset
22 | end
23 |
24 | def each(&block)
25 | @features.each(&block)
26 | end
27 |
28 | def enable(feature)
29 | update(feature, true)
30 | end
31 |
32 | def disable(feature)
33 | update(feature, false)
34 | end
35 |
36 | def [](feature)
37 | @features[feature]
38 | end
39 |
40 | def reset
41 | @features = DEFAULTS.dup
42 | end
43 |
44 | def to_h
45 | @features
46 | end
47 |
48 | private
49 |
50 | def update(feature, value)
51 | if @features.key?(feature)
52 | @features[feature] = value
53 | else
54 | raise KeyError, "#{feature} is not an available feature."
55 | end
56 | end
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "active_support/deprecation"
3 | require "active_support/dependencies/autoload"
4 | require "active_support/hash_with_indifferent_access"
5 | require "active_support/core_ext/module/delegation"
6 | require "active_support/inflector"
7 | require "active_support/core_ext"
8 | require "virtus"
9 |
10 | require "active_mocker/version"
11 | require "active_mocker/loaded_mocks"
12 | require "active_mocker/mock/hash_process"
13 | require "active_mocker/mock/collection"
14 | require "active_mocker/mock/queries"
15 | require "active_mocker/mock/mockable_method"
16 | require "active_mocker/mock/relation"
17 | require "active_mocker/mock/mock_relation"
18 | require "active_mocker/mock/association"
19 | require "active_mocker/mock/has_many"
20 | require "active_mocker/mock/single_relation"
21 | require "active_mocker/mock/has_one"
22 | require "active_mocker/mock/has_and_belongs_to_many"
23 | require "active_mocker/mock/belongs_to"
24 | require "active_mocker/mock/exceptions"
25 | require "active_mocker/mock/template_methods"
26 | require "active_mocker/mock/do_nothing_active_record_methods"
27 | require "active_mocker/mock/records"
28 | require "active_mocker/mock/object_inspect"
29 | require "active_mocker/mock/alias_attribute"
30 | require "active_mocker/mock/unrepresentable_const_value"
31 | require "active_mocker/attribute_types/enum"
32 | require "active_mocker/mock/base"
33 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/alias_attribute.rb:
--------------------------------------------------------------------------------
1 | module ActiveMocker
2 | module AliasAttribute
3 | # Is +new_name+ an alias?
4 | def attribute_alias?(new_name)
5 | attribute_aliases.key? new_name.to_s
6 | end
7 |
8 | # Returns the original name for the alias +name+
9 | def attribute_alias(name)
10 | attribute_aliases[name.to_s]
11 | end
12 |
13 | private
14 |
15 | def attribute_aliases
16 | @attribute_aliases ||= {}
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/association.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class Association < Relation
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/belongs_to.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class BelongsTo < SingleRelation
4 | attr_reader :item
5 |
6 | def initialize(item, child_self:, foreign_key:)
7 | save_item(item, child_self)
8 | assign_foreign_key(child_self, foreign_key, item.try(:id))
9 | super
10 | end
11 |
12 | private
13 |
14 | def assign_foreign_key(child_self, foreign_key, foreign_id)
15 | child_self.send(:write_attribute, foreign_key, foreign_id)
16 | end
17 |
18 | def save_item(item, child_self)
19 | return if item.nil?
20 | item.try(:save) if child_self.persisted?
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/collection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "forwardable"
3 |
4 | module ActiveMocker
5 | class Collection
6 | include Enumerable
7 | extend ::Forwardable
8 | def_delegators :@collection, :[], :take, :push, :clear, :first, :last, :concat, :replace, :uniq, :count, :size, :length, :empty?, :any?, :many?, :include?, :delete
9 | alias distinct uniq
10 |
11 | def initialize(collection = [])
12 | @collection = collection
13 | end
14 |
15 | def <<(*records)
16 | collection.concat(records.flatten)
17 | end
18 |
19 | def each
20 | collection.each do |item|
21 | yield(item)
22 | end
23 | end
24 |
25 | def to_a
26 | @collection
27 | end
28 |
29 | def to_ary
30 | to_a
31 | end
32 |
33 | def hash
34 | @collection.hash
35 | end
36 |
37 | def ==(val)
38 | @collection == val
39 | end
40 |
41 | def blank?
42 | to_a.blank?
43 | end
44 |
45 | protected
46 |
47 | attr_accessor :collection
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/compatibility/base/ar51.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: tru
2 | module ActiveMocker
3 | class Base
4 | module AR51
5 | def delete_all
6 | super
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/compatibility/queries/ar52.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module ActiveMocker
4 | module Queries
5 | module AR52
6 | extend LateInclusion::Extension
7 |
8 | private
9 |
10 | def check_for_limit_scope!
11 | # noop
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/do_nothing_active_record_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module DoNothingActiveRecordMethods
4 | def self.included(base)
5 | base.extend(ClassMethods)
6 | end
7 |
8 | module ClassMethods
9 | def transaction(*)
10 | yield
11 | rescue LocalJumpError => err
12 | raise err
13 | rescue StandardError => e
14 | raise e
15 | end
16 |
17 | def column_names
18 | attribute_names
19 | end
20 | end
21 |
22 | def readonly?
23 | false
24 | end
25 |
26 | def errors
27 | obj = Object.new
28 |
29 | def obj.[](_key)
30 | []
31 | end
32 |
33 | def obj.full_messages
34 | []
35 | end
36 |
37 | obj
38 | end
39 |
40 | def valid?
41 | true
42 | end
43 |
44 | def marked_for_destruction?
45 | false
46 | end
47 |
48 | def destroyed?
49 | false
50 | end
51 |
52 | def reload
53 | self
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/exceptions.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class BaseError < StandardError
4 | end
5 | class RecordNotFound < BaseError
6 | end
7 | class RecordNotUnique < BaseError
8 | end
9 |
10 | module Mock
11 | # @deprecated
12 | RecordNotFound = ActiveMocker::RecordNotFound
13 | end
14 |
15 | class IdError < BaseError
16 | end
17 |
18 | # Raised when unknown attributes are supplied via mass assignment.
19 | class UnknownAttributeError < NoMethodError
20 | attr_reader :record, :attribute
21 |
22 | def initialize(record, attribute)
23 | @record = record
24 | @attribute = attribute.to_s
25 | super("unknown attribute: #{attribute}")
26 | end
27 | end
28 |
29 | class UpdateMocksError < BaseError
30 | def initialize(name, mock_build_version, mock_current_version)
31 | super("#{name} was built with #{mock_build_version} but the mock current version is #{mock_current_version}. Run `rake active_mocker:build` to update.")
32 | end
33 | end
34 |
35 | class NotImplementedError < BaseError
36 | end
37 |
38 | class Error < BaseError
39 | end
40 |
41 | class MockNotLoaded < BaseError
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/has_and_belongs_to_many.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class HasAndBelongsToMany < HasMany
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/has_many.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class HasMany < Association
4 | include Queries
5 |
6 | def self.new(collection, options = {})
7 | return Relation.new(collection) if options[:relation_class].nil?
8 | super(collection, options)
9 | end
10 |
11 | def initialize(collection, options = {})
12 | @relation_class = options[:relation_class]
13 | @foreign_key = options[:foreign_key]
14 | @foreign_id = options[:foreign_id]
15 | @source = options[:source]
16 | self.class.include "#{@relation_class.name}::Scopes".constantize
17 | super(collection)
18 | set_foreign_key
19 | end
20 |
21 | def set_foreign_key
22 | collection.each do |item|
23 | item.send(:write_attribute, foreign_key, foreign_id) if item.respond_to?("#{foreign_key}=")
24 | end
25 | end
26 |
27 | # @api private
28 | attr_reader :relation_class, :foreign_key, :foreign_id, :source
29 |
30 | def build(options = {}, &block)
31 | new_record = relation_class.new(init_options.merge!(options), &block)
32 |
33 | # @private
34 | def new_record._belongs_to(collection)
35 | @belongs_to_collection = collection
36 | end
37 |
38 | new_record._belongs_to(self)
39 |
40 | # @private
41 | def new_record.save
42 | @belongs_to_collection << self
43 | super
44 | end
45 |
46 | new_record
47 | end
48 |
49 | def create(options = {}, &block)
50 | created_record = relation_class.create(init_options.merge!(options), &block)
51 | collection << created_record
52 | created_record
53 | end
54 |
55 | alias create! create
56 |
57 | # @api private
58 | def init_options
59 | { foreign_key => foreign_id }
60 | end
61 | end
62 | module Mock
63 | # @deprecated
64 | HasMany = ActiveMocker::HasMany
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/has_one.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class HasOne < SingleRelation
4 | attr_reader :item
5 |
6 | def initialize(item, child_self:, foreign_key:)
7 | item.send(:write_attribute, foreign_key, item.try(:id)) unless item.try(:id).nil?
8 | super
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/hash_process.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | # @api private
4 | class HashProcess
5 | attr_accessor :hash, :processor
6 |
7 | def initialize(hash, processor)
8 | @hash = hash
9 | @processor = processor
10 | @hash_process = {}
11 | end
12 |
13 | def [](val)
14 | @hash_process[val] ||= processor.call(hash[val])
15 | end
16 |
17 | def merge(merge_hash)
18 | self.hash = hash.merge(merge_hash.hash)
19 | self
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/mock_relation.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class MockRelation
4 | # @param [ActiveMocker::Base] mock, a generated mock class
5 | # @param [Array] collection, an array of mock instances
6 | # @return [ScopeRelation] for the given mock
7 | def self.new(mock, collection)
8 | mock.send(:__new_relation__, collection)
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/mockable_method.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module ActiveMocker
4 | module MockableMethod
5 | private
6 |
7 | def __am_raise_not_mocked_error(method:, caller:, type:)
8 | variable_name, klass, method_type = if is_a?(Relation)
9 | klass = self.class.name.underscore.split("/").first
10 | ["#{klass}_relation", klass.camelize, :scopes]
11 | elsif type == "#"
12 | klass = self.class.name
13 | ["#{klass.underscore.split("/").first}_record", klass, :instance_methods]
14 | else
15 | [name, name, :class_methods]
16 | end
17 |
18 | message = <<-ERROR.strip_heredoc
19 | Unknown implementation for mock method: #{variable_name}.#{method}
20 | Stub method to continue.
21 |
22 | RSpec:
23 | allow(
24 | #{variable_name}
25 | ).to receive(:#{method}).and_return(:some_expected_result)
26 |
27 | OR Whitelist the method as safe to copy/run in the context of ActiveMocker (requires mock rebuild)
28 | # ActiveMocker.safe_methods #{method_type}: [:#{method}]
29 | class #{klass.gsub("Mock", "")} < ActiveRecord::Base
30 | end
31 | ERROR
32 |
33 | raise NotImplementedError, message, caller
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/object_inspect.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class ObjectInspect
4 | def initialize(class_name, attributes)
5 | @class_name = class_name
6 | @attributes = attributes
7 | @string = create_inspections
8 | end
9 |
10 | def to_s
11 | @string
12 | end
13 |
14 | def to_str
15 | @string
16 | end
17 |
18 | private
19 |
20 | def create_inspections
21 | inspection = @attributes.map do |name, value|
22 | "#{name}: #{object_for_inspect(value)}"
23 | end
24 | "#<#{@class_name} #{inspection.compact.join(", ")}>"
25 | end
26 |
27 | def object_for_inspect(value)
28 | if value.is_a?(String) && value.length > 50
29 | "#{value[0, 50]}...".inspect
30 | elsif value.is_a?(Date) || value.is_a?(Time)
31 | %("#{value.to_s(:db)}")
32 | elsif value.is_a?(Array) && value.size > 10
33 | inspected = value.first(10).inspect
34 | %(#{inspected[0...-1]}, ...])
35 | else
36 | value.inspect
37 | end
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/records.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class Records
4 | extend Forwardable
5 | def_delegators :records, :<<, :count, :length, :to_a
6 |
7 | attr_reader :records
8 | private :records
9 |
10 | def initialize(records = [])
11 | @records = records
12 | end
13 |
14 | def insert(record)
15 | records << validate_id((record.id ||= next_id), record)
16 | end
17 |
18 | def delete(record)
19 | raise RecordNotFound, "Record has not been created." unless records.delete(record)
20 | end
21 |
22 | def exists?(record)
23 | records.include?(record)
24 | end
25 |
26 | def new_record?(record)
27 | !exists?(record)
28 | end
29 |
30 | def persisted?(id)
31 | ids.include?(id)
32 | end
33 |
34 | def reset
35 | records.clear
36 | end
37 |
38 | private
39 |
40 | def ids
41 | records.map(&:id)
42 | end
43 |
44 | def next_id
45 | max_record.succ
46 | rescue NoMethodError
47 | 1
48 | end
49 |
50 | def max_record
51 | ids.max
52 | end
53 |
54 | def validate_id(id, record)
55 | record.id = id.to_i
56 | validate_unique_id(id, record)
57 | end
58 |
59 | def validate_unique_id(id, record)
60 | raise IdError, "Duplicate ID found for record #{record.inspect}" if persisted?(id)
61 | record
62 | end
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/relation.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class Relation < Collection
4 | include Queries
5 | include MockableMethod
6 |
7 | def initialize(collection = [])
8 | super
9 | @from_limit = false
10 | end
11 |
12 | def inspect
13 | entries = to_a.take(11).map!(&:inspect)
14 | entries[10] = "..." if entries.size == 11
15 | "#<#{name} [#{entries.join(", ")}]>"
16 | end
17 |
18 | def from_limit?
19 | @from_limit
20 | end
21 |
22 | def name
23 | self.class.name
24 | end
25 |
26 | private
27 |
28 | def set_from_limit
29 | @from_limit = true
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/single_relation.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class SingleRelation
4 | attr_reader :item
5 |
6 | def initialize(item, child_self:, foreign_key:)
7 | @item = item
8 | assign_associations(child_self, item) if item.class <= Base
9 | end
10 |
11 | def assign_associations(child_self, item)
12 | [*item.class._find_associations_by_class(child_self.class.send("mocked_class"))].each do |_type, relations|
13 | relations.each do |relation|
14 | if item.send(relation).class <= Collection
15 | item.send(relation) << child_self
16 | else
17 | item.send(:write_association, relation, child_self)
18 | end
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/template_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module TemplateMethods
4 | def self.included(base)
5 | base.extend(ClassMethods)
6 | end
7 |
8 | module ClassMethods
9 | def attributes
10 | HashWithIndifferentAccess.new({})
11 | end
12 |
13 | def types
14 | HashProcess.new({}, method(:build_type))
15 | end
16 |
17 | def associations
18 | {}
19 | end
20 |
21 | def associations_by_class
22 | {}
23 | end
24 |
25 | def mocked_class
26 | ""
27 | end
28 |
29 | def attribute_names
30 | []
31 | end
32 |
33 | def primary_key
34 | ""
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock/unrepresentable_const_value.rb:
--------------------------------------------------------------------------------
1 | module ActiveMocker
2 | UNREPRESENTABLE_CONST_VALUE = "ActiveMocker can not determine the value, if needed stub this const with a valid test value".freeze
3 | end
4 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/associations.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class MockCreator
4 | module Associations
5 | def has_many
6 | relation_find(:type, __method__)
7 | end
8 |
9 | def has_one
10 | relation_find(:type, __method__)
11 | end
12 |
13 | def belongs_to
14 | relation_find(:type, __method__)
15 | end
16 |
17 | def has_and_belongs_to_many
18 | relation_find(:type, __method__)
19 | end
20 |
21 | def relation_find(key, value)
22 | association_collection.select { |r| r.send(key).to_sym == value }
23 | end
24 |
25 | def association_collection
26 | @association_collection ||= schema_scrapper.associations.to_a
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/attributes.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class MockCreator
4 | module Attributes
5 | def attributes
6 | @attributes ||= begin
7 | a = schema_scrapper.attributes.to_a
8 | a << primary_key unless a.any? { |aa| aa.name == "id" }
9 | a.map(&method(:process_attr))
10 | a
11 | end
12 | end
13 |
14 | def process_attr(attr)
15 | enums = enums(attr.name)
16 | attr.default = Virtus::Attribute.build(attr.type).coerce(attr.default)
17 | attr.attribute_writer = "write_attribute(:#{attr.name}, val)"
18 | attr.attribute_reader = "read_attribute(:#{attr.name})"
19 |
20 | unless enums.empty?
21 | enum_type = ActiveMocker::AttributeTypes::Enum.build(
22 | enums: enums,
23 | table_name: table_name,
24 | attribute: attr.name,
25 | db_value_type: attr.type,
26 | )
27 | if ActiveRecord::VERSION::MAJOR >= 5
28 | enum_type.ignore_value = true
29 | attr.type = enum_type
30 | if attr.default
31 | attr.default = Virtus::Attribute.build(enum_type).get_key(attr.default)
32 | end
33 | elsif ActiveRecord::VERSION::MAJOR == 4
34 | attr.attribute_writer = "@#{attr.name}_enum_type ||= Virtus::Attribute.build(#{enum_type})\nwrite_attribute(:#{attr.name}, @#{attr.name}_enum_type.coerce(val))"
35 | attr.attribute_reader = "@#{attr.name}_enum_type ||= Virtus::Attribute.build(#{enum_type})\n@#{attr.name}_enum_type.get_key(read_attribute(:#{attr.name}))"
36 | if attr.default
37 | attr.default = Virtus::Attribute.build(attr.type).coerce(attr.default)
38 | end
39 | end
40 | attr
41 | end
42 | end
43 |
44 | def enums(attribute)
45 | @enums ||= begin
46 | raw_enums = class_introspector
47 | .class_macros
48 | .select { |hash| hash.key?(:enum) }
49 | if raw_enums
50 | raw_enums
51 | .map { |hash| hash[:enum].flatten.first }
52 | .each_with_object({}) { |v, h| h.merge!(v) }
53 | else
54 | {}
55 | end
56 | end
57 |
58 | @enums.fetch(attribute.to_sym, {})
59 | end
60 | end
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/class_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require_relative "attributes"
3 |
4 | module ActiveMocker
5 | class MockCreator
6 | module ClassMethods
7 | include Attributes
8 |
9 | def attributes_with_defaults
10 | types_hash
11 | attributes.each_with_object({}) do |attr, hash|
12 | hash[attr.name] = attr.default
13 | end
14 | end
15 |
16 | def types_hash
17 | @types_hash ||= attributes.each_with_object(HashNewStyle.new) do |attr, types|
18 | types[attr.name] = attr.type.to_s
19 | end.inspect
20 | end
21 |
22 | def associations
23 | @associations ||= schema_scrapper.associations.to_a.each_with_object({}) do |a, h|
24 | h[a.name] = nil
25 | end
26 | end
27 |
28 | def associations_by_class
29 | schema_scrapper.associations.to_a.each_with_object({}) do |r, hash|
30 | hash[r.class_name.to_s] ||= {}
31 | hash[r.class_name.to_s][r.type] ||= []
32 | hash[r.class_name.to_s][r.type] << r.name
33 | end
34 | end
35 |
36 | def attribute_names
37 | attributes.map(&:name)
38 | end
39 |
40 | def abstract_class
41 | schema_scrapper.abstract_class?
42 | end
43 |
44 | def table_name
45 | schema_scrapper.table_name
46 | end
47 |
48 | def mocked_class
49 | [nested_modules, class_name].compact.reject(&:empty?).join("::")
50 | end
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/defined_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require_relative "safe_methods"
3 | module ActiveMocker
4 | class MockCreator
5 | module DefinedMethods
6 | include SafeMethods
7 | Method = Struct.new(:name, :arguments, :body)
8 |
9 | def instance_methods
10 | meths = class_introspector.get_class.public_instance_methods(false).sort
11 | meths << :initialize if safe_methods[:instance_methods].include?(:initialize)
12 | meths.map { |m| create_method(m, :instance_method) }
13 | end
14 |
15 | def class_methods
16 | class_introspector
17 | .get_class
18 | .methods(false)
19 | .sort
20 | .map { |m| create_method(m, :method) }
21 | end
22 |
23 | private
24 |
25 | def create_method(m, type)
26 | plural_type = (type.to_s + "s").to_sym
27 | if safe_method?(type, m)
28 | def_type = type == :method ? :class_defs : :defs
29 | def_method = class_introspector.parsed_source.public_send(def_type).detect { |meth| meth.name == m }
30 | raise "ActiveMocker.safe_methods is unable to find #{plural_type}: #{m}" unless def_method
31 | Method.new(
32 | m,
33 | def_method.arguments,
34 | def_method.body
35 | )
36 | else
37 | type_symbol = type == :method ? "::" : "#"
38 | Method.new(
39 | m,
40 | ReverseParameters.new(
41 | class_introspector.get_class.send(type, m).parameters
42 | ).parameters,
43 | "__am_raise_not_mocked_error(method: __method__, caller: Kernel.caller, type: '#{type_symbol}')"
44 | )
45 | end
46 | end
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/mock_build_version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module ActiveMocker
4 | class MockCreator
5 | module MockBuildVersion
6 | def mock_build_version
7 | "mock_build_version #{ActiveMocker::Mock::VERSION.inspect}, active_record: '#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}'"
8 | end
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/modules_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class MockCreator
4 | module ModulesConstants
5 | class Inspectable
6 | attr_reader :inspect
7 |
8 | def initialize(inspect)
9 | @inspect = inspect
10 | end
11 | end
12 |
13 | def modules
14 | @modules ||= begin
15 | {
16 | included: get_module_by_reference(:included_modules),
17 | extended: get_module_by_reference(:extended_modules),
18 | }
19 | end
20 | end
21 |
22 | def constants
23 | class_introspector.get_class.constants.map do |v|
24 | c = class_introspector.get_class.const_get(v)
25 | next if [Module, Class].include?(c.class)
26 | const = if /\A# =~ c.inspect
27 | Inspectable.new("ActiveMocker::UNREPRESENTABLE_CONST_VALUE")
28 | else
29 | c
30 | end
31 | [v, const]
32 | end.compact.sort
33 | end
34 |
35 | private
36 | def reject_local_const(source)
37 | source.reject do |n|
38 | class_introspector.locally_defined_constants.values.include?(n)
39 | end
40 | end
41 |
42 | def get_real_module(type)
43 | if type == :extended_modules
44 | active_record_model.singleton_class.included_modules
45 | else
46 | active_record_model.included_modules
47 | end
48 | end
49 |
50 | def get_module_by_reference(type)
51 | isolated_module_names = reject_local_const(class_introspector.public_send(type)).map(&:referenced_name)
52 | real_module_names = get_real_module(type).map(&:name).compact
53 | isolated_module_names.map do |isolated_name|
54 | real_name = real_module_names.detect do |rmn|
55 | real_parts = rmn.split("::")
56 | total_parts_count = active_record_model.name.split("::").count + isolated_name.split("::").count
57 | [
58 | real_parts.include?(active_record_model.name),
59 | real_parts.include?(isolated_name),
60 | (total_parts_count == real_parts.count)
61 | ].all?
62 | end
63 | real_name ? real_name : isolated_name
64 | end
65 | end
66 | end
67 | end
68 | end
69 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/recreate_class_method_calls.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class MockCreator
4 | module RecreateClassMethodCalls
5 | AliasAttributeMethod = Struct.new(:new_name, :old_name)
6 |
7 | def class_method_calls
8 | @class_method_calls ||= class_introspector
9 | .class_macros
10 | .select { |h| h.keys.first == :alias_attribute }
11 | .map do |h|
12 | a = h.values.first.first
13 | AliasAttributeMethod.new(a[0].to_s, a[1].to_s)
14 | end
15 | end
16 |
17 | def attribute_aliases
18 | class_method_calls.each_with_object({}) do |alias_attr, hash|
19 | hash[alias_attr.new_name] = alias_attr.old_name
20 | end
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/safe_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class MockCreator
4 | module SafeMethods
5 | BASE = { instance_methods: [], scopes: [], methods: [], all_methods_safe: false }.freeze
6 |
7 | def safe_method?(type, name)
8 | plural_type = (type.to_s + "s").to_sym
9 | all_methods_safe = all_methods_safe?(type, name)
10 | return true if all_methods_safe
11 | return true if safe_methods[plural_type].include?(name)
12 | false
13 | end
14 |
15 | private
16 |
17 | def safe_methods
18 | @safe_methods ||= class_introspector.parsed_source.comments.each_with_object(BASE.dup) do |comment, hash|
19 | if comment.text.include?("ActiveMocker.all_methods_safe")
20 | hash[:all_methods_safe] = ActiveMocker.module_eval(comment.text.delete("#"))
21 | elsif comment.text.include?("ActiveMocker.safe_methods")
22 | hash.merge!(ActiveMocker.module_eval(comment.text.delete("#")))
23 | else
24 | hash
25 | end
26 | end
27 | end
28 |
29 | def all_methods_safe?(type, name)
30 | plural_type = (type.to_s + "s").to_sym
31 | all_methods_safe = safe_methods.fetch(:all_methods_safe)
32 | if all_methods_safe.is_a?(Hash)
33 | !all_methods_safe.fetch(plural_type).include?(name)
34 | else
35 | all_methods_safe
36 | end
37 | end
38 |
39 | module ActiveMocker
40 | class << self
41 | def safe_methods(*arg_methods, scopes: [], instance_methods: [], class_methods: [], all_methods_safe: false)
42 | {
43 | instance_methods: arg_methods.concat(instance_methods),
44 | scopes: scopes,
45 | methods: class_methods,
46 | all_methods_safe: all_methods_safe,
47 | }
48 | end
49 |
50 | def all_methods_safe(except: {})
51 | other_keys = except.except(:instance_methods, :scopes, :class_methods)
52 | unless other_keys.empty?
53 | raise ArgumentError, "ActiveMocker.all_methods_safe arguments must only be `except: { instance_methods: [], scopes: [], class_methods: [] }`"
54 | end
55 | {
56 | instance_methods: except.fetch(:instance_methods, []),
57 | scopes: except.fetch(:scopes, []),
58 | methods: except.fetch(:class_methods, []),
59 | }
60 | end
61 | end
62 | end
63 | end
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_creator/scopes.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require_relative "safe_methods"
3 | module ActiveMocker
4 | class MockCreator
5 | module Scopes
6 | Method = Struct.new(:name, :arguments, :body)
7 | include SafeMethods
8 |
9 | def scope_methods
10 | class_introspector.class_macros.select { |h| h.keys.first == :scope }.map do |h|
11 | name, args = h.values.first.first
12 | arguments = ReverseParameters.new(args)
13 | body = scope_body(arguments, name)
14 | Method.new(name, arguments, body)
15 | end
16 | end
17 |
18 | def scope_body(_arguments, name)
19 | if safe_method?(:scope, name)
20 | find_scope_body_from_ast(name)
21 | else
22 | <<-METHOD
23 | __am_raise_not_mocked_error(
24 | method: "#{name}",
25 | caller: Kernel.caller,
26 | type: "::"
27 | )
28 | METHOD
29 | end
30 | end
31 |
32 | def ast_scopes
33 | @ast_scopes ||= class_introspector
34 | .parsed_source
35 | .class_begin
36 | .children
37 | .select { |n| n.try(:type) == :send && n.try { children[1] == :scope } }
38 | end
39 |
40 | def find_scope_body_from_ast(name)
41 | scope = ast_scopes.detect { |n| n.children[2].children.first == name }
42 | DissociatedIntrospection::RubyCode.build_from_ast(scope.children[3].children[2]).source
43 | end
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template.erb:
--------------------------------------------------------------------------------
1 | require 'active_mocker/mock'
2 |
3 | class <%= class_name + mock_append_name %> < <%= parent_class_inspector.parent_mock_name %>
4 |
5 | <%= partials.mock_build_version %>
6 | <%= partials.modules_constants %>
7 | <%= partials.class_methods %>
8 | <%= partials.attributes %>
9 | <%= partials.associations %>
10 | <%= partials.recreate_class_method_calls %>
11 | <%= partials.defined_methods %>
12 | <%= partials.scopes %>
13 | end
14 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_associations.erb:
--------------------------------------------------------------------------------
1 | # _associations.erb
2 |
3 | <%= '# belongs_to' unless belongs_to.empty? -%>
4 |
5 | <% belongs_to.each do |meth| -%>
6 | def <%= meth.name %>
7 | <% association = relation_find(:name, meth.name).first -%>
8 | read_association(:<%= meth.name %>) || write_association(:<%= meth.name %>, classes('<%= association.class_name %>').try{ |k| k.find_by(id: <%= association.foreign_key %>)})
9 | end
10 | def <%= meth.name %>=(val)
11 | write_association(:<%= meth.name %>, val)
12 | ActiveMocker::BelongsTo.new(val, child_self: self, foreign_key: :<%= meth.foreign_key %>).item
13 | end
14 |
15 | def build_<%= meth.name %>(attributes={}, &block)
16 | <% association = relation_find(:name, meth.name).first -%>
17 | <% if association -%>
18 | self.<%= meth.name %> = classes('<%= association.class_name %>', true).new(attributes, &block)
19 | <% end -%>
20 | end
21 |
22 | def create_<%= meth.name %>(attributes={}, &block)
23 | <% association = relation_find(:name, meth.name).first -%>
24 | <% if association -%>
25 | self.<%= meth.name %> = classes('<%= association.class_name %>', true).create(attributes, &block)
26 | <% end -%>
27 | end
28 | alias_method :create_<%= meth.name %>!, :create_<%= meth.name %>
29 | <% end -%>
30 |
31 | <%= '# has_one' unless has_one.empty? -%>
32 |
33 | <% has_one.each do |meth| -%>
34 | def <%= meth.name %>
35 | read_association(:<%= meth.name %>)
36 | end
37 |
38 | def <%= meth.name %>=(val)
39 | write_association(:<%= meth.name %>, val)
40 | ActiveMocker::HasOne.new(val, child_self: self, foreign_key: '<%= meth.foreign_key %>').item
41 | end
42 |
43 | def build_<%= meth.name %>(attributes={}, &block)
44 | <% association = relation_find(:name, meth.name).first -%>
45 | <% if association -%>
46 | self.<%= meth.name %>= classes('<%= association.class_name %>', true).new(attributes, &block)
47 | <% end -%>
48 | end
49 |
50 | def create_<%= meth.name %>(attributes={}, &block)
51 | <% association = relation_find(:name, meth.name).first -%>
52 | <% if association -%>
53 | self.<%= meth.name %>= classes('<%= association.class_name %>', true).new(attributes, &block)
54 | <% end -%>
55 | end
56 | alias_method :create_<%= meth.name %>!, :create_<%= meth.name %>
57 | <% end -%>
58 |
59 | <%= '# has_many' unless has_many.empty? -%>
60 |
61 | <% has_many.each do |meth| -%>
62 | def <%= meth.name %>
63 | read_association(:<%= meth.name %>, -> { ActiveMocker::HasMany.new([],foreign_key: '<%= meth.foreign_key %>', foreign_id: self.id, relation_class: classes('<%= meth.class_name %>'), source: '<%= meth.source %>') })
64 | end
65 |
66 | def <%= meth.name %>=(val)
67 | write_association(:<%= meth.name %>, ActiveMocker::HasMany.new(val, foreign_key: '<%= meth.foreign_key %>', foreign_id: self.id, relation_class: classes('<%= meth.class_name %>'), source: '<%= meth.source %>'))
68 | end
69 | <% end -%>
70 | <%= '# has_and_belongs_to_many' unless has_and_belongs_to_many.empty? -%>
71 |
72 | <% has_and_belongs_to_many.each do |meth| -%>
73 | def <%= meth.name %>
74 | read_association(:<%= meth.name %>, -> { ActiveMocker::HasAndBelongsToMany.new([],foreign_key: '<%= meth.foreign_key %>', foreign_id: self.id, relation_class: classes('<%= meth.class_name %>'), source: '<%= meth.source %>') })
75 | end
76 |
77 | def <%= meth.name %>=(val)
78 | write_association(:<%= meth.name %>, ActiveMocker::HasAndBelongsToMany.new(val, foreign_key: '<%= meth.foreign_key %>', foreign_id: self.id, relation_class: classes('<%= meth.class_name %>'), source: '<%= meth.source %>'))
79 | end
80 | <% end -%>
81 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_attributes.erb:
--------------------------------------------------------------------------------
1 | # _attributes.erb
2 | <% attributes.each do |meth| -%>
3 | def <%= meth.name %>
4 | <%= meth.attribute_reader %>
5 | end
6 |
7 |
8 | def <%= meth.name %>=(val)
9 | <%= meth.attribute_writer %>
10 | end
11 | <% end -%>
12 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_class_methods.erb:
--------------------------------------------------------------------------------
1 | #_class_methods.erb
2 | class << self
3 | private
4 |
5 | def attributes
6 | @attributes ||= HashWithIndifferentAccess.new(<%= attributes_with_defaults.map {|key,value| %Q[#{key}: #{value.inspect}]}.join(", ") %>).merge(super)
7 | end
8 |
9 | def types
10 | @types ||= ActiveMocker::HashProcess.new(<%= types_hash %>, method(:build_type)).merge(super)
11 | end
12 |
13 | def associations
14 | @associations ||= <%= associations %>.merge(super)
15 | end
16 |
17 | def associations_by_class
18 | @associations_by_class ||= <%= associations_by_class %>.merge(super)
19 | end
20 |
21 | def mocked_class
22 | <%= mocked_class.inspect %>
23 | end
24 |
25 | public
26 |
27 | def attribute_names
28 | @attribute_names ||= attributes.stringify_keys.keys
29 | end
30 |
31 | def primary_key
32 | <%= primary_key.name.inspect %>
33 | end
34 |
35 | def abstract_class?
36 | <%= abstract_class.inspect %>
37 | end
38 |
39 | def table_name
40 | <%= table_name.inspect %> || super
41 | end
42 |
43 | end
44 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_defined_methods.erb:
--------------------------------------------------------------------------------
1 | <% instance_methods.each do |method| -%>
2 | def <%= method.name %><%= "(#{method.arguments})" unless method.arguments.blank? %>
3 | <%= method.body %>
4 | end
5 | <% end -%>
6 | module ClassMethods
7 | <% class_methods.each do |method| -%>
8 | def <%= method.name %><%= "(#{method.arguments})" unless method.arguments.blank? %>
9 | <%= method.body %>
10 | end
11 | <% end -%>
12 | end
13 |
14 | extend ClassMethods
15 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_mock_build_version.erb:
--------------------------------------------------------------------------------
1 | <%= mock_build_version %>
2 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_modules_constants.erb:
--------------------------------------------------------------------------------
1 | # _modules_constants.erb
2 | <% constants.each do |constant, value| -%>
3 | <%= constant %> = <%= value.inspect %>
4 | <% end -%>
5 | <% modules[:included].each do |constant| -%>
6 | prepend <%= constant %>
7 | <% end -%>
8 | <% modules[:extended].each do |constant| -%>
9 | extend <%= constant %>
10 | <% end -%>
11 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_recreate_class_method_calls.erb:
--------------------------------------------------------------------------------
1 | # _recreate_class_method_calls.erb
2 |
3 | def self.attribute_aliases
4 | @attribute_aliases ||= <%= attribute_aliases %>.merge(super)
5 | end
6 |
7 | <% class_method_calls.each do |method| -%>
8 | alias_method :<%= method.new_name %>, :<%= method.old_name %>
9 | alias_method :<%= method.new_name %>=, :<%= method.old_name %>=
10 |
11 | <% end -%>
12 |
13 |
--------------------------------------------------------------------------------
/lib/active_mocker/mock_template/_scopes.erb:
--------------------------------------------------------------------------------
1 | # _scopes.erb
2 | module Scopes
3 | include <%= parent_class_inspector.parent_mock_name %>::Scopes
4 |
5 | <% scope_methods.each do |method| -%>
6 | def <%= method.name %><%= "(#{method.arguments.parameters})" unless method.arguments.parameters.to_a.empty? %>
7 | <%= method.body %>
8 | end
9 |
10 | <% end -%>
11 | end
12 |
13 | extend Scopes
14 |
15 | class ScopeRelation < ActiveMocker::Association
16 | include <%= class_name + mock_append_name %>::Scopes
17 | include ClassMethods
18 | end
19 |
20 | def self.__new_relation__(collection)
21 | <%= class_name + mock_append_name %>::ScopeRelation.new(collection)
22 | end
23 |
24 | private_class_method :__new_relation__
25 |
--------------------------------------------------------------------------------
/lib/active_mocker/null_progress.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class NullProgress
4 | def self.create(*)
5 | new
6 | end
7 |
8 | def initialize(*)
9 | end
10 |
11 | def increment
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/lib/active_mocker/parent_class.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class ParentClass
4 | def initialize(parsed_source:, klasses_to_be_mocked:, mock_append_name:, active_record_base_klass: ::ActiveRecord::Base)
5 | @parsed_source = parsed_source
6 | @klasses_to_be_mocked = klasses_to_be_mocked
7 | @active_record_base_klass = active_record_base_klass
8 | @mock_append_name = mock_append_name
9 | end
10 |
11 | attr_reader :error
12 |
13 | def call
14 | if parent_class?
15 | deal_with_parent
16 | else
17 | create_error("#{class_name} is missing a parent class.")
18 | end
19 | self
20 | end
21 |
22 | def parent_mock_name
23 | if @parent_mock_name
24 | "#{@parent_mock_name}#{mock_append_name}"
25 | else
26 | "ActiveMocker::Base"
27 | end
28 | end
29 |
30 | private
31 |
32 | attr_reader :parsed_source,
33 | :klasses_to_be_mocked,
34 | :active_record_base_klass,
35 | :mock_append_name
36 |
37 | def deal_with_parent
38 | if parent_class <= active_record_base_klass
39 | @parent_mock_name = parent_class_name if included_mocked_class?
40 | else
41 | create_error("#{class_name} does not inherit from ActiveRecord::Base")
42 | end
43 | end
44 |
45 | def create_error(message)
46 | @error = OpenStruct.new(class_name: class_name,
47 | message: message)
48 | end
49 |
50 | def parent_class?
51 | parsed_source.parent_class?
52 | end
53 |
54 | def parent_class_name
55 | parsed_source.parent_class_name
56 | end
57 |
58 | def class_name
59 | parsed_source.class_name
60 | end
61 |
62 | def parent_class
63 | parent_class_name.constantize
64 | end
65 |
66 | def included_mocked_class?
67 | sanitize_consts(klasses_to_be_mocked).include?(sanitize_consts(parent_class_name).first)
68 | end
69 |
70 | def sanitize_consts(consts)
71 | [*consts].map do |const|
72 | const.split("::").reject(&:empty?).join("::")
73 | end
74 | end
75 | end
76 | end
77 |
--------------------------------------------------------------------------------
/lib/active_mocker/progress.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class Progress
4 | def self.create(count)
5 | require "ruby-progressbar"
6 | new(count)
7 | rescue LoadError
8 | NullProgress.new
9 | end
10 |
11 | def initialize(count)
12 | @count = count
13 | end
14 |
15 | delegate :increment, to: :progress
16 |
17 | def progress
18 | @progress ||= ProgressBar.create(title: "Generating Mocks",
19 | total: @count,
20 | format: "%t |%b>>%i| %p%%")
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/active_mocker/public_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class << self
4 | # Override default Configurations
5 | #
6 | # ActiveMocker.configure do |c|
7 | # c.model_dir= # Directory of ActiveRecord models
8 | # c.mock_dir= # Directory to save mocks
9 | # c.single_model_path= # Path to generate a single mock
10 | # c.progress_bar= # False disables progress bar from sending to STDOUT
11 | # or pass a class that takes a count in the initializer and responds to #increment.
12 | # c.error_verbosity= # 0 = none
13 | # # 1 = Summary of failures
14 | # # 2 = One line per error
15 | # # 3 = Errors with exception backtrace
16 | # c.disable_modules_and_constants= # Modules are include/extend along with constant declarations.
17 | # # Default is false, to disable set to true.
18 | # end
19 | #
20 | # @returns self
21 | # @yield [Config]
22 | def configure(&block)
23 | Config.set(&block)
24 | self
25 | end
26 | alias config configure
27 |
28 | # Generates Mocks file
29 | # @returns self
30 | def create_mocks
31 | Generate.new.call
32 | self
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/active_mocker/railtie.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | class Railtie < Rails::Railtie
4 | rake_tasks do
5 | load "active_mocker/task.rake"
6 | end
7 |
8 | config.to_prepare do
9 | ActiveMocker::Config.load_defaults
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/lib/active_mocker/rspec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | module Rspec
4 | # @return ActiveMocker::LoadedMocks
5 | def active_mocker
6 | ActiveMocker::LoadedMocks
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/lib/active_mocker/rspec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "active_mocker/loaded_mocks"
3 | require "active_mocker/rspec"
4 |
5 | RSpec.configure do |config|
6 | config.include ActiveMocker::Rspec
7 |
8 | config.before(:each, active_mocker: true) do
9 | unless ENV["RUN_WITH_RAILS"] && self.class.metadata[:rails_compatible]
10 | active_mocker.mocks.each { |class_name, mock| stub_const(class_name, mock) }
11 | end
12 | if (mapping = active_mocker.features[:stub_active_record_exceptions])
13 | mapping.each { |class_name, mock| stub_const(class_name, mock) }
14 | end
15 | end
16 |
17 | config.after(:all, active_mocker: true) do
18 | ActiveMocker::LoadedMocks.delete_all
19 | end
20 |
21 | config.before(:all, active_mocker: true) do
22 | ActiveMocker::LoadedMocks.delete_all
23 | end
24 |
25 | config.after(:each, active_mocker: true) do
26 | ActiveMocker::LoadedMocks.delete_all if active_mocker.features[:delete_all_before_example]
27 | end
28 |
29 | config.before(:each, active_mocker: true) do
30 | ActiveMocker::LoadedMocks.delete_all if active_mocker.features[:delete_all_before_example]
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/active_mocker/task.rake:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | namespace :active_mocker do
3 | desc("Rebuild mocks.")
4 | task build: :environment do
5 | ActiveMocker.configure do |c|
6 | c.single_model_path = ENV["MODEL"] if ENV["MODEL"]
7 | c.model_dir = ENV["MODEL_DIR"] if ENV["MODEL_DIR"]
8 | c.mock_dir = ENV["MOCK_DIR"] if ENV["MOCK_DIR"]
9 | c.progress_bar = false if ENV["MUTE_PROGRESS_BAR"]
10 | c.error_verbosity = ENV["ERROR_VERBOSITY"].to_i if ENV["ERROR_VERBOSITY"]
11 | c.disable_modules_and_constants = false
12 | end.create_mocks
13 | end
14 |
15 | desc("Run all tests tagged active_mocker")
16 | task :test do
17 | sh "rspec --tag active_mocker"
18 | end
19 |
20 | desc("Run all tests tagged active_mocker and rails_compatible and will disable model stubbing")
21 | task :rails_compatible do
22 | sh "RUN_WITH_RAILS=1 rspec --tag rails_compatible"
23 | end
24 | end
25 |
26 | ["db:migrate", "db:rollback"].each do |task|
27 | Rake::Task[task].enhance do
28 | Rake::Task["active_mocker:build"].invoke
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/lib/active_mocker/template_creator.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "forwardable"
3 |
4 | module ActiveMocker
5 | class TemplateCreator
6 | def initialize(erb_template:, file_out: nil, binding:, post_process: -> (str) { str })
7 | @erb_template = erb_template
8 | @binding = binding
9 | @file_out = file_out || Tempfile.new("TemplateModel")
10 | @post_process = post_process
11 | end
12 |
13 | def render
14 | template = ERB.new(erb_template.read, nil, ">")
15 | file_out.write post_process.call(template.result(binding))
16 | file_out
17 | end
18 |
19 | private
20 |
21 | attr_reader :erb_template, :binding, :file_out, :post_process
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/active_mocker/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module ActiveMocker
3 | VERSION = "2.6.2"
4 | module Mock
5 | VERSION = "2" # This increments when breaking changes happen in the generated mocks
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/log/.keep
--------------------------------------------------------------------------------
/spec/gemfile_version_match_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | RSpec.describe "Gemfile Version Match" do
3 | it "rails_4.2.gemfile.lock" do
4 | file = File.join(File.expand_path("../../", __FILE__), "test_rails_app/gemfiles/rails_4.2.gemfile.lock")
5 | expect(!File.readlines(file).grep(/active_mocker \(#{Regexp.quote(ActiveMocker::VERSION)}\)/).empty?).to eq true
6 | end
7 |
8 | it "rails_5.2.gemfile.lock" do
9 | file = File.join(File.expand_path("../../", __FILE__), "test_rails_app/gemfiles/rails_5.2.gemfile.lock")
10 | expect(!File.readlines(file).grep(/active_mocker \(#{Regexp.quote(ActiveMocker::VERSION)}\)/).empty?).to eq true
11 | end
12 |
13 | it "rails_6.0.gemfile.lock" do
14 | file = File.join(File.expand_path("../../", __FILE__), "test_rails_app/gemfiles/rails_6.0.gemfile.lock")
15 | expect(!File.readlines(file).grep(/active_mocker \(#{Regexp.quote(ActiveMocker::VERSION)}\)/).empty?).to eq true
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/config_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "logger"
4 | require "active_mocker/config"
5 |
6 | describe ActiveMocker::Config do
7 | after do
8 | described_class.reset_all
9 | described_class.load_defaults
10 | end
11 |
12 | before do
13 | described_class.reset_all
14 | described_class.load_defaults
15 | end
16 |
17 | it do
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/file_path_to_ruby_class_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/file_path_to_ruby_class"
4 | require "active_support/core_ext/string"
5 |
6 | RSpec.describe ActiveMocker::FilePathToRubyClass do
7 | describe "#to_s" do
8 | subject do
9 | described_class.new(base_path: base_path,
10 | class_path: class_path).to_s
11 | end
12 |
13 | context "single class" do
14 | let(:base_path) { "user/my_app/models" }
15 | let(:class_path) { "user/my_app/models/user.rb" }
16 |
17 | it { expect(subject).to eq "User" }
18 | end
19 |
20 | context "one deep namespaced class" do
21 | let(:base_path) { "user/my_app/models" }
22 | let(:class_path) { "user/my_app/models/api/user.rb" }
23 |
24 | it { expect(subject).to eq "Api::User" }
25 | end
26 |
27 | context "two deep namespaced class" do
28 | let(:base_path) { "user/my_app/models" }
29 | let(:class_path) { "user/my_app/models/api/b/user.rb" }
30 |
31 | it { expect(subject).to eq "Api::B::User" }
32 | end
33 |
34 | context "three deep namespaced class" do
35 | let(:base_path) { "user/my_app/models" }
36 | let(:class_path) { "user/my_app/models/api/b/c/user.rb" }
37 |
38 | it { expect(subject).to eq "Api::B::C::User" }
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/association_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock/queries"
4 | require "active_mocker/mock/collection"
5 | require "active_mocker/mock/mockable_method"
6 | require "active_mocker/mock/relation"
7 | require "active_mocker/mock/association"
8 | require "active_mocker/mock/has_many"
9 | require "ostruct"
10 | require_relative "has_many_shared_example"
11 | require_relative "queriable_shared_example"
12 |
13 | describe ActiveMocker::Association do
14 | it_behaves_like "Queriable", -> (*args) { described_class.new(args.flatten) }
15 | end
16 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/base_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "logger"
4 | require "active_mocker/mock"
5 | require_relative "queriable_shared_example"
6 | require "active_mocker/mock/exceptions"
7 | describe ActiveMocker::Base do
8 | class ActiveMocker::Base
9 | class << self
10 | def abstract_class?
11 | false
12 | end
13 |
14 | attr_writer :records
15 | end
16 |
17 | def id
18 | self.class.attributes[:id]
19 | end
20 |
21 | def id=(val)
22 | self.class.attributes[:id] = val
23 | end
24 | end
25 |
26 | it_behaves_like "Queriable", -> (*args) {
27 | ActiveMocker::Base.clear_mock
28 | ActiveMocker::Base.send(:records=, ActiveMocker::Records.new(args.flatten))
29 | ActiveMocker::Base
30 | }
31 |
32 | describe "destroy" do
33 | subject { described_class.create }
34 |
35 | it "will delegate to delete" do
36 | subject.destroy
37 | expect(described_class.count).to eq 0
38 | end
39 | end
40 |
41 | describe "::_find_associations_by_class" do
42 | it do
43 | allow(ActiveMocker::Base).to receive(:associations_by_class) { { "User" => [:customers] } }
44 | result = described_class._find_associations_by_class("User")
45 | expect(result).to eq [:customers]
46 | end
47 | end
48 |
49 | describe "::classes" do
50 | it "raises an error if not loaded" do
51 | expect{described_class.send(:classes, "Abc", true)}.to raise_error(ActiveMocker::MockNotLoaded, "The ActiveMocker version of Abc is not required.")
52 | end
53 | end
54 |
55 | before do
56 | described_class.delete_all
57 | end
58 |
59 | after do
60 | described_class.delete_all
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/belongs_to_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock"
4 | require "active_mocker/mock/belongs_to"
5 | describe ActiveMocker::BelongsTo do
6 | it "item can be an non ActiveMock that does not respond to save" do
7 | described_class.new(double("NonActiveMocker"), child_self: double("ActiveMocker", persisted?: true, write_attribute: true), foreign_key: 1)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/collection_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock/collection"
4 |
5 | describe ActiveMocker::Collection do
6 | describe '#<<' do
7 | it "will add a single item to the array" do
8 | subject << "item"
9 | expect(subject.count).to eq 1
10 | expect(subject.first).to eq "item"
11 | end
12 |
13 | it "will add a many item to the array" do
14 | subject << %w(item1 item2 item3)
15 | expect(subject.count).to eq 3
16 | expect(subject).to eq %w(item1 item2 item3)
17 | end
18 | end
19 |
20 | describe "empty?" do
21 | it "returns true if collection is empty" do
22 | expect(subject.empty?).to eq true
23 | end
24 |
25 | it "returns false if collection is not empty" do
26 | subject << 1
27 | expect(subject.empty?).to eq false
28 | end
29 | end
30 |
31 | describe "each" do
32 | it "can iterate over array" do
33 | sum = 0
34 | described_class.new([1, 2]).each { |a| sum += a }
35 | expect(sum).to eq 3
36 | end
37 | end
38 |
39 | describe "map" do
40 | it "return a new array" do
41 | expect(described_class.new([1, 2]).map { |a| a + a }).to eq [2, 4]
42 | end
43 |
44 | it "return an instance of the class" do
45 | expect(described_class.new([1, 2]).map { |a| a + a }).to be_a_kind_of Array
46 | end
47 | end
48 |
49 | describe "[]" do
50 | it "can get an item from the array" do
51 | expect(described_class.new([1, 2])[0]).to eq 1
52 | end
53 |
54 | it "can get a range of items from the array" do
55 | expect(described_class.new([1, 2])[0..1]).to eq [1, 2]
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/has_and_belongs_to_many_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock/collection"
4 | require "active_mocker/mock/queries"
5 | require "active_mocker/mock/relation"
6 | require "active_mocker/mock/association"
7 | require "active_mocker/mock/has_many"
8 | require "active_mocker/mock/has_and_belongs_to_many"
9 | require "active_mocker/mock"
10 | require "ostruct"
11 | require "active_support/inflector"
12 | require_relative "has_many_shared_example"
13 | require_relative "queriable_shared_example"
14 |
15 | describe ActiveMocker::HasAndBelongsToMany do
16 | it_behaves_like "HasMany"
17 | it_behaves_like "Queriable", -> (*args) { described_class.new(args.flatten) }
18 | end
19 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/has_many_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock/queries"
4 | require "active_mocker/mock/collection"
5 | require "active_mocker/mock/relation"
6 | require "active_mocker/mock/association"
7 | require "active_mocker/mock/has_many"
8 | require "active_mocker/mock"
9 | require "ostruct"
10 | require "active_support/inflector"
11 | require_relative "has_many_shared_example"
12 | require_relative "queriable_shared_example"
13 |
14 | describe ActiveMocker::HasMany do
15 | it_behaves_like "HasMany"
16 | it_behaves_like "Queriable", -> (*args) { described_class.new(args.flatten) }
17 | end
18 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/hash_process_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock/hash_process"
4 |
5 | describe ActiveMocker::HashProcess do
6 | it do
7 | subject = described_class.new({ id: 1 }, ->(val) { val * 2 })
8 | expect(subject[:id]).to eq 2
9 | end
10 |
11 | it "merge" do
12 | hash1 = described_class.new({ id: 1 }, ->(val) { val })
13 | hash2 = described_class.new({ value: 2 }, ->(val) { val })
14 | subject = hash1.merge(hash2)
15 | expect(subject.hash).to eq(id: 1, value: 2)
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/records_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock/records"
4 | require "active_mocker/mock/exceptions"
5 | require "active_support/hash_with_indifferent_access"
6 | require "active_support/core_ext/object/try"
7 |
8 | describe ActiveMocker::Records do
9 | subject { described_class.new }
10 |
11 | let(:record) { RecordBase.new }
12 |
13 | before do
14 | class RecordBase
15 | attr_accessor :id
16 |
17 | def inspect
18 | { id: id }
19 | end
20 | end
21 | end
22 |
23 | describe '#insert' do
24 | it "adds to records" do
25 | expect(subject.insert(record).to_a).to include(record)
26 | end
27 |
28 | it "gets next id" do
29 | subject.insert(record)
30 | expect(record.id).to eq 1
31 | end
32 |
33 | it "validate unique id" do
34 | subject.insert(record)
35 | new_record = RecordBase.new
36 | new_record.id = 1
37 | expect { subject.insert(new_record) }.to raise_exception(ActiveMocker::IdError, "Duplicate ID found for record {:id=>1}")
38 | end
39 |
40 | context 'id#to_i called' do
41 | it "validate string" do
42 | new_record = RecordBase.new
43 | new_record.id = "aa"
44 | subject.insert(new_record)
45 | expect(new_record.id).to eq(0)
46 | end
47 |
48 | it "validate float" do
49 | new_record = RecordBase.new
50 | new_record.id = 1.1
51 | subject.insert(new_record)
52 | expect(new_record.id).to eq(1)
53 | end
54 | end
55 | end
56 |
57 | describe '#delete' do
58 | before do
59 | subject.insert(record)
60 | subject.delete(record)
61 | end
62 |
63 | it "deletes from record array" do
64 | expect(subject.to_a).to eq []
65 | end
66 |
67 | it "raises if record is not in array" do
68 | expect { described_class.new.delete(record) }.to raise_error(ActiveMocker::RecordNotFound, "Record has not been created.")
69 | end
70 | end
71 |
72 | describe '#existis?' do
73 | it "returns true if has record" do
74 | subject.insert(record)
75 | expect(subject.exists?(record)).to eq true
76 | end
77 |
78 | it "returns false if doesn't have record" do
79 | expect(subject.exists?(record)).to eq false
80 | end
81 | end
82 |
83 | describe '#new_record?' do
84 | it "returns false if has record" do
85 | subject.insert(record)
86 | expect(subject.new_record?(record)).to eq false
87 | end
88 |
89 | it "returns true if doesn't have record" do
90 | expect(subject.new_record?(record)).to eq true
91 | end
92 | end
93 |
94 | describe '#persisted?' do
95 | it "returns true if has record" do
96 | subject.insert(record)
97 | expect(subject.persisted?(record.id)).to eq true
98 | end
99 |
100 | it "returns true if doesn't have record" do
101 | expect(subject.persisted?(record.id)).to eq false
102 | end
103 | end
104 |
105 | describe '#reset' do
106 | it "clears records array and record_index hash" do
107 | subject.insert(record)
108 | subject.reset
109 | expect(subject.send(:records)).to eq([])
110 | end
111 | end
112 | end
113 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/mock/relation_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/mock"
4 | require "ostruct"
5 | require_relative "has_many_shared_example"
6 | require_relative "queriable_shared_example"
7 |
8 | describe ActiveMocker::Relation do
9 | it_behaves_like "Queriable", -> (*args) { described_class.new(args.flatten) }
10 | end
11 |
--------------------------------------------------------------------------------
/spec/lib/active_mocker/template_creator_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "spec/support/strip_heredoc"
4 | require "active_mocker/template_creator"
5 | require "active_record_schema_scrapper/attribute"
6 | require "active_record_schema_scrapper/attributes"
7 | require "tempfile"
8 |
9 | describe ActiveMocker::TemplateCreator do
10 | using StripHeredoc
11 |
12 | describe "render" do
13 | it "return a file" do
14 | expect(described_class.new(erb_template: double("file", read: "", path: ""), binding: {}.send(:binding)).render.class).to eq(Tempfile)
15 | end
16 |
17 | it "takes an output file to write to" do
18 | file_out = Tempfile.new("fileout")
19 | described_class.new(erb_template: double("file", read: "hello", path: ""),
20 | binding: {}.send(:binding),
21 | file_out: file_out).render.class
22 | file_out.rewind
23 | expect(file_out.read).to eq("hello")
24 | end
25 |
26 | it "given template it will fulfill it based on template model" do
27 | class TestModel
28 | def model_name
29 | :ModelName
30 | end
31 |
32 | def get_binding
33 | binding
34 | end
35 | end
36 | template = Tempfile.new("Template")
37 | template.write <<-ERB
38 | class <%= model_name %>
39 |
40 | end
41 | ERB
42 | template.rewind
43 | result = described_class.new(erb_template: template,
44 | binding: TestModel.new.get_binding).render
45 | result.rewind
46 | expect(result.read).to eq(<<-RUBY)
47 | class ModelName
48 | end
49 | RUBY
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/spec/lib/model_nested.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module Api
3 | class ModelNested < ActiveRecord::Base
4 | MY_CONSTANT_VALUE = 3
5 | module FooBar
6 | end
7 |
8 | # include FooBar
9 | # extend Baz
10 | include PostMethods
11 | # include ModelCore::PlanService::Dah
12 |
13 | belongs_to :company, class_name: "PlanServiceCategory", foreign_key: "category_id"
14 | belongs_to :person, through: "customer"
15 | has_many :users
16 | has_one :account
17 | has_and_belongs_to_many :disclosures
18 | devise :database_authenticatable, :registerable,
19 | :recoverable, :rememberable, :trackable, :validatable
20 |
21 | def self.duper(_value, *_args)
22 | end
23 |
24 | scope :named, ->(name, value = nil, options = {}) {}
25 | scope :other_named, -> {}
26 |
27 | def foo(foobar, value)
28 | end
29 |
30 | def self.foo
31 | end
32 |
33 | def superman
34 | end
35 |
36 | def self.bang!
37 | end
38 |
39 | private
40 |
41 | def bar
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/spec/lib/models/model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # ActiveMocker.safe_methods :superman, scopes: [:named], instance_methods: [:foo], class_methods: [:bang!, :foo]
3 | class Model < ActiveRecord::Base
4 | MY_CONSTANT_VALUE = 3
5 | MY_OBJECT = Object.new
6 | module FooBar
7 | end
8 |
9 | # include FooBar
10 | # extend Baz
11 | include PostMethods
12 | # include ModelCore::PlanService::Dah
13 |
14 | belongs_to :company, class_name: "PlanServiceCategory", foreign_key: "category_id"
15 | belongs_to :person, through: "customer"
16 | has_many :users
17 | has_one :account
18 | has_and_belongs_to_many :disclosures
19 | devise :database_authenticatable, :registerable,
20 | :recoverable, :rememberable, :trackable, :validatable
21 |
22 | def self.duper(value, *args)
23 | end
24 |
25 | scope :named, ->(name, value = nil, options = {}) { 2 + 2}
26 | scope :other_named, -> { 1 + 1}
27 | alias_attribute :full_name, :name
28 | def foo(foobar, value)
29 | end
30 |
31 | class << self
32 | def foo
33 | :buz
34 | end
35 | end
36 |
37 | def superman
38 | __method__
39 | end
40 |
41 | def self.bang!
42 | :boom!
43 | end
44 |
45 | private
46 |
47 | def bar
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/spec/lib/models/non_active_record_model.rb:
--------------------------------------------------------------------------------
1 | class NonActiveRecordModel
2 | end
3 |
--------------------------------------------------------------------------------
/spec/lib/models/some_namespace/some_module.rb:
--------------------------------------------------------------------------------
1 | module SomeNamespace
2 | module SomeModule
3 | def some_method
4 | "some return value"
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/lib/person.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class Person < ActiveRecord::Base
3 | belongs_to :zip_code
4 |
5 | def full_name
6 | "#{first_name} #{last_name}"
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/lib/post_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module PostMethods
3 | def sample_method
4 | end
5 |
6 | def content
7 | "from PostMethods"
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rspec"
3 | $LOAD_PATH.unshift File.join(File.expand_path("../../", __FILE__))
4 | $LOAD_PATH.unshift File.join(File.expand_path("../../", "lib"))
5 |
--------------------------------------------------------------------------------
/spec/support/strip_heredoc.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module StripHeredoc
3 | refine String do
4 | def strip_heredoc
5 | indent = scan(/^[ \t]*(?=\S)/).min.size || 0
6 | gsub(/^[ \t]{#{indent}}/, "")
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/unit_logger.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "logger"
3 | class UnitLogger
4 | def self.method_missing(meth, *args, &block)
5 | return unit.send(meth, *args, &block) unless unit.nil?
6 | return Rails.logger.send(meth, *args, &block) if defined? Rails
7 | end
8 |
9 | def self.unit
10 | return @logger unless @logger.nil?
11 | FileUtils.mkdir_p "log" unless File.directory? "log"
12 | File.open("log/test.log", "w").close unless File.exist? "log/test.log"
13 | @logger = ::Logger.new("log/test.log")
14 | @logger.formatter = proc do |_severity, _datetime, _progname, msg|
15 | msg
16 | end
17 | @logger.level = ::Logger::DEBUG
18 | @logger
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/tasks/integration.rake:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | desc "run integration specs"
3 | task :integration do
4 | Dir.chdir("test_rails_app") do
5 | root = File.expand_path("../../", __FILE__)
6 | gemfiles, error_verbosity = if ENV["TRAVIS"]
7 | [[ENV["BUNDLE_GEMFILE"]], "1"]
8 | else
9 | [Dir[Pathname(File.join(root, "test_rails_app/gemfiles/*.gemfile")).expand_path], 0]
10 | end
11 | Bundler.with_clean_env do
12 | gemfiles.each do |gemfile|
13 | Pathname(gemfile).basename.to_s =~ /rails_(\d\.\d).*/
14 | rails_version = $1
15 | mock_dir = File.expand_path(File.join(root, "test_rails_app/spec/mocks", rails_version))
16 | sh "RAILS_VERSION=#{rails_version} MOCK_DIR=#{mock_dir} MUTE_PROGRESS_BAR=true ERROR_VERBOSITY=#{error_verbosity} BUNDLE_GEMFILE=#{gemfile} bundle exec rake active_mocker:build"
17 | sh "RAILS_VERSION=#{rails_version} BUNDLE_GEMFILE=#{gemfile} bundle exec rspec"
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/tasks/setup.rake:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | desc "setup"
3 | task :setup do
4 | unless ENV["TRAVIS"]
5 | Bundler.with_clean_env do
6 | rails_test_gemfile = File.expand_path(File.dirname(__FILE__) + "/../test_rails_app/Gemfile")
7 | sh "BUNDLE_GEMFILE=#{rails_test_gemfile} bundle install --local 2>&1 >/dev/null" do |ok, _res|
8 | sh "BUNDLE_GEMFILE=#{rails_test_gemfile} bundle install" unless ok
9 | end
10 | Dir.chdir("test_rails_app") do
11 | sh "appraisal bundle install"
12 | end
13 | end
14 | end
15 | Dir.chdir("test_rails_app") do
16 | sh "rake db:setup"
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/tasks/unit.rake:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | desc "Run unit specs"
4 | task :unit do
5 | sh "bundle exec rspec"
6 | end
7 |
--------------------------------------------------------------------------------
/test_rails_app/.secret:
--------------------------------------------------------------------------------
1 | f189df0a71311525020854546e98bafd7f46ef622edaa129c78fabfdeabf6972ab027e9a3d4acee4204b97adbefb32c609216a25bfcd145d7dda29cdd8049618
--------------------------------------------------------------------------------
/test_rails_app/Appraisals:
--------------------------------------------------------------------------------
1 | appraise "rails-4.2" do
2 | gem "rails", "~> 4.2.8"
3 | gem "rspec", "~> 3.4"
4 | gem "rspec-rails", "~>3.4"
5 | end
6 |
7 | appraise "rails-5.2" do
8 | gem "rails", "~> 5.2.1"
9 | gem "rspec", "3.7.0"
10 | gem "rspec-rails", "3.7.0"
11 | end
12 |
13 | appraise "rails-6.0" do
14 | gem 'sqlite3', '~> 1.4'
15 | gem "rails", "~> 6.0.0"
16 | gem "actionpack", "~> 6.0.0"
17 | gem "rspec", "3.8.0"
18 | gem "rspec-rails", "4.0.0.beta2"
19 | end
20 |
--------------------------------------------------------------------------------
/test_rails_app/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | source "https://rubygems.org"
3 |
4 | gem "rails", "~>4.2"
5 | gem "appraisal"
6 |
7 | gem "capybara", "~>3.15.1"
8 | gem "rspec", ">= 3.4"
9 | gem "sqlite3", "~>1.3.13"
10 | gem "active_mocker", path: "../"
11 | gem "omniauth-identity", "1.1.1"
12 |
--------------------------------------------------------------------------------
/test_rails_app/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2013 Michael Hartl
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/test_rails_app/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path("../config/application", __FILE__)
6 |
7 | SampleApp::Application.load_tasks
8 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/test_rails_app/app/models/.keep
--------------------------------------------------------------------------------
/test_rails_app/app/models/account.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # # ActiveMocker.all_methods_safe
3 | class Account < ActiveRecord::Base
4 | belongs_to :user
5 |
6 | def safe
7 | :hello
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/api/customer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module Api
3 | class Customer < ActiveRecord::Base
4 | has_many :microposts, -> { order("created_at DESC") }
5 |
6 | def User.new_remember_token
7 | SecureRandom.urlsafe_base64
8 | end
9 |
10 | def User.digest(token)
11 | Digest::SHA1.hexdigest(token.to_s)
12 | end
13 |
14 | def feed
15 | Micropost.from_users_followed_by(self)
16 | end
17 |
18 | def following?(other_user)
19 | relationships.find_by(followed_id: other_user.id)
20 | end
21 |
22 | def follow!(other_user)
23 | relationships.create!(followed_id: other_user.id)
24 | end
25 |
26 | def unfollow!(other_user)
27 | relationships.find_by(followed_id: other_user.id).destroy
28 | end
29 |
30 | def key_arg_reg(key:)
31 | end
32 |
33 | def key_arg_opt(key: nil)
34 | end
35 |
36 | def key_arg_rest(**key_rest)
37 | end
38 |
39 | def arg_rest(*key_rest)
40 | end
41 |
42 | private
43 |
44 | def create_remember_token
45 | self.remember_token = User.digest(User.new_remember_token)
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/child_model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # ActiveMocker.all_methods_safe
3 | class ChildModel < User
4 | has_many :accounts
5 |
6 | scope :by_credits, -> (credits) { where(credits: credits) }
7 | scope :i_take_a_block, -> () { where(credits: credits) }
8 |
9 | def child_method
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/has_no_parent.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class HasNoParent
3 | end
4 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/has_no_table.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class HasNoTable < ActiveRecord::Base
3 | self.abstract_class = true
4 | end
5 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/identity.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class Identity < OmniAuth::Identity::Models::ActiveRecord
3 | end
4 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/micropost.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "#{Rails.root}/lib/post_methods"
3 |
4 | class Micropost < ActiveRecord::Base
5 | belongs_to :user
6 | default_scope -> { order("created_at DESC") }
7 | MAGIC_ID_NUMBER = 90
8 | MAGIC_ID_STRING = "F-1"
9 |
10 | include PostMethods
11 | extend PostMethods
12 | include Core
13 |
14 | module DoNotIncludeInMock
15 | def sample_method
16 | end
17 | end
18 | include DoNotIncludeInMock
19 | # self.primary_key = :lol
20 | # self.table_name = :posts
21 | # Returns microposts from the users being followed by the given user.
22 | def self.from_users_followed_by(user = nil)
23 | followed_user_ids = "SELECT followed_id FROM relationships
24 | WHERE follower_id = :user_id"
25 | where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
26 | user_id: user.id)
27 | end
28 |
29 | def display_name
30 | end
31 |
32 | def post_id
33 | id
34 | end
35 |
36 | def i_take_block(&block)
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/micropost/core.rb:
--------------------------------------------------------------------------------
1 | class Micropost
2 | module Core
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/relationship.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | class Relationship < ActiveRecord::Base
3 | belongs_to :follower, class_name: "User"
4 | belongs_to :followed, class_name: "User"
5 | validates :follower_id, presence: true
6 | validates :followed_id, presence: true
7 | end
8 |
--------------------------------------------------------------------------------
/test_rails_app/app/models/user.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # ActiveMocker.safe_methods :initialize, :safe_method1, :safe_method2, scopes: [ :by_name ], class_methods: [:digest]
3 | class User < ActiveRecord::Base
4 | has_many :microposts, -> { order("created_at DESC") }
5 | has_many :relationships, foreign_key: "follower_id", dependent: :destroy
6 | has_many :followed_users, through: :relationships, source: :followed
7 | has_many :reverse_relationships, foreign_key: "followed_id",
8 | class_name: "Relationship",
9 | dependent: :destroy
10 | has_many :followers, through: :reverse_relationships, source: :follower
11 | has_one :account
12 | scope :find_by_name, -> (name) { where(name: name) }
13 | scope :by_name, -> (name) { where(name: name) }
14 | scope :no_arg_scope, -> { where(name: "name") }
15 |
16 | alias_attribute :first_and_last_name, :name
17 | enum status: { active: 0, archived: 1 }
18 | def self.new_remember_token
19 | SecureRandom.urlsafe_base64
20 | end
21 |
22 | def self.digest(token)
23 | Digest::SHA1.hexdigest(token.to_s)
24 | end
25 |
26 | def feed
27 | Micropost.from_users_followed_by(self)
28 | end
29 |
30 | def following?(other_user)
31 | relationships.find_by(followed_id: other_user.id)
32 | end
33 |
34 | def follow!(other_user)
35 | relationships.create!(followed_id: other_user.id)
36 | end
37 |
38 | def unfollow!(other_user)
39 | relationships.find_by(followed_id: other_user.id).destroy
40 | end
41 |
42 | def key_arg_reg(key:)
43 | end
44 |
45 | def key_arg_opt(key:nil)
46 | end
47 |
48 | def initialize(*args)
49 | @test_that_this_was_run = true
50 | super
51 | end
52 |
53 | def safe_method1
54 | 1+1
55 | end
56 |
57 | def safe_method2
58 | 2+2
59 | end
60 |
61 | private
62 |
63 | def create_remember_token
64 | self.remember_token = User.digest(User.new_remember_token)
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/test_rails_app/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4 | load Gem.bin_path("bundler", "bundle")
5 |
--------------------------------------------------------------------------------
/test_rails_app/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | APP_PATH = File.expand_path("../../config/application", __FILE__)
4 | require_relative "../config/boot"
5 | require "rails/commands"
6 |
--------------------------------------------------------------------------------
/test_rails_app/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | require_relative "../config/boot"
4 | require "rake"
5 | Rake.application.run
6 |
--------------------------------------------------------------------------------
/test_rails_app/bin/rspec:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 | #
4 | # This file was generated by Bundler.
5 | #
6 | # The application 'rspec' is installed as part of a gem, and
7 | # this file is here to facilitate running it.
8 | #
9 |
10 | require "pathname"
11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12 | Pathname.new(__FILE__).realpath)
13 |
14 | require "rubygems"
15 | require "bundler/setup"
16 |
17 | load Gem.bin_path("rspec-core", "rspec")
18 |
--------------------------------------------------------------------------------
/test_rails_app/config.ru:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # This file is used by Rack-based servers to start the application.
3 |
4 | require ::File.expand_path("../config/environment", __FILE__)
5 | run SampleApp::Application
6 |
--------------------------------------------------------------------------------
/test_rails_app/config/application.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require File.expand_path("../boot", __FILE__)
3 | # Pick the frameworks you want:
4 | require "active_record/railtie"
5 |
6 | Bundler.require(*Rails.groups)
7 | require 'rails/all'
8 | # require "rails/test_unit/railtie"
9 |
10 | # Assets should be precompiled for production (so we don't need the gems loaded then)
11 | # Bundler.require(*Rails.groups(assets: %w(development test)))
12 |
13 | module SampleApp
14 | class Application < Rails::Application
15 | # Settings in config/environments/* take precedence over those specified here.
16 | # Application configuration should go into files in config/initializers
17 | # -- all .rb files in that directory are automatically loaded.
18 |
19 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
20 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
21 | # config.time_zone = 'Central Time (US & Canada)'
22 |
23 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
24 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
25 | # config.i18n.default_locale = :de
26 | # I18n.enforce_available_locales = true
27 | I18n.enforce_available_locales = true
28 | config.autoload_paths << Rails.root.join("lib")
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/test_rails_app/config/boot.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Set up gems listed in the Gemfile.
3 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4 |
5 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
6 |
--------------------------------------------------------------------------------
/test_rails_app/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | development:
7 | adapter: sqlite3
8 | database: db/development.sqlite3
9 | pool: 5
10 | timeout: 5000
11 |
12 | # Warning: The database defined as "test" will be erased and
13 | # re-generated from your development database when you run "rake".
14 | # Do not set this db to the same as development or production.
15 | test:
16 | adapter: sqlite3
17 | encoding: utf8
18 | pool: 5
19 | timeout: 5000
20 | database: db/test.sqlite3
21 | verbosity: quiet
22 |
23 | production:
24 | adapter: sqlite3
25 | database: db/production.sqlite3
26 | pool: 5
27 | timeout: 5000
--------------------------------------------------------------------------------
/test_rails_app/config/environment.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Load the rails application.
3 | require File.expand_path("../application", __FILE__)
4 |
5 | # Initialize the rails application.
6 | SampleApp::Application.initialize!
7 |
--------------------------------------------------------------------------------
/test_rails_app/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | SampleApp::Application.configure do
3 | # Settings specified here will take precedence over those in config/application.rb.
4 |
5 | # In the development environment your application's code is reloaded on
6 | # every request. This slows down response time but is perfect for development
7 | # since you don't have to restart the web server when you make code changes.
8 | config.cache_classes = false
9 |
10 | # Do not eager load code on boot.
11 | config.eager_load = false
12 |
13 | # Show full error reports and disable caching.
14 | config.consider_all_requests_local = true
15 |
16 | # Don't care if the mailer can't send.
17 |
18 | # Print deprecation notices to the Rails logger.
19 | config.active_support.deprecation = :log
20 |
21 | # Raise an error on page load if there are pending migrations
22 | config.active_record.migration_error = :page_load
23 |
24 | # Debug mode disables concatenation and preprocessing of assets.
25 | end
26 |
--------------------------------------------------------------------------------
/test_rails_app/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | SampleApp::Application.configure do
3 | # Settings specified here will take precedence over those in config/application.rb.
4 |
5 | # Code is not reloaded between requests.
6 | config.cache_classes = true
7 |
8 | # Eager load code on boot. This eager loads most of Rails and
9 | # your application in memory, allowing both thread web servers
10 | # and those relying on copy on write to perform better.
11 | # Rake tasks automatically ignore this option for performance.
12 | config.eager_load = true
13 |
14 | # Full error reports are disabled and caching is turned on.
15 | config.consider_all_requests_local = false
16 | config.action_controller.perform_caching = true
17 |
18 | # Enable Rack::Cache to put a simple HTTP cache in front of your application
19 | # Add `rack-cache` to your Gemfile before enabling this.
20 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
21 | # config.action_dispatch.rack_cache = true
22 |
23 | # Compress JavaScripts and CSS.
24 | config.assets.js_compressor = :uglifier
25 | # config.assets.css_compressor = :sass
26 |
27 | # Whether to fallback to assets pipeline if a precompiled asset is missed.
28 | config.assets.compile = false
29 |
30 | # Generate digests for assets URLs.
31 | config.assets.digest = true
32 |
33 | # Version of your assets, change this if you want to expire all your assets.
34 | config.assets.version = "1.0"
35 |
36 | # Specifies the header that your server uses for sending files.
37 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
38 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
39 |
40 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
41 | config.force_ssl = true
42 |
43 | # Set to :debug to see everything in the log.
44 | config.log_level = :info
45 |
46 | # Prepend all log lines with the following tags.
47 | # config.log_tags = [ :subdomain, :uuid ]
48 |
49 | # Use a different logger for distributed setups.
50 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
51 |
52 | # Use a different cache store in production.
53 | # config.cache_store = :mem_cache_store
54 |
55 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
56 | # config.action_controller.asset_host = "http://assets.example.com"
57 |
58 | # Precompile additional assets.
59 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
60 | # config.assets.precompile += %w( search.js )
61 |
62 | # Ignore bad email addresses and do not raise email delivery errors.
63 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
64 | # config.action_mailer.raise_delivery_errors = false
65 |
66 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
67 | # the I18n.default_locale when a translation can not be found).
68 | config.i18n.fallbacks = true
69 |
70 | # Send deprecation notices to registered listeners.
71 | config.active_support.deprecation = :notify
72 |
73 | # Disable automatic flushing of the log to improve performance.
74 | # config.autoflush_log = false
75 |
76 | # Use default logging formatter so that PID and timestamp are not suppressed.
77 | config.log_formatter = ::Logger::Formatter.new
78 | end
79 |
--------------------------------------------------------------------------------
/test_rails_app/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | SampleApp::Application.configure do
3 | # Settings specified here will take precedence over those in config/application.rb.
4 |
5 | # The test environment is used exclusively to run your application's
6 | # test suite. You never need to work with it otherwise. Remember that
7 | # your test database is "scratch space" for the test suite and is wiped
8 | # and recreated between test runs. Don't rely on the data there!
9 | config.cache_classes = true
10 |
11 | # Do not eager load code on boot. This avoids loading your whole application
12 | # just for the purpose of running a single test. If you are using a tool that
13 | # preloads Rails for running tests, you may have to set it to true.
14 | config.eager_load = false
15 |
16 | # Configure static asset server for tests with Cache-Control for performance.
17 | # Show full error reports and disable caching.
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates.
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment.
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 |
31 | # Print deprecation notices to the stderr.
32 | config.active_support.deprecation = :stderr
33 |
34 | # Speed up tests by lowering bcrypt's cost function.
35 | ActiveModel::SecurePassword.min_cost = true
36 | end
37 |
--------------------------------------------------------------------------------
/test_rails_app/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
5 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
6 |
7 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
8 | # Rails.backtrace_cleaner.remove_silencers!
9 |
--------------------------------------------------------------------------------
/test_rails_app/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Configure sensitive parameters which will be filtered from the log file.
5 | Rails.application.config.filter_parameters += [:password]
6 |
--------------------------------------------------------------------------------
/test_rails_app/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Add new inflection rules using the following format. Inflections
5 | # are locale specific, and you may define rules for as many different
6 | # locales as you wish. All of these examples are active by default:
7 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
8 | # inflect.plural /^(ox)$/i, '\1en'
9 | # inflect.singular /^(ox)en/i, '\1'
10 | # inflect.irregular 'person', 'people'
11 | # inflect.uncountable %w( fish sheep )
12 | # end
13 |
14 | # These inflection rules are supported but not enabled by default:
15 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
16 | # inflect.acronym 'RESTful'
17 | # end
18 |
--------------------------------------------------------------------------------
/test_rails_app/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Add new mime types for use in respond_to blocks:
5 | # Mime::Type.register "text/richtext", :rtf
6 | # Mime::Type.register_alias "text/html", :iphone
7 |
--------------------------------------------------------------------------------
/test_rails_app/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # Make sure your secret_key_base is kept private
5 | # if you're sharing your code publicly, such as by adding
6 | # .secret to your .gitignore file.
7 |
8 | require "securerandom"
9 |
10 | def secure_token
11 | token_file = Rails.root.join(".secret")
12 | if File.exist?(token_file)
13 | # Use the existing token.
14 | File.read(token_file).chomp
15 | else
16 | # Generate a new token and store it in token_file.
17 | token = SecureRandom.hex(64)
18 | File.write(token_file, token)
19 | token
20 | end
21 | end
22 |
23 | SampleApp::Application.config.secret_key_base = secure_token
24 |
--------------------------------------------------------------------------------
/test_rails_app/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | SampleApp::Application.config.session_store :cookie_store, key: "_sample_app_session"
5 |
--------------------------------------------------------------------------------
/test_rails_app/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # Be sure to restart your server when you modify this file.
3 |
4 | # This file contains settings for ActionController::ParamsWrapper which
5 | # is enabled by default.
6 |
7 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
8 | ActiveSupport.on_load(:action_controller) do
9 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
10 | end
11 |
12 | # To enable root element in JSON for ActiveRecord objects.
13 | # ActiveSupport.on_load(:active_record) do
14 | # self.include_root_in_json = true
15 | # end
16 |
--------------------------------------------------------------------------------
/test_rails_app/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
--------------------------------------------------------------------------------
/test_rails_app/config/routes.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | SampleApp::Application.routes.draw do
3 | resources :users do
4 | member do
5 | get :following, :followers
6 | end
7 | end
8 | resources :sessions, only: [:new, :create, :destroy]
9 | resources :microposts, only: [:create, :destroy]
10 | resources :relationships, only: [:create, :destroy]
11 | root to: 'static_pages#home'
12 | match "/signup", to: 'users#new', via: "get"
13 | match "/signin", to: 'sessions#new', via: "get"
14 | match "/signout", to: 'sessions#destroy', via: "delete"
15 | match "/help", to: 'static_pages#help', via: "get"
16 | match "/about", to: 'static_pages#about', via: "get"
17 | match "/contact", to: 'static_pages#contact', via: "get"
18 | end
19 |
--------------------------------------------------------------------------------
/test_rails_app/db/migrate/20160621215939_create_products.rb:
--------------------------------------------------------------------------------
1 | class CreateProducts < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :products do |t|
4 | t.string :name
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test_rails_app/db/schema.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 | # This file is auto-generated from the current state of the database. Instead
3 | # of editing this file, please use the migrations feature of Active Record to
4 | # incrementally modify your database, and then regenerate this schema definition.
5 | #
6 | # Note that this schema.rb definition is the authoritative source for your
7 | # database schema. If you need to create the application database on another
8 | # system, you should be using db:schema:load, not running all the migrations
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 | # you'll amass, the slower it'll run and the greater likelihood for issues).
11 | #
12 | # It's strongly recommended that you check this file into your version control system.
13 |
14 | ActiveRecord::Schema.define(version: 20160621215939) do
15 |
16 | create_table "accounts", force: :cascade do |t|
17 | t.integer "user_id"
18 | t.decimal "balance"
19 | end
20 |
21 | create_table "customers", force: :cascade do |t|
22 | t.string "name"
23 | t.string "email", default: ""
24 | t.decimal "credits", precision: 19, scale: 6, default: -1.0
25 | t.datetime "created_at"
26 | t.datetime "updated_at"
27 | t.string "password_digest"
28 | t.boolean "remember_token", default: true
29 | t.boolean "admin", default: false
30 | end
31 |
32 | create_table "identities", force: :cascade do |t|
33 | t.string "name"
34 | t.string "email", default: "n/a"
35 | t.decimal "credits", precision: 19, scale: 6, default: -2.0
36 | t.datetime "created_at"
37 | t.datetime "updated_at"
38 | t.string "password_digest"
39 | t.boolean "remember_token", default: true
40 | t.boolean "admin", default: false
41 | end
42 |
43 | create_table "microposts", force: :cascade do |t|
44 | t.string "content"
45 | t.integer "user_id"
46 | t.integer "up_votes"
47 | t.datetime "created_at"
48 | t.datetime "updated_at"
49 | t.index ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at"
50 | end
51 |
52 | create_table "products", force: :cascade do |t|
53 | t.string "name"
54 | end
55 |
56 | create_table "relationships", force: :cascade do |t|
57 | t.integer "follower_id"
58 | t.integer "followed_id"
59 | t.datetime "created_at"
60 | t.datetime "updated_at"
61 | t.index ["followed_id"], name: "index_relationships_on_followed_id"
62 | t.index ["follower_id", "followed_id"], name: "index_relationships_on_follower_id_and_followed_id", unique: true
63 | t.index ["follower_id"], name: "index_relationships_on_follower_id"
64 | end
65 |
66 | create_table "users", force: :cascade do |t|
67 | t.string "name"
68 | t.string "email", default: ""
69 | t.decimal "credits", precision: 19, scale: 6, default: -1.0
70 | t.datetime "requested_at", default: DateTime.parse("3rd Feb 2001 04:05:06+03:30")
71 | t.datetime "created_at"
72 | t.datetime "updated_at"
73 | t.string "password_digest"
74 | t.boolean "remember_token", default: true
75 | t.boolean "admin", default: false
76 | t.index ["email"], name: "index_users_on_email", unique: true
77 | t.index ["remember_token"], name: "index_users_on_remember_token"
78 | t.integer :status, default: 0
79 | end
80 |
81 | end
82 |
--------------------------------------------------------------------------------
/test_rails_app/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | # This file should contain all the record creation needed to seed the database with its default values.
3 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
4 | #
5 | # Examples:
6 | #
7 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
8 | # Mayor.create(name: 'Emanuel', city: cities.first)
9 |
--------------------------------------------------------------------------------
/test_rails_app/gemfiles/rails_4.2.gemfile:
--------------------------------------------------------------------------------
1 | # This file was generated by Appraisal
2 |
3 | source "https://rubygems.org"
4 |
5 | gem "rails", "~> 4.2.8"
6 | gem "appraisal"
7 | gem "capybara", "~>3.15.1"
8 | gem "rspec", "~> 3.4"
9 | gem "sqlite3", "~>1.3.13"
10 | gem "active_mocker", path: "../../"
11 | gem "omniauth-identity", "1.1.1"
12 | gem "rspec-rails", "~>3.4"
13 |
--------------------------------------------------------------------------------
/test_rails_app/gemfiles/rails_5.2.gemfile:
--------------------------------------------------------------------------------
1 | # This file was generated by Appraisal
2 |
3 | source "https://rubygems.org"
4 |
5 | gem "rails", "~> 5.2.1"
6 | gem "appraisal"
7 | gem "capybara", "~>3.15.1"
8 | gem "rspec", "3.7.0"
9 | gem "sqlite3", "~>1.3.13"
10 | gem "active_mocker", path: "../../"
11 | gem "omniauth-identity", "1.1.1"
12 | gem "rspec-rails", "3.7.0"
13 |
--------------------------------------------------------------------------------
/test_rails_app/gemfiles/rails_6.0.gemfile:
--------------------------------------------------------------------------------
1 | # This file was generated by Appraisal
2 |
3 | source "https://rubygems.org"
4 |
5 | gem "rails", "~> 6.0.0"
6 | gem "appraisal"
7 | gem "capybara", "~>3.15.1"
8 | gem "rspec", "3.8.0"
9 | gem "sqlite3", "~> 1.4"
10 | gem "active_mocker", path: "../../"
11 | gem "omniauth-identity", "1.1.1"
12 | gem "actionpack", "~> 6.0.0"
13 | gem "rspec-rails", "4.0.0.beta2"
14 |
--------------------------------------------------------------------------------
/test_rails_app/lib/post_methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | module PostMethods
3 | def sample_method
4 | end
5 |
6 | def content
7 | "from PostMethods"
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/test_rails_app/lib/unit_logger.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "logger"
3 | class UnitLogger
4 | def self.method_missing(meth, *args, &block)
5 | return Rails.logger.send(meth, *args, &block) if defined? Rails
6 | unit.send(meth, *args, &block)
7 | end
8 |
9 | def self.unit
10 | return @logger unless @logger.nil?
11 | @logger = Logger.new(STDOUT)
12 | @logger.formatter = proc do |_severity, _datetime, _progname, msg|
13 | msg
14 | end
15 | @logger.level = Logger::DEBUG
16 | @logger
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/test_rails_app/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeisler/active_mocker/8c795c9ee8a8ef1e94d81fbcb0e44ab64e672928/test_rails_app/log/.keep
--------------------------------------------------------------------------------
/test_rails_app/spec/account_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rails_helper"
3 | require_mock "user_mock"
4 | require_mock "account_mock"
5 |
6 | describe AccountMock do
7 | it "has_one user" do
8 | user = UserMock.create
9 | account = described_class.new(user: user)
10 | expect(user.account).to eq account
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/test_rails_app/spec/api/customer_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rails_helper"
3 | require_mock "api/customer_mock"
4 |
5 | RSpec.describe Api::CustomerMock do
6 | describe "::mocked_class" do
7 | it "returns the class name with the namespace" do
8 | expect(described_class.send(:mocked_class)).to eq "Api::Customer"
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/test_rails_app/spec/child_model_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rails_helper"
3 | require "active_mocker/rspec_helper"
4 | require_mock "user_mock"
5 | require_mock "child_model_mock"
6 |
7 | describe ChildModel do
8 | it "column_names" do
9 | expect(ChildModelMock.column_names).to eq ChildModel.column_names
10 | end
11 |
12 | context "mutatable objects " do
13 | it "email" do
14 | ChildModelMock.new.email << "@"
15 | expect(ChildModelMock.new.email).to eq("")
16 | end
17 | end
18 |
19 | it "table_name" do
20 | expect(ChildModelMock.table_name).to eq ChildModel.table_name
21 | end
22 |
23 | it "reflections" do
24 | expect(ChildModelMock.reflections).to eq UserMock.reflections.merge("accounts" => nil)
25 | end
26 |
27 | it "has parent class of UserMock" do
28 | expect(ChildModelMock.superclass.name).to eq "UserMock"
29 | end
30 |
31 | it "has its methods" do
32 | expect(ChildModelMock.public_instance_methods.sort - Object.public_instance_methods).to eq ([:accounts, :accounts=, :child_method] + ChildModelMock.public_instance_methods.sort - Object.public_instance_methods).uniq.sort
33 | end
34 |
35 | it "has a parent method" do
36 | expect(ChildModelMock.instance_methods).to include(:id, :id=, :name, :name=, :email, :email=, :credits, :credits=, :created_at, :created_at=, :updated_at, :updated_at=, :password_digest, :password_digest=, :remember_token, :remember_token=, :admin, :admin=, :account, :account=, :build_account, :create_account, :create_account!, :microposts, :microposts=, :relationships, :relationships=, :followed_users, :followed_users=, :reverse_relationships, :reverse_relationships=, :followers, :followers=, :child_method, :feed, :following?, :follow!, :unfollow!)
37 | end
38 |
39 | it "scoped methods" do
40 | expect(ChildModelMock::Scopes.instance_methods).to include(*UserMock::Scopes.instance_methods, *:by_credits)
41 | end
42 |
43 | it "stubbed parent methods are stubbed on child" do
44 | allow_any_instance_of(UserMock).to receive(:feed) { "Feed!" }
45 | expect(ChildModelMock.new.feed).to eq "Feed!"
46 | end
47 |
48 | context "auto stubbing", active_mocker: true do
49 | it "is a mock" do
50 | expect(ChildModel.ancestors).to include(ActiveMocker::Base)
51 | end
52 |
53 | it "can be searched for" do
54 | expect(active_mocker.find("ChildModel").ancestors).to include(ActiveMocker::Base)
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/test_rails_app/spec/clear_after_all_example_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/rspec_helper"
4 | require "lib/post_methods"
5 | require_mock "micropost_mock"
6 | require_mock "user_mock"
7 |
8 | describe "1) State Not Shared between outer examples", active_mocker: true do
9 | context "state in one example will not leak to another" do
10 | it "make a record" do
11 | MicropostMock.create(content: "from 1) false")
12 | end
13 | end
14 | end
15 |
16 | describe "2) State Not Shared between outer examples", active_mocker: true do
17 | context "state in one example will not leak to another" do
18 | it "count records" do
19 | expect(MicropostMock.all.to_a).to eq([])
20 | expect(MicropostMock.count).to eq 0
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/test_rails_app/spec/const_stub_example_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "active_mocker/rspec_helper"
4 | require "lib/post_methods"
5 | require_mock "micropost_mock"
6 | require_mock "user_mock"
7 |
8 | describe "Another Example", active_mocker: true do
9 | context '#mock_class' do
10 | before do
11 | active_mocker.mocks.find("Micropost").create!
12 | User.create
13 | active_mocker.mocks.except(User).delete_all
14 | end
15 |
16 | after do
17 | active_mocker.mocks.delete_all
18 | end
19 |
20 | it "will create an instance of mock" do
21 | expect(Micropost.count).to eq 0
22 | expect(User.count).to eq 1
23 | end
24 |
25 | it "will create an instance of mock 2" do
26 | expect(Micropost.count).to eq 0
27 | expect(User.count).to eq 1
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/test_rails_app/spec/factories.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | FactoryGirl.define do
3 | factory :user do
4 | sequence(:name) { |n| "Person #{n}" }
5 | sequence(:email) { |n| "person_#{n}@example.com" }
6 | password "foobar"
7 | password_confirmation "foobar"
8 |
9 | factory :admin do
10 | admin true
11 | end
12 | end
13 |
14 | factory :micropost do
15 | content "Lorem ipsum"
16 | user
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/test_rails_app/spec/features_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 | require "active_mocker/rspec_helper"
3 | require_mock "user_mock"
4 |
5 | describe "ActiveMocker::Features", active_mocker: true do
6 | describe "delete_all_before_example", order: :defined do
7 | context "when enabled" do
8 | before(:all) { active_mocker.features.enable(:delete_all_before_example) }
9 | after(:all) { active_mocker.features.disable(:delete_all_before_example) }
10 | it "test1" do
11 | 10.times do
12 | User.create
13 | end
14 |
15 | expect(User.count).to eq(10)
16 | end
17 |
18 | it "test2" do
19 | User.create
20 | expect(User.count).to eq(1)
21 | end
22 | end
23 |
24 | context "when disabled" do
25 | it "test1" do
26 | 10.times do
27 | User.create
28 | end
29 |
30 | expect(User.count).to eq(10)
31 | end
32 |
33 | it "test2" do
34 | User.create
35 | expect(User.count).to eq(11)
36 | end
37 | end
38 | end
39 |
40 | describe "timestamps" do
41 | context "when enabled" do
42 | before(:all) { active_mocker.features.enable(:timestamps) }
43 | after(:all) { active_mocker.features.disable(:timestamps) }
44 |
45 | it "touches updated_at and created_at" do
46 | record = User.create
47 | expect(record.updated_at).to_not be_nil
48 | expect(record.created_at).to_not be_nil
49 | end
50 |
51 | context "when touch is called" do
52 | it "increments the updated at" do
53 | record = User.create
54 | first_time = record.updated_at
55 | record.touch
56 | expect(record.updated_at > first_time).to eq(true)
57 | end
58 | end
59 | end
60 |
61 | context "when disabled" do
62 | it "touches updated_at and created_at" do
63 | record = User.create
64 | expect(record.updated_at).to be_nil
65 | expect(record.created_at).to be_nil
66 | end
67 | end
68 | end
69 |
70 | describe "stub_active_record_exceptions", active_mocker: true do
71 | it "can load these exceptions" do
72 | ActiveRecord::RecordNotFound
73 | ActiveRecord::RecordNotUnique
74 | ActiveRecord::UnknownAttributeError
75 | end
76 | end
77 | end
78 |
--------------------------------------------------------------------------------
/test_rails_app/spec/has_no_table_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rails_helper"
3 | require_mock "has_no_table_mock"
4 |
5 | describe HasNoTableMock do
6 | it "will raise error on initialization" do
7 | expect { described_class.new }.to raise_error("HasNoTableMock is an abstract class and cannot be instantiated.")
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/test_rails_app/spec/idenity_mock_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rails_helper"
3 | require_mock "identity_mock"
4 |
5 | describe IdentityMock do
6 | it "has base class of Base" do
7 | expect(described_class.superclass).to eq ActiveMocker::Base
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/test_rails_app/spec/micropost_mock_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require "lib/post_methods"
4 | require_mock "micropost_mock"
5 | require_mock "user_mock"
6 |
7 | describe MicropostMock do
8 | describe "user=" do
9 | it "setting user will assign its foreign key" do
10 | user = UserMock.create!
11 | post = MicropostMock.create(user: user)
12 | expect(post.user_id).to eq user.id
13 | end
14 | end
15 |
16 | describe "::MAGIC_ID_NUMBER" do
17 | it "has constant from model" do
18 | expect(MicropostMock::MAGIC_ID_NUMBER).to eq 90
19 | end
20 | end
21 |
22 | context "included methods" do
23 | it "has methods" do
24 | expect(MicropostMock.new.respond_to?(:sample_method)).to eq true
25 | end
26 |
27 | it "can override attributes" do
28 | post = MicropostMock.new(content: "attribute")
29 | expect(post.content).to eq "from PostMethods"
30 | end
31 | end
32 |
33 | context "extended methods" do
34 | it "has methods" do
35 | expect(MicropostMock.respond_to?(:sample_method)).to eq true
36 | end
37 | end
38 |
39 | describe "::MAGIC_ID_STRING" do
40 | it "has constant from model" do
41 | expect(MicropostMock::MAGIC_ID_STRING).to eq "F-1"
42 | end
43 | end
44 |
45 | describe "::constants" do
46 | it "has constant from model" do
47 | expect(MicropostMock.constants).to include(:MAGIC_ID_NUMBER, :MAGIC_ID_STRING)
48 | end
49 | end
50 |
51 | describe 'has_one#create_attribute' do
52 | let(:post) { MicropostMock.new }
53 |
54 | it "can create off of has_one" do
55 | user = post.create_user
56 | expect(post.user).to eq user
57 | expect(user.persisted?).to eq true
58 | end
59 | end
60 |
61 | describe 'has_one#build_attribute' do
62 | let(:post) { MicropostMock.new }
63 |
64 | it "can create off of has_one" do
65 | user = post.build_user
66 | expect(post.user).to eq user
67 | expect(user.persisted?).to eq false
68 | end
69 | end
70 |
71 | describe "Mocking methods" do
72 | context "mocked from class before new" do
73 | before do
74 | allow_any_instance_of(MicropostMock).to receive(:display_name) do
75 | "Method Mocked at class level"
76 | end
77 | end
78 |
79 | it "when no instance level mocks is set will default to class level" do
80 | expect(MicropostMock.new.display_name).to eq "Method Mocked at class level"
81 | end
82 |
83 | it "instance mocking overrides class mocking" do
84 | post = MicropostMock.new
85 | allow(post).to receive(:display_name) do
86 | "Method Mocked at instance level"
87 | end
88 | expect(post.display_name).to eq "Method Mocked at instance level"
89 | end
90 | end
91 | end
92 |
93 | after(:each) do
94 | ActiveMocker::LoadedMocks.clear_all
95 | end
96 | end
97 |
--------------------------------------------------------------------------------
/test_rails_app/spec/rails_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | ENV["RAILS_ENV"] ||= "test"
3 | require "spec_helper"
4 | require File.expand_path("../../config/environment", __FILE__)
5 | require "rspec/rails"
6 | Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
7 |
8 | ActiveRecord::Migration.maintain_test_schema!
9 | require "spec_helper"
10 | RSpec.configure do |config|
11 | config.use_transactional_fixtures = true
12 | config.infer_base_class_for_anonymous_controllers = false
13 | end
14 |
--------------------------------------------------------------------------------
/test_rails_app/spec/rake_task_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rails_helper"
3 | require "rake"
4 |
5 | describe "rake active_mocker:build" do
6 | before { SampleApp::Application.load_tasks }
7 | it "builds the mocks from the model dir" do
8 | expect(File.exist? mock_path).to eq true
9 | expect(File.exist? File.join(mock_path, "user_mock.rb")).to eq true
10 | expect(File.exist? File.join(mock_path, "micropost_mock.rb")).to eq true
11 | expect(File.exist? File.join(mock_path, "relationship_mock.rb")).to eq true
12 | expect(File.exist? File.join(mock_path, "api/customer_mock.rb")).to eq true
13 | expect(File.exist? File.join(mock_path, "nacis_mock.rb")).to eq false
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/test_rails_app/spec/relation_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "spec_helper"
3 | require_mock "user_mock"
4 | require_relative "../../spec/lib/active_mocker/mock/queriable_shared_example"
5 |
6 | describe UserMock do
7 | describe "ActiveMocker::MockRelation" do
8 | it_behaves_like "Queriable", -> (*args) { ActiveMocker::MockRelation.new(UserMock, args.flatten) }
9 |
10 | subject { ActiveMocker::MockRelation.new(UserMock, collection) }
11 | let(:collection) { [UserMock.new, UserMock.new] }
12 |
13 | it "call a private method on class" do
14 | expect(UserMock).to receive(:__new_relation__).with(collection)
15 | subject
16 | end
17 |
18 | it "has the correct count" do
19 | expect(subject.count).to eq 2
20 | end
21 |
22 | it "has scoped methods" do
23 | expect(subject.respond_to?(:find_by_name)).to eq true
24 | expect(subject.respond_to?(:by_name)).to eq true
25 | expect(subject.respond_to?(:no_arg_scope)).to eq true
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/test_rails_app/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rspec"
3 | ENV["RAILS_VERSION"] ||= "4.2"
4 | $LOAD_PATH.unshift File.expand_path("../../", __FILE__)
5 | APP_ROOT = File.expand_path("../../", __FILE__) unless defined? APP_ROOT
6 |
7 | RSpec.configure do |config|
8 | config.order = "random"
9 |
10 | config.expect_with :rspec do |c|
11 | c.syntax = :expect
12 | end
13 |
14 | config.mock_with :rspec do |mocks|
15 | mocks.verify_doubled_constant_names = true
16 | mocks.verify_partial_doubles = true
17 | end
18 | end
19 |
20 | def require_mock(name)
21 | require "#{mock_path}/#{name}"
22 | end
23 |
24 | def mock_path
25 | rails_version = if ENV["RAILS_VERSION"]
26 | ENV["RAILS_VERSION"]
27 | elsif defined? Rails
28 | "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
29 | else
30 | "5.2"
31 | end
32 | File.join(APP_ROOT, "spec/mocks/#{rails_version}")
33 | end
34 |
--------------------------------------------------------------------------------
/test_rails_app/spec/user_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 | require "rails_helper"
3 | require_relative "active_record_compatible_api"
4 |
5 | describe User do
6 | it_behaves_like "ActiveRecord", Micropost, Account
7 | end
8 |
--------------------------------------------------------------------------------
/test_rails_app/test_rails_4_app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------