rails_readonly_injector 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0c17f3a71ff8c4089bfc183fd0b661a50f0b3d60
4
+ data.tar.gz: eda68bb545c0cfe97dfc2c15227cd271a15f41ae
5
+ SHA512:
6
+ metadata.gz: 55e15401c1aef32c37f4e7ad5b921a2ef7fc81554e421f948b598b778cc647f588cf76d901854bde6bdcde209cca70f76b0d8b8baed9c9c109d551193d14f58a
7
+ data.tar.gz: fd618f6e50007598655d667e9dcda0412ae5e9582c9b0e0a94437171f0d98c5106381f36c19811c97c34ae4bc0ca224cc420fc21fd0399f121bd23394550e01d
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ gemfiles/*.gemfile.lock
10
+ .byebug_history
data/.travis.yml ADDED
@@ -0,0 +1,56 @@
1
+ env:
2
+ global:
3
+ - CC_TEST_REPORTER_ID=42f23507800f7e37490680c9eb163455d5214d7f8c7140d0757e4858fa809497
4
+ language: ruby
5
+ rvm:
6
+ - 2.1.3
7
+ - 2.2.7
8
+ - 2.3.6
9
+ - 2.4.1
10
+ - ruby-head
11
+
12
+ branches:
13
+ only:
14
+ - master
15
+
16
+
17
+ before_script:
18
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
19
+ - chmod +x ./cc-test-reporter
20
+ - ./cc-test-reporter before-build
21
+
22
+ after_script:
23
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
24
+
25
+ gemfile:
26
+ - gemfiles/rails_3.gemfile
27
+ - gemfiles/rails_4_0.gemfile
28
+ - gemfiles/rails_4_1.gemfile
29
+ - gemfiles/rails_4_2.gemfile
30
+ - gemfiles/rails_5_0.gemfile
31
+
32
+ matrix:
33
+ fast_finish: true
34
+ exclude:
35
+ - rvm: 2.1.3
36
+ gemfile: gemfiles/rails_4_1.gemfile
37
+ - rvm: 2.1.3
38
+ gemfile: gemfiles/rails_4_2.gemfile
39
+ - rvm: 2.1.3
40
+ gemfile: gemfiles/rails_5_0.gemfile
41
+ - rvm: 2.2.7
42
+ gemfile: gemfiles/rails_3.gemfile
43
+ - rvm: 2.3.6
44
+ gemfile: gemfiles/rails_3.gemfile
45
+ - rvm: 2.4.1
46
+ gemfile: gemfiles/rails_3.gemfile
47
+ - rvm: 2.4.1
48
+ gemfile: gemfiles/rails_4_0.gemfile
49
+ - rvm: 2.4.1
50
+ gemfile: gemfiles/rails_4_1.gemfile
51
+ - rvm: jruby
52
+ gemfile: gemfiles/rails_3.gemfile
53
+ - rvm: rbx-3
54
+ gemfile: gemfiles/rails_3.gemfile
55
+ allow_failures:
56
+ - rvm: ruby-head
data/Appraisals ADDED
@@ -0,0 +1,38 @@
1
+ appraise 'rails_3' do
2
+ gem 'rails', '~> 3'
3
+ gem 'cucumber-rails', '~> 1.4.5'
4
+ gem 'rspec-rails', '~> 3.7.2', group: :test
5
+ gem 'database_cleaner', '~> 1.0.1'
6
+ gem 'sass', '= 3.4.21'
7
+ end
8
+
9
+ appraise 'rails_4_0' do
10
+ gem 'rails', '~> 4.0.0'
11
+ gem 'cucumber-rails', '~> 1.5.0', group: :test, require: false
12
+ gem 'rspec-rails', '~> 3.7.2', group: :test
13
+ gem 'database_cleaner', '~> 1.0.1'
14
+ gem 'sqlite3', '~> 1.3.13'
15
+ end
16
+
17
+ appraise 'rails_4_1' do
18
+ gem 'rails', '~> 4.1.0'
19
+ gem 'cucumber-rails', '~> 1.5.0', group: :test, require: false
20
+ gem 'rspec-rails', '~> 3.7.2', group: :test
21
+ gem 'database_cleaner', '~> 1.0.1'
22
+ gem 'sqlite3', '~> 1.3.13'
23
+ end
24
+
25
+ appraise 'rails_4_2' do
26
+ gem 'rails', '~> 4.2.0'
27
+ gem 'cucumber-rails', '~> 1.5.0', group: :test, require: false
28
+ gem 'rspec-rails', '~> 3.7.2', group: :test
29
+ gem 'database_cleaner', '~> 1.0.1'
30
+ gem 'sqlite3', '~> 1.3.13'
31
+ end
32
+
33
+ appraise 'rails_5_0' do
34
+ gem 'rails', '~> 5.0.0'
35
+ gem 'cucumber-rails', '~> 1.5.0', group: :test, require: false
36
+ gem 'rspec-rails', '~> 3.7.2', group: :test
37
+ gem 'database_cleaner', '~> 1.0.1'
38
+ end
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at andrew.walter@burnet.edu.au. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in rails_readonly_injector.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rails_readonly_injector (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ appraisal (2.2.0)
10
+ bundler
11
+ rake
12
+ thor (>= 0.14.0)
13
+ rake (10.5.0)
14
+ thor (0.20.0)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ appraisal (~> 2.2.0)
21
+ bundler (~> 1.16)
22
+ rails_readonly_injector!
23
+ rake (~> 10.0)
24
+
25
+ BUNDLED WITH
26
+ 1.16.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Andrew Walter
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.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Rails ReadOnly Injector
2
+ [![Build Status](https://travis-ci.org/xtrasimplicity/rails_readonly_injector.svg?branch=master)](https://travis-ci.org/xtrasimplicity/rails_readonly_injector)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/427c153efd48ae03f688/maintainability)](https://codeclimate.com/github/xtrasimplicity/rails_readonly_injector/maintainability)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/427c153efd48ae03f688/test_coverage)](https://codeclimate.com/github/xtrasimplicity/rails_readonly_injector/test_coverage)
5
+
6
+ Easily switch a Rails site into 'read-only' mode, and back again, without restarting the server.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'rails_readonly_injector'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install rails_readonly_injector
23
+
24
+ ## Usage
25
+
26
+ In order to switch a complete site into read-only mode, you will first need to set the action to occur when an attempt to commit changes to the database is made, from within a controller. Usually, this won't need to change once the application has booted, so I recommend defining it within an initializer, as follows:
27
+
28
+ ```
29
+ # config/initializers/rails_readonly_injector.rb
30
+ RailsReadonlyInjector.config do |config|
31
+ config.controller_rescue_action = lambda do |context|
32
+ # Define actions to be performed if changes to a read-only model are attempted to be committed to the database.
33
+ # This lambda expression is evaluated from within the instance of the referring controller.
34
+
35
+ # You may want to set a redirect, or flash an error message, or something, here.
36
+ # e.g.
37
+ # flash[:danger] = 'The site is currently in read-only mode'
38
+ # redirect_to readonly_page_url
39
+ end
40
+ end
41
+ ```
42
+
43
+ When you want to switch a site into read-only mode, you can then simply set `RailsReadonlyInjector.read_only` to true and then call `RailsReadonlyInjector.reload!` to (re-)load the configuration. Alternatively, you can also set `read_only` from within the configuration block inside the initializer.
44
+
45
+ If you want to reset the configuration to the defaults, you can simply call `RailsReadonlyInjector.reset_configuration!` from anywhere in your application.
46
+
47
+ ## Development
48
+
49
+ After checking out the repo, run `bundle install` to install the dependencies.
50
+
51
+ RSpec specs and Cucumber features are stored in `rspec_specs` and `cucumber_features`, respectively. When `bundle exec rake` is run against an appraisal, the contents of these folders are copied to the necessary folders under the temporary rails application that is generated (by `bundle exec rake`) into `tmp/rails_app`.
52
+
53
+ To run tests for a specific version of Rails, simply run `bundle exec appraisal {APPRAISAL} bundle exec rake`, where `{APPRAISAL}` is one of the appraisals found under `Appraisals`.
54
+
55
+ ## Contributing
56
+
57
+ Bug reports and pull requests are welcome on GitHub at https://github.com/xtrasimplicity/rails_readonly_injector. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
58
+
59
+ ## License
60
+
61
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
62
+
63
+ ## Code of Conduct
64
+
65
+ Everyone interacting in the RailsReadonlyInjector project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/xtrasimplicity/rails_readonly_injector/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ development_tasks_path = File.expand_path('../development_tasks', __FILE__)
4
+
5
+ Dir[File.join(development_tasks_path, '*.rake')].each { |rb| load rb }
6
+
7
+ task :default => ['dev:deploy_test_app', 'dev:run_tests']
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rails_readonly_injector"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,29 @@
1
+ Feature: Configuration
2
+ Scenario: When changing from read-only back to writeable
3
+ Given I execute:
4
+ """
5
+ RailsReadonlyInjector.config do |config|
6
+ config.read_only = true
7
+ end
8
+
9
+ RailsReadonlyInjector.reload!
10
+ """
11
+ When I execute:
12
+ """
13
+ RailsReadonlyInjector.config do |config|
14
+ config.read_only = false
15
+ end
16
+
17
+ RailsReadonlyInjector.reload!
18
+ """
19
+ Then I should be able to create a user without any errors
20
+
21
+
22
+ #Feature: Configuration
23
+ # Scenario: When `allowed_models` is set
24
+ # Given I configure RailsReadonlyInjector with:
25
+ # """
26
+ # RailsReadonlyInjector.config do |config|
27
+ # config.allowed_models = ['User']
28
+ # """
29
+ # When
File without changes
@@ -0,0 +1,7 @@
1
+ Given("I execute:") do |code|
2
+ eval code
3
+ end
4
+
5
+ Then("The page should contain {string}") do |string|
6
+ expect(page).to have_content(string)
7
+ end
@@ -0,0 +1,70 @@
1
+ Given("There is a user that has been persisted to the database") do
2
+ RailsReadonlyInjector.config.read_only = false
3
+ RailsReadonlyInjector.reload!
4
+
5
+ @user = User.create(name: 'Bob')
6
+
7
+ expect(@user.persisted?).to eq(true)
8
+ end
9
+
10
+ Given("There is a user that has not been persisted to the database") do
11
+ User.destroy_all
12
+
13
+ @user = User.new(name: 'Bob')
14
+ end
15
+
16
+ When("I update the user") do
17
+ begin
18
+ @user.update_attributes(name: 'Fred')
19
+ rescue ActiveRecord::ReadOnlyRecord
20
+ end
21
+ end
22
+
23
+ When("I save the user") do
24
+ begin
25
+ @user.save
26
+ rescue ActiveRecord::ReadOnlyRecord
27
+ end
28
+ end
29
+
30
+ Then("the user should not be updated") do
31
+ @user.reload
32
+
33
+ expect(@user.name).to eq('Bob')
34
+ end
35
+
36
+ Then("the user should be updated") do
37
+ @user.reload
38
+
39
+ expect(@user.name).to eq('Fred')
40
+ end
41
+
42
+ Then("the user should be saved") do
43
+ @user.reload
44
+
45
+ expect(@user.persisted?).to eq(true)
46
+ end
47
+
48
+ Then("the user should not be saved") do
49
+ expect(User.all.length).to eq(0)
50
+ end
51
+
52
+ When("I'm using a web browser and attempt to update the user") do
53
+ visit "/users/#{@user.id}/edit"
54
+ fill_in 'user[name]', with: 'Fred'
55
+ click_on 'Update User'
56
+ end
57
+
58
+ When("I'm using a web browser and attempt to create a user") do
59
+ visit "/users/new"
60
+ fill_in 'user[name]', with: 'Fred'
61
+ click_on 'Create User'
62
+ end
63
+
64
+ Then("the user should be created") do
65
+ expect(User.all.length).to eq(1)
66
+ end
67
+
68
+ Then("I should be able to create a user without any errors") do
69
+ expect { User.create(name: 'Bob') }.not_to raise_error
70
+ end
File without changes
@@ -0,0 +1,20 @@
1
+ Feature: Users Controller - When not in read only mode
2
+ Background:
3
+ Given I execute:
4
+ """
5
+ RailsReadonlyInjector.config do |config|
6
+ config.read_only = false
7
+ end
8
+
9
+ RailsReadonlyInjector.reload!
10
+ """
11
+
12
+ Scenario: A user has previously been persisted to the database, and an attempt to update it has been made
13
+ Given There is a user that has been persisted to the database
14
+ When I'm using a web browser and attempt to update the user
15
+ Then the user should be updated
16
+
17
+
18
+ Scenario: A new user is created (and was not previously persisted to the database), and an attempt to save it has been made
19
+ Given I'm using a web browser and attempt to create a user
20
+ Then the user should be created
@@ -0,0 +1,33 @@
1
+ Feature: User Controller - When in read only mode
2
+ Scenario: A user has previously been persisted to the database, and an attempt to update it has been made
3
+ Given There is a user that has been persisted to the database
4
+ And I execute:
5
+ """
6
+ RailsReadonlyInjector.config do |config|
7
+ config.read_only = true
8
+ config.controller_rescue_action = lambda do |context|
9
+ render :text => 'The site is currently in read-only mode'
10
+ end
11
+ end
12
+
13
+ RailsReadonlyInjector.reload!
14
+ """
15
+ When I'm using a web browser and attempt to update the user
16
+ Then The page should contain 'The site is currently in read-only mode'
17
+ And the user should not be updated
18
+
19
+
20
+ Scenario: A new user is created (and was not previously persisted to the database), and an attempt to save it has been made
21
+ Given I execute:
22
+ """
23
+ RailsReadonlyInjector.config do |config|
24
+ config.read_only = true
25
+ config.controller_rescue_action = lambda do |context|
26
+ render :text => 'The site is currently in read-only mode'
27
+ end
28
+ end
29
+
30
+ RailsReadonlyInjector.reload!
31
+ """
32
+ When I'm using a web browser and attempt to create a user
33
+ Then the user should not be saved
@@ -0,0 +1,20 @@
1
+ Feature: User model - When not in read-only mode
2
+ Background:
3
+ Given I execute:
4
+ """
5
+ RailsReadonlyInjector.config do |config|
6
+ config.read_only = false
7
+ end
8
+
9
+ RailsReadonlyInjector.reload!
10
+ """
11
+
12
+ Scenario: A user has previously been persisted to the database, and an attempt to update it has been made
13
+ Given There is a user that has been persisted to the database
14
+ When I update the user
15
+ Then the user should be updated
16
+
17
+ Scenario: A new user is created (and was not previously persisted to the database), and an attempt to save it has been made
18
+ Given There is a user that has not been persisted to the database
19
+ When I save the user
20
+ Then the user should be saved
@@ -0,0 +1,26 @@
1
+ Feature: User model - When in read-only mode
2
+ Scenario: A user has previously been persisted to the database, and an attempt to update it has been made
3
+ Given There is a user that has been persisted to the database
4
+ And I execute:
5
+ """
6
+ RailsReadonlyInjector.config do |config|
7
+ config.read_only = true
8
+ end
9
+
10
+ RailsReadonlyInjector.reload!
11
+ """
12
+ When I update the user
13
+ Then the user should not be updated
14
+
15
+ Scenario: A new user is created (and was not previously persisted to the database), and an attempt to save it has been made
16
+ Given There is a user that has not been persisted to the database
17
+ And I execute:
18
+ """
19
+ RailsReadonlyInjector.config do |config|
20
+ config.read_only = true
21
+ end
22
+
23
+ RailsReadonlyInjector.reload!
24
+ """
25
+ When I save the user
26
+ Then the user should not be saved
@@ -0,0 +1,127 @@
1
+ require 'fileutils'
2
+
3
+ namespace :dev do
4
+ RAILS_APP_PATH = File.expand_path('../../tmp/rails_app', __FILE__).freeze
5
+ GEM_ROOT_PATH = File.expand_path('../..', __FILE__).freeze
6
+
7
+ desc "Deploys a test rails application into the #{RAILS_APP_PATH} directory."
8
+ task :deploy_test_app do
9
+ switch_to_gems_root_path
10
+
11
+ # Remove the app, if it exists already
12
+ system("rm -rf #{RAILS_APP_PATH}")
13
+
14
+ puts "Creating a new rails application..."
15
+ FileUtils.mkdir_p RAILS_APP_PATH
16
+ system("bundle exec rails new #{RAILS_APP_PATH}")
17
+
18
+ switch_to_rails_app_path
19
+
20
+ # Read gems defined in this Appraisal,
21
+ # so we can write them to the Gemfile rails generated.
22
+ # i.e. To 'override'/force a specific version.
23
+ gems_defined_in_appraisal = parse_gemfile(ENV['BUNDLE_GEMFILE'])
24
+ gems_defined_in_gemfile = parse_gemfile('Gemfile').collect { |l| l.gem_name }
25
+
26
+ gems_to_override = gems_defined_in_appraisal.reject { |l| gems_defined_in_gemfile.include? l.gem_name }.collect { |gem| gem.original_line_in_gemfile }
27
+
28
+ # Add required gems to the gemfile
29
+ append_to_file 'Gemfile', gems_to_override.join("\n")
30
+ append_to_file 'Gemfile', %{gem 'simplecov', require: false, group: :test\n}
31
+ append_to_file 'Gemfile', %{gem "rails_readonly_injector", path: "#{GEM_ROOT_PATH}"\n}
32
+
33
+ # Make sure we don't use the gemfile from Appraisal
34
+ ENV.delete('BUNDLE_GEMFILE')
35
+ ENV.delete('BUNDLE_BIN_PATH')
36
+ ENV.delete('RUBYOPT')
37
+
38
+ # Install gems
39
+ system("bundle install")
40
+
41
+ system("bundle exec rails generate cucumber:install")
42
+ system("bundle exec rails generate rspec:install")
43
+
44
+ # RSpec: Include all files in support/
45
+ append_to_file 'spec/spec_helper.rb', "Dir.glob('support/**/*.rb').each { |rb| require rb }"
46
+
47
+ # Set up SimpleCov
48
+ append_to_beginning_of_file 'spec/spec_helper.rb', %{
49
+ require 'simplecov'
50
+ require 'rails_readonly_injector'
51
+ }
52
+ append_to_beginning_of_file 'features/support/env.rb', "require 'simplecov'"
53
+
54
+ write_file_with_content '.simplecov', %{
55
+ SimpleCov.start do
56
+ coverage_dir '#{GEM_ROOT_PATH}/coverage'
57
+ end
58
+ }
59
+
60
+ # Prepare database migrations, etc
61
+ system("bundle exec rails generate scaffold User name:string")
62
+
63
+ system("RAILS_ENV=test bundle exec rake db:migrate")
64
+ end
65
+
66
+ desc "Synchronises tests from `cucumber_features` and `rspec_specs` into the rails application in #{RAILS_APP_PATH}, and runs the tests against the application."
67
+ task :run_tests do
68
+ switch_to_rails_app_path
69
+
70
+ # Set up the Cucumber and RSpec tests
71
+ FileUtils.cp_r File.join(GEM_ROOT_PATH, 'cucumber_features', '.'), 'features'
72
+ FileUtils.cp_r File.join(GEM_ROOT_PATH, 'rspec_specs', '.'), 'spec'
73
+
74
+ system('bundle exec cucumber')
75
+ system('bundle exec rspec')
76
+ end
77
+
78
+ def parse_gemfile(file_path)
79
+ gems = []
80
+
81
+ File.open(file_path).readlines.each do |line|
82
+ matches = line.match /^\s*gem\s+['|"]/
83
+
84
+ next if matches.nil?
85
+
86
+ parts = line.split(',')
87
+
88
+ gem_name = parts.first.gsub(/\s*gem\s*|["|']|\n/, '')
89
+
90
+ gems << OpenStruct.new({ gem_name: gem_name, original_line_in_gemfile: line })
91
+ end
92
+
93
+ gems
94
+ end
95
+
96
+ def switch_to_gems_root_path
97
+ FileUtils.cd GEM_ROOT_PATH
98
+ end
99
+
100
+ def switch_to_rails_app_path
101
+ FileUtils.cd RAILS_APP_PATH
102
+ end
103
+
104
+ def append_to_file(path_to_file, content)
105
+ raise 'The specified path is not a file!' unless File.file? path_to_file
106
+
107
+ File.open(path_to_file, 'a') do |f|
108
+ f.write content
109
+ end
110
+ end
111
+
112
+ def append_to_beginning_of_file(path_to_file, content)
113
+ raise 'The specified path is not a file!' unless File.file? path_to_file
114
+
115
+ existing_content_as_array = File.open(path_to_file, 'r').readlines
116
+
117
+ new_content_arr = [content] + existing_content_as_array
118
+
119
+ write_file_with_content path_to_file, new_content_arr.join("\n")
120
+ end
121
+
122
+ def write_file_with_content(path_to_file, content)
123
+ File.open(path_to_file, 'w') do |f|
124
+ f.write content
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 3"
6
+ gem "cucumber-rails", "~> 1.4.5"
7
+ gem "rspec-rails", "~> 3.7.2", group: :test
8
+ gem "database_cleaner", "~> 1.0.1"
9
+ gem "sass", "= 3.4.21"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.0.0"
6
+ gem "cucumber-rails", "~> 1.5.0", group: :test, require: false
7
+ gem "rspec-rails", "~> 3.7.2", group: :test
8
+ gem "database_cleaner", "~> 1.0.1"
9
+ gem "sqlite3", "~> 1.3.13"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.1.0"
6
+ gem "cucumber-rails", "~> 1.5.0", group: :test, require: false
7
+ gem "rspec-rails", "~> 3.7.2", group: :test
8
+ gem "database_cleaner", "~> 1.0.1"
9
+ gem "sqlite3", "~> 1.3.13"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.2.0"
6
+ gem "cucumber-rails", "~> 1.5.0", group: :test, require: false
7
+ gem "rspec-rails", "~> 3.7.2", group: :test
8
+ gem "database_cleaner", "~> 1.0.1"
9
+ gem "sqlite3", "~> 1.3.13"
10
+
11
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 5.0.0"
6
+ gem "cucumber-rails", "~> 1.5.0", group: :test, require: false
7
+ gem "rspec-rails", "~> 3.7.2", group: :test
8
+ gem "database_cleaner", "~> 1.0.1"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,57 @@
1
+ require "rails_readonly_injector/version"
2
+ require "rails_readonly_injector/configuration"
3
+
4
+ module RailsReadonlyInjector
5
+ def self.reload!
6
+ descendants = ActiveRecord::Base.descendants
7
+
8
+ if descendants.empty?
9
+ Rails.application.eager_load!
10
+ descendants = ActiveRecord::Base.descendants
11
+ end
12
+
13
+ descendants.each do |descendant_class|
14
+ if self.config.read_only
15
+ override_readonly_method(descendant_class)
16
+ else
17
+ restore_readonly_method(descendant_class)
18
+ end
19
+ end
20
+
21
+ inject_error_handler_into_actioncontroller_base
22
+ end
23
+
24
+ private
25
+
26
+ ALIASED_METHOD_NAME = :old_readonly?
27
+
28
+ def self.override_readonly_method(klass)
29
+ klass.class_eval do
30
+ alias_method ALIASED_METHOD_NAME, :readonly?
31
+
32
+ def readonly?
33
+ true
34
+ end
35
+ end
36
+ end
37
+
38
+ def self.restore_readonly_method(klass)
39
+ klass.class_eval do
40
+ def readonly?
41
+ super
42
+ end
43
+ end
44
+ end
45
+
46
+ def self.inject_error_handler_into_actioncontroller_base
47
+ ActionController::Base.class_eval do |klass|
48
+ rescue_from ActiveRecord::ReadOnlyRecord, with: :rescue_from_readonly_failure
49
+
50
+ protected
51
+
52
+ def rescue_from_readonly_failure
53
+ instance_eval &RailsReadonlyInjector.config.controller_rescue_action
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+ module RailsReadonlyInjector
2
+ class Configuration
3
+ attr_writer :read_only
4
+
5
+ def read_only
6
+ @read_only || false
7
+ end
8
+
9
+ def controller_rescue_action=(action)
10
+ raise 'A lambda or proc must be specified' unless action.respond_to? :call
11
+
12
+ @controller_rescue_action = action
13
+ end
14
+
15
+ def controller_rescue_action
16
+ @controller_rescue_action || Proc.new {}
17
+ end
18
+ end
19
+ private_constant :Configuration
20
+
21
+ # Sets the specified configuration options, if a block is provided
22
+ # @return [Configuration] the current configuration object.
23
+ def self.config
24
+ yield self.configuration if block_given?
25
+
26
+ self.configuration
27
+ end
28
+
29
+ def self.reset_configuration!
30
+ @config = Configuration.new
31
+
32
+ self.reload!
33
+ end
34
+
35
+ private
36
+
37
+ def self.configuration
38
+ @config ||= Configuration.new
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module RailsReadonlyInjector
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,30 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "rails_readonly_injector/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rails_readonly_injector"
8
+ spec.version = RailsReadonlyInjector::VERSION
9
+ spec.authors = ["Andrew Walter"]
10
+ spec.email = ["andrew.walter@burnet.edu.au"]
11
+
12
+ spec.summary = "Globally toggle 'read-only' mode in a Rails application, on-demand, without having to restart the server."
13
+ spec.homepage = "https://www.github.com"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.required_ruby_version = ">= 2.1.3"
24
+
25
+ spec.add_runtime_dependency "rails", ">= 3.0"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.16"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency 'appraisal', '~> 2.2.0'
30
+ end
File without changes
@@ -0,0 +1,31 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe RailsReadonlyInjector.config do
4
+ describe '#controller_rescue_action=' do
5
+ context 'when given a lambda expression' do
6
+ let(:lambda_expression) { lambda { "This is a test lambda!" } }
7
+
8
+ before { RailsReadonlyInjector.config.controller_rescue_action = lambda_expression }
9
+
10
+ subject { RailsReadonlyInjector.config.controller_rescue_action }
11
+
12
+ it { is_expected.to eq(lambda_expression) }
13
+ end
14
+
15
+ context 'when given a Proc' do
16
+ let(:proc) { Proc.new { "This is a test Proc!" } }
17
+
18
+ before { RailsReadonlyInjector.config.controller_rescue_action = proc }
19
+
20
+ subject { RailsReadonlyInjector.config.controller_rescue_action }
21
+
22
+ it { is_expected.to eq(proc) }
23
+ end
24
+
25
+ context 'when an invalid value is assigned' do
26
+ it 'raises an error message' do
27
+ expect { RailsReadonlyInjector.config.controller_rescue_action = nil }.to raise_error 'A lambda or proc must be specified'
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,59 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe RailsReadonlyInjector do
4
+ describe '.reset_configuration!' do
5
+ before do
6
+ RailsReadonlyInjector.config do |config|
7
+ config.read_only = true
8
+ end
9
+
10
+ RailsReadonlyInjector.reset_configuration!
11
+ end
12
+
13
+ subject { RailsReadonlyInjector.config }
14
+
15
+ it 'sets `read_only` to false' do
16
+ expect(RailsReadonlyInjector.config.read_only).to eq(false)
17
+ end
18
+ end
19
+
20
+ describe '.override_readonly_method' do
21
+ let(:klass) { User }
22
+
23
+ before do
24
+ RailsReadonlyInjector.config do |config|
25
+ config.read_only = true
26
+ end
27
+
28
+ RailsReadonlyInjector.reload!
29
+
30
+ RailsReadonlyInjector.send(:override_readonly_method, klass)
31
+ end
32
+
33
+ describe 'An ActiveRecord object\'s #readonly? method' do
34
+ subject { klass.new.readonly? }
35
+
36
+ it { is_expected.to eq(true) }
37
+ end
38
+ end
39
+
40
+ describe '.restore_readonly_method' do
41
+ let(:klass) { User }
42
+
43
+ before do
44
+ RailsReadonlyInjector.config do |config|
45
+ config.read_only = false
46
+ end
47
+
48
+ RailsReadonlyInjector.reload!
49
+
50
+ RailsReadonlyInjector.send(:restore_readonly_method, klass)
51
+ end
52
+
53
+ describe('An ActiveRecord object\'s #readonly? method') do
54
+ subject { klass.new.readonly? }
55
+
56
+ it { is_expected.to eq(false) }
57
+ end
58
+ end
59
+ end
File without changes
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_readonly_injector
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Walter
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-03-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: appraisal
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.2.0
69
+ description:
70
+ email:
71
+ - andrew.walter@burnet.edu.au
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Appraisals
79
+ - CODE_OF_CONDUCT.md
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - bin/console
86
+ - bin/setup
87
+ - cucumber_features/configuration.feature
88
+ - cucumber_features/step_definitions/.gitkeep
89
+ - cucumber_features/step_definitions/generic_steps.rb
90
+ - cucumber_features/step_definitions/user_steps.rb
91
+ - cucumber_features/support/.gitkeep
92
+ - cucumber_features/user_controller.feature
93
+ - cucumber_features/user_controller_readonly.feature
94
+ - cucumber_features/user_model.feature
95
+ - cucumber_features/user_model_readonly.feature
96
+ - development_tasks/tests.rake
97
+ - gemfiles/.bundle/config
98
+ - gemfiles/rails_3.gemfile
99
+ - gemfiles/rails_4_0.gemfile
100
+ - gemfiles/rails_4_1.gemfile
101
+ - gemfiles/rails_4_2.gemfile
102
+ - gemfiles/rails_5_0.gemfile
103
+ - lib/rails_readonly_injector.rb
104
+ - lib/rails_readonly_injector/configuration.rb
105
+ - lib/rails_readonly_injector/version.rb
106
+ - rails_readonly_injector.gemspec
107
+ - rspec_specs/.gitkeep
108
+ - rspec_specs/readonly_site_toggle/configuration_spec.rb
109
+ - rspec_specs/readonly_site_toggle_spec.rb
110
+ - rspec_specs/support/.gitkeep
111
+ homepage: https://www.github.com
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: 2.1.3
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.6.13
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Globally toggle 'read-only' mode in a Rails application, on-demand, without
135
+ having to restart the server.
136
+ test_files: []