good_migrations 0.0.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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +9 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +59 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +7 -0
  10. data/example/.gitignore +10 -0
  11. data/example/Gemfile +9 -0
  12. data/example/README +256 -0
  13. data/example/Rakefile +7 -0
  14. data/example/app/controllers/application_controller.rb +3 -0
  15. data/example/app/helpers/application_helper.rb +2 -0
  16. data/example/app/models/pant.rb +3 -0
  17. data/example/app/views/layouts/application.html.erb +14 -0
  18. data/example/config.ru +4 -0
  19. data/example/config/application.rb +42 -0
  20. data/example/config/boot.rb +13 -0
  21. data/example/config/database.yml +22 -0
  22. data/example/config/environment.rb +5 -0
  23. data/example/config/environments/development.rb +26 -0
  24. data/example/config/environments/production.rb +49 -0
  25. data/example/config/environments/test.rb +35 -0
  26. data/example/config/initializers/backtrace_silencers.rb +7 -0
  27. data/example/config/initializers/inflections.rb +10 -0
  28. data/example/config/initializers/mime_types.rb +5 -0
  29. data/example/config/initializers/secret_token.rb +7 -0
  30. data/example/config/initializers/session_store.rb +8 -0
  31. data/example/config/locales/en.yml +5 -0
  32. data/example/config/routes.rb +58 -0
  33. data/example/db/migrate/20160202162849_create_pants.rb +8 -0
  34. data/example/db/migrate/20160202163803_change_pants.rb +9 -0
  35. data/example/db/migrate/20160202182520_change_pants_dangerously.rb +10 -0
  36. data/example/db/seeds.rb +7 -0
  37. data/example/doc/README_FOR_APP +2 -0
  38. data/example/lib/tasks/.gitkeep +0 -0
  39. data/example/public/404.html +26 -0
  40. data/example/public/422.html +26 -0
  41. data/example/public/500.html +26 -0
  42. data/example/public/favicon.ico +0 -0
  43. data/example/public/images/rails.png +0 -0
  44. data/example/public/index.html +239 -0
  45. data/example/public/javascripts/application.js +2 -0
  46. data/example/public/javascripts/controls.js +965 -0
  47. data/example/public/javascripts/dragdrop.js +974 -0
  48. data/example/public/javascripts/effects.js +1123 -0
  49. data/example/public/javascripts/prototype.js +6001 -0
  50. data/example/public/javascripts/rails.js +175 -0
  51. data/example/public/robots.txt +5 -0
  52. data/example/public/stylesheets/.gitkeep +0 -0
  53. data/example/script/rails +6 -0
  54. data/example/test/performance/browsing_test.rb +9 -0
  55. data/example/test/test_helper.rb +13 -0
  56. data/example/vendor/plugins/.gitkeep +0 -0
  57. data/good_migrations.gemspec +27 -0
  58. data/lib/good_migrations.rb +3 -0
  59. data/lib/good_migrations/load_error.rb +4 -0
  60. data/lib/good_migrations/railtie.rb +11 -0
  61. data/lib/good_migrations/version.rb +3 -0
  62. data/tasks/good_migrations.rake +63 -0
  63. metadata +177 -0
@@ -0,0 +1,175 @@
1
+ (function() {
2
+ // Technique from Juriy Zaytsev
3
+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
4
+ function isEventSupported(eventName) {
5
+ var el = document.createElement('div');
6
+ eventName = 'on' + eventName;
7
+ var isSupported = (eventName in el);
8
+ if (!isSupported) {
9
+ el.setAttribute(eventName, 'return;');
10
+ isSupported = typeof el[eventName] == 'function';
11
+ }
12
+ el = null;
13
+ return isSupported;
14
+ }
15
+
16
+ function isForm(element) {
17
+ return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
18
+ }
19
+
20
+ function isInput(element) {
21
+ if (Object.isElement(element)) {
22
+ var name = element.nodeName.toUpperCase()
23
+ return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
24
+ }
25
+ else return false
26
+ }
27
+
28
+ var submitBubbles = isEventSupported('submit'),
29
+ changeBubbles = isEventSupported('change')
30
+
31
+ if (!submitBubbles || !changeBubbles) {
32
+ // augment the Event.Handler class to observe custom events when needed
33
+ Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
34
+ function(init, element, eventName, selector, callback) {
35
+ init(element, eventName, selector, callback)
36
+ // is the handler being attached to an element that doesn't support this event?
37
+ if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
38
+ (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
39
+ // "submit" => "emulated:submit"
40
+ this.eventName = 'emulated:' + this.eventName
41
+ }
42
+ }
43
+ )
44
+ }
45
+
46
+ if (!submitBubbles) {
47
+ // discover forms on the page by observing focus events which always bubble
48
+ document.on('focusin', 'form', function(focusEvent, form) {
49
+ // special handler for the real "submit" event (one-time operation)
50
+ if (!form.retrieve('emulated:submit')) {
51
+ form.on('submit', function(submitEvent) {
52
+ var emulated = form.fire('emulated:submit', submitEvent, true)
53
+ // if custom event received preventDefault, cancel the real one too
54
+ if (emulated.returnValue === false) submitEvent.preventDefault()
55
+ })
56
+ form.store('emulated:submit', true)
57
+ }
58
+ })
59
+ }
60
+
61
+ if (!changeBubbles) {
62
+ // discover form inputs on the page
63
+ document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
64
+ // special handler for real "change" events
65
+ if (!input.retrieve('emulated:change')) {
66
+ input.on('change', function(changeEvent) {
67
+ input.fire('emulated:change', changeEvent, true)
68
+ })
69
+ input.store('emulated:change', true)
70
+ }
71
+ })
72
+ }
73
+
74
+ function handleRemote(element) {
75
+ var method, url, params;
76
+
77
+ var event = element.fire("ajax:before");
78
+ if (event.stopped) return false;
79
+
80
+ if (element.tagName.toLowerCase() === 'form') {
81
+ method = element.readAttribute('method') || 'post';
82
+ url = element.readAttribute('action');
83
+ params = element.serialize();
84
+ } else {
85
+ method = element.readAttribute('data-method') || 'get';
86
+ url = element.readAttribute('href');
87
+ params = {};
88
+ }
89
+
90
+ new Ajax.Request(url, {
91
+ method: method,
92
+ parameters: params,
93
+ evalScripts: true,
94
+
95
+ onComplete: function(request) { element.fire("ajax:complete", request); },
96
+ onSuccess: function(request) { element.fire("ajax:success", request); },
97
+ onFailure: function(request) { element.fire("ajax:failure", request); }
98
+ });
99
+
100
+ element.fire("ajax:after");
101
+ }
102
+
103
+ function handleMethod(element) {
104
+ var method = element.readAttribute('data-method'),
105
+ url = element.readAttribute('href'),
106
+ csrf_param = $$('meta[name=csrf-param]')[0],
107
+ csrf_token = $$('meta[name=csrf-token]')[0];
108
+
109
+ var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
110
+ element.parentNode.insert(form);
111
+
112
+ if (method !== 'post') {
113
+ var field = new Element('input', { type: 'hidden', name: '_method', value: method });
114
+ form.insert(field);
115
+ }
116
+
117
+ if (csrf_param) {
118
+ var param = csrf_param.readAttribute('content'),
119
+ token = csrf_token.readAttribute('content'),
120
+ field = new Element('input', { type: 'hidden', name: param, value: token });
121
+ form.insert(field);
122
+ }
123
+
124
+ form.submit();
125
+ }
126
+
127
+
128
+ document.on("click", "*[data-confirm]", function(event, element) {
129
+ var message = element.readAttribute('data-confirm');
130
+ if (!confirm(message)) event.stop();
131
+ });
132
+
133
+ document.on("click", "a[data-remote]", function(event, element) {
134
+ if (event.stopped) return;
135
+ handleRemote(element);
136
+ event.stop();
137
+ });
138
+
139
+ document.on("click", "a[data-method]", function(event, element) {
140
+ if (event.stopped) return;
141
+ handleMethod(element);
142
+ event.stop();
143
+ });
144
+
145
+ document.on("submit", function(event) {
146
+ var element = event.findElement(),
147
+ message = element.readAttribute('data-confirm');
148
+ if (message && !confirm(message)) {
149
+ event.stop();
150
+ return false;
151
+ }
152
+
153
+ var inputs = element.select("input[type=submit][data-disable-with]");
154
+ inputs.each(function(input) {
155
+ input.disabled = true;
156
+ input.writeAttribute('data-original-value', input.value);
157
+ input.value = input.readAttribute('data-disable-with');
158
+ });
159
+
160
+ var element = event.findElement("form[data-remote]");
161
+ if (element) {
162
+ handleRemote(element);
163
+ event.stop();
164
+ }
165
+ });
166
+
167
+ document.on("ajax:after", "form", function(event, element) {
168
+ var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
169
+ inputs.each(function(input) {
170
+ input.value = input.readAttribute('data-original-value');
171
+ input.removeAttribute('data-original-value');
172
+ input.disabled = false;
173
+ });
174
+ });
175
+ })();
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.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: /
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+ require 'rails/performance_test_help'
3
+
4
+ # Profiling results for each test method are written to tmp/performance.
5
+ class BrowsingTest < ActionDispatch::PerformanceTest
6
+ def test_homepage
7
+ get '/'
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ require 'rails/test_help'
4
+
5
+ class ActiveSupport::TestCase
6
+ # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
7
+ #
8
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
9
+ # -- they do not yet inherit this setting
10
+ fixtures :all
11
+
12
+ # Add more helper methods to be used by all tests here...
13
+ end
File without changes
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'good_migrations/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "good_migrations"
8
+ spec.version = GoodMigrations::VERSION
9
+ spec.authors = ["Justin Searls", "Kevin Baribeau"]
10
+ spec.email = ["searls@gmail.com", "kevin.baribeau@gmail.com"]
11
+
12
+ spec.summary = %q{Prevents Rails from auto-loading app code in database migrations}
13
+ spec.description = %q{Referencing code in app/ from a database migration risks breaking the migration when your app code changes; this gem prevents that mistake}
14
+ spec.homepage = "https://github.com/testdouble/good-migrations"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "railties", ">= 3.1"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.10"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "minitest"
26
+ spec.add_development_dependency "pry"
27
+ end
@@ -0,0 +1,3 @@
1
+ require "good_migrations/version"
2
+ require "good_migrations/load_error"
3
+ require "good_migrations/railtie" if defined?(Rails)
@@ -0,0 +1,4 @@
1
+ module GoodMigrations
2
+ class LoadError < ::LoadError
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ require "active_record/railtie"
2
+
3
+ module GoodMigrations
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ Dir[File.join(File.dirname(__FILE__), '../../tasks/*.rake')].each do |file|
7
+ load file
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module GoodMigrations
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,63 @@
1
+ require 'active_support/dependencies'
2
+ require 'good_migrations'
3
+
4
+ namespace :good_migrations do
5
+ task :disable_autoload do
6
+ next if ENV['GOOD_MIGRATIONS'] == "skip"
7
+ ActiveSupport::Dependencies.class_eval do
8
+ extend Module.new {
9
+ def load_file(path, const_paths = loadable_constants_for_path(path))
10
+ if path.starts_with? File.join(Rails.application.root, 'app')
11
+ raise GoodMigrations::LoadError, <<-ERROR
12
+ Rails attempted to auto-load:
13
+
14
+ #{path}
15
+
16
+ Which is in your project's `app/` directory. The good_migrations
17
+ gem was designed to prevent this, because migrations are intended
18
+ to be immutable and safe-to-run for the life of your project, but
19
+ code in `app/` is liable to change at any time.
20
+
21
+ The most common reason for this error is that you may be referencing an
22
+ ActiveRecord model inside the migration in order to use the ActiveRecord API
23
+ to implement a data migration by querying and updating objects.
24
+
25
+ For instance, if you want to access a model "User" in your migration, it's safer
26
+ to redefine the class inside the migration instead, like this:
27
+
28
+ class MakeUsersOlder < ActiveRecord::Migration
29
+ class User < ActiveRecord::Base
30
+ # Define whatever you need on the User beyond what AR adds automatically
31
+ end
32
+
33
+ def up
34
+ User.find_each do |user|
35
+ user.update!(:age => user.age + 1)
36
+ end
37
+ end
38
+
39
+ def down
40
+ #...
41
+ end
42
+ end
43
+
44
+ For more information, visit:
45
+
46
+ https://github.com/testdouble/good-migrations
47
+
48
+ ERROR
49
+ else
50
+ super
51
+ end
52
+ end
53
+ }
54
+ end
55
+ end
56
+ end
57
+
58
+ Rake.application.in_namespace('db:migrate') do |namespace|
59
+ ([Rake::Task['db:migrate']] + namespace.tasks).each do |task|
60
+ task.prerequisites << "good_migrations:disable_autoload"
61
+ end
62
+ end
63
+
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: good_migrations
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Justin Searls
8
+ - Kevin Baribeau
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2016-02-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '3.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '3.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.10'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.10'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '10.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '10.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: minitest
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ description: Referencing code in app/ from a database migration risks breaking the
85
+ migration when your app code changes; this gem prevents that mistake
86
+ email:
87
+ - searls@gmail.com
88
+ - kevin.baribeau@gmail.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".travis.yml"
95
+ - Gemfile
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - bin/console
100
+ - bin/setup
101
+ - example/.gitignore
102
+ - example/Gemfile
103
+ - example/README
104
+ - example/Rakefile
105
+ - example/app/controllers/application_controller.rb
106
+ - example/app/helpers/application_helper.rb
107
+ - example/app/models/pant.rb
108
+ - example/app/views/layouts/application.html.erb
109
+ - example/config.ru
110
+ - example/config/application.rb
111
+ - example/config/boot.rb
112
+ - example/config/database.yml
113
+ - example/config/environment.rb
114
+ - example/config/environments/development.rb
115
+ - example/config/environments/production.rb
116
+ - example/config/environments/test.rb
117
+ - example/config/initializers/backtrace_silencers.rb
118
+ - example/config/initializers/inflections.rb
119
+ - example/config/initializers/mime_types.rb
120
+ - example/config/initializers/secret_token.rb
121
+ - example/config/initializers/session_store.rb
122
+ - example/config/locales/en.yml
123
+ - example/config/routes.rb
124
+ - example/db/migrate/20160202162849_create_pants.rb
125
+ - example/db/migrate/20160202163803_change_pants.rb
126
+ - example/db/migrate/20160202182520_change_pants_dangerously.rb
127
+ - example/db/seeds.rb
128
+ - example/doc/README_FOR_APP
129
+ - example/lib/tasks/.gitkeep
130
+ - example/public/404.html
131
+ - example/public/422.html
132
+ - example/public/500.html
133
+ - example/public/favicon.ico
134
+ - example/public/images/rails.png
135
+ - example/public/index.html
136
+ - example/public/javascripts/application.js
137
+ - example/public/javascripts/controls.js
138
+ - example/public/javascripts/dragdrop.js
139
+ - example/public/javascripts/effects.js
140
+ - example/public/javascripts/prototype.js
141
+ - example/public/javascripts/rails.js
142
+ - example/public/robots.txt
143
+ - example/public/stylesheets/.gitkeep
144
+ - example/script/rails
145
+ - example/test/performance/browsing_test.rb
146
+ - example/test/test_helper.rb
147
+ - example/vendor/plugins/.gitkeep
148
+ - good_migrations.gemspec
149
+ - lib/good_migrations.rb
150
+ - lib/good_migrations/load_error.rb
151
+ - lib/good_migrations/railtie.rb
152
+ - lib/good_migrations/version.rb
153
+ - tasks/good_migrations.rake
154
+ homepage: https://github.com/testdouble/good-migrations
155
+ licenses: []
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.4.5.1
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: Prevents Rails from auto-loading app code in database migrations
177
+ test_files: []