validation_issues 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.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +50 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/validation_issues.js +2 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/assets/stylesheets/validation_issues.css +5 -0
- data/app/assets/stylesheets/validation_issues/buttons.css +77 -0
- data/app/controllers/validation_admin/validation_issues_controller.rb +44 -0
- data/app/models/validation_issue.rb +26 -0
- data/app/views/validation_admin/validation_issues/index.html.erb +25 -0
- data/app/views/validation_admin/validation_issues/show.html.erb +22 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20120722204204_create_validation_issues.rb +16 -0
- data/lib/generators/valid_issues/templates/migration.rb +22 -0
- data/lib/generators/valid_issues/valid_issues_generator.rb +23 -0
- data/lib/tasks/validation_issues_tasks.rake +4 -0
- data/lib/validation_issues.rb +7 -0
- data/lib/validation_issues/acts_as_validation_issues.rb +37 -0
- data/lib/validation_issues/core_ext.rb +0 -0
- data/lib/validation_issues/engine.rb +4 -0
- data/lib/validation_issues/version.rb +3 -0
- data/test/acts_as_validation_issues_test.rb +21 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/user.rb +10 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +56 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20120722183345_create_users.rb +11 -0
- data/test/dummy/db/schema.rb +38 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +128 -0
- data/test/dummy/log/test.log +1129 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/fixtures/users.yml +11 -0
- data/test/dummy/test/unit/user_test.rb +7 -0
- data/test/factories/validation_issues.rb +9 -0
- data/test/functional/validation_issues_controller_test.rb +42 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +17 -0
- data/test/unit/helpers/validation_issues_helper_test.rb +4 -0
- data/test/unit/validation_issue_test.rb +23 -0
- data/test/validation_issues_test.rb +7 -0
- metadata +186 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= ValidationIssues
|
2
|
+
|
3
|
+
The Reason for this project is simple. People are paying attention to A/B tests and user conversion without having all the details.
|
4
|
+
|
5
|
+
For example, Lets say you have a form that appears to have users drop out of your signup funnel. Normally the first stab at the problem is to create an A/B test without any data.
|
6
|
+
|
7
|
+
What if you knew 90% of the people that hit the form had a validation error on the first_name field. I'm betting that you might not need an AB test. If you did add an AB test you would focus on the first_name field.
|
8
|
+
|
9
|
+
This problem actually happened on a live production app I was working on. Turns out the first_name validated white space. If a user added a space at the end of their name the validation would fail. The user would receive a "Invalid First Name" message. They would look at their name and be confused and eventually leave. The solution was as simple as sanitizing the first_name before validations. If we had this tool the problem would have never lasted for so long.
|
10
|
+
|
11
|
+
= Getting started
|
12
|
+
|
13
|
+
add this to your gemfile
|
14
|
+
|
15
|
+
gem 'validation_issues'
|
16
|
+
|
17
|
+
In your application_controller.rb add the following to have permissions to see the admin section:
|
18
|
+
|
19
|
+
class ApplicationController < ActionController::Base
|
20
|
+
protected
|
21
|
+
def has_validation_issues_admin_privileges
|
22
|
+
# logic you want to make this true
|
23
|
+
# Typically this will work
|
24
|
+
current_user && current_user.admin?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
In your model add 'acts_as_validation_issues'
|
29
|
+
|
30
|
+
class User < ActiveRecord::Base
|
31
|
+
# add this line
|
32
|
+
acts_as_validation_issues
|
33
|
+
end
|
34
|
+
|
35
|
+
Now the only you need to do is this in your controller:
|
36
|
+
|
37
|
+
def create
|
38
|
+
user = User.new(:first_name => '', :last_name => 'Good Last Name')
|
39
|
+
if user.save
|
40
|
+
# do something
|
41
|
+
else
|
42
|
+
user.log_validation_issue!('user_form')
|
43
|
+
# do something else(like render the form again)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
you pass the form's name into the user.log_validation_issue! method. This way if you have an AB test you can see the difference in the results.
|
48
|
+
|
49
|
+
Happy Coding. If you have any problems feel free to ask me directly, David Henner
|
50
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ValidationIssues'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.libs << 'test'
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
36
|
+
t.verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
@@ -0,0 +1,56 @@
|
|
1
|
+
body { background-color: #fff; color: #333; }
|
2
|
+
|
3
|
+
body, p, ol, ul, td {
|
4
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
5
|
+
font-size: 13px;
|
6
|
+
line-height: 18px;
|
7
|
+
}
|
8
|
+
|
9
|
+
pre {
|
10
|
+
background-color: #eee;
|
11
|
+
padding: 10px;
|
12
|
+
font-size: 11px;
|
13
|
+
}
|
14
|
+
|
15
|
+
a { color: #000; }
|
16
|
+
a:visited { color: #666; }
|
17
|
+
a:hover { color: #fff; background-color:#000; }
|
18
|
+
|
19
|
+
div.field, div.actions {
|
20
|
+
margin-bottom: 10px;
|
21
|
+
}
|
22
|
+
|
23
|
+
#notice {
|
24
|
+
color: green;
|
25
|
+
}
|
26
|
+
|
27
|
+
.field_with_errors {
|
28
|
+
padding: 2px;
|
29
|
+
background-color: red;
|
30
|
+
display: table;
|
31
|
+
}
|
32
|
+
|
33
|
+
#error_explanation {
|
34
|
+
width: 450px;
|
35
|
+
border: 2px solid red;
|
36
|
+
padding: 7px;
|
37
|
+
padding-bottom: 0;
|
38
|
+
margin-bottom: 20px;
|
39
|
+
background-color: #f0f0f0;
|
40
|
+
}
|
41
|
+
|
42
|
+
#error_explanation h2 {
|
43
|
+
text-align: left;
|
44
|
+
font-weight: bold;
|
45
|
+
padding: 5px 5px 5px 15px;
|
46
|
+
font-size: 12px;
|
47
|
+
margin: -7px;
|
48
|
+
margin-bottom: 0px;
|
49
|
+
background-color: #c00;
|
50
|
+
color: #fff;
|
51
|
+
}
|
52
|
+
|
53
|
+
#error_explanation ul li {
|
54
|
+
font-size: 12px;
|
55
|
+
list-style: square;
|
56
|
+
}
|
@@ -0,0 +1,77 @@
|
|
1
|
+
.button {
|
2
|
+
display: inline-block;
|
3
|
+
zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
|
4
|
+
*display: inline;
|
5
|
+
vertical-align: baseline;
|
6
|
+
margin: 0 2px;
|
7
|
+
outline: none;
|
8
|
+
cursor: pointer;
|
9
|
+
text-align: center;
|
10
|
+
text-decoration: none;
|
11
|
+
font: 14px/100% Arial, Helvetica, sans-serif;
|
12
|
+
padding: .5em 2em .55em;
|
13
|
+
text-shadow: 0 1px 1px rgba(0,0,0,.3);
|
14
|
+
-webkit-border-radius: .25em;
|
15
|
+
-moz-border-radius: .25em;
|
16
|
+
border-radius: .25em;
|
17
|
+
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,.2);
|
18
|
+
-moz-box-shadow: 0 1px 1px rgba(0,0,0,.2);
|
19
|
+
box-shadow: 0 1px 1px rgba(0,0,0,.2);
|
20
|
+
}
|
21
|
+
|
22
|
+
input[type="submit"].button {border: 0;background-color: transparent;color: #888;}
|
23
|
+
input[type="submit"].button.dark-orange-button {color:#FFF;}
|
24
|
+
input[type="submit"].button.small-dark-orange-button {color:#FFF;}
|
25
|
+
|
26
|
+
.dark-orange-button {
|
27
|
+
color: #fef4e9;
|
28
|
+
border: solid 1px #db3909;
|
29
|
+
background: #c6481a;
|
30
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#c8581a), to(#c5441F));
|
31
|
+
background: -moz-linear-gradient(top, #c8581a, #c5441F);
|
32
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c8581a', endColorstr='#c5441F');
|
33
|
+
}
|
34
|
+
.dark-orange-button:hover {
|
35
|
+
background: #c4421F;
|
36
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#c75114), to(#c23415));
|
37
|
+
background: -moz-linear-gradient(top, #c75114, #c23415);
|
38
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c75114', endColorstr='#c23415');
|
39
|
+
}
|
40
|
+
.dark-orange-button:active {
|
41
|
+
background: #c4421F;
|
42
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#c75114), to(#c23415));
|
43
|
+
background: -moz-linear-gradient(top, #c75114, #c23415);
|
44
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c75114', endColorstr='#c23415');
|
45
|
+
}
|
46
|
+
|
47
|
+
.small-dark-orange-button {
|
48
|
+
font-family:'Century Schoolbook Italic', 'Century Schoolbook', Georgia;
|
49
|
+
color: #fef4e9 !important;
|
50
|
+
border: solid 1px #db3909;
|
51
|
+
background: #c6481a;
|
52
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#c9681a), to(#c6451F));
|
53
|
+
background: -moz-linear-gradient(top, #c9681a, #c6451F);
|
54
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c9681a', endColorstr='#c6451F');
|
55
|
+
font-size: 14px;
|
56
|
+
font-weight: normal;
|
57
|
+
padding: 0.2em 0.7em;
|
58
|
+
&.myriad {
|
59
|
+
font-family: "MyriadPro","Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
60
|
+
padding: 0.7em;
|
61
|
+
padding-top: 0.3em;
|
62
|
+
padding-bottom: 0.1em;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
.small-dark-orange-button:hover {
|
66
|
+
color: #fff7ef;
|
67
|
+
background: #c4421F;
|
68
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#c65114), to(#c23415));
|
69
|
+
background: -moz-linear-gradient(top, #c65114, #c23415);
|
70
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c65114', endColorstr='#c23415');
|
71
|
+
}
|
72
|
+
.small-dark-orange-button:active {
|
73
|
+
background: #c4421F;
|
74
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#c65114), to(#c23415));
|
75
|
+
background: -moz-linear-gradient(top, #c65114, #c23415);
|
76
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#c65114', endColorstr='#c23415');
|
77
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class ValidationAdmin::ValidationIssuesController < ApplicationController
|
2
|
+
before_filter :redirect_if_no_privileges
|
3
|
+
# has_validation_issues_admin_privileges
|
4
|
+
|
5
|
+
# GET /validation_issues
|
6
|
+
# GET /validation_issues.json
|
7
|
+
def index
|
8
|
+
@validation_issues = ValidationIssue.all
|
9
|
+
|
10
|
+
respond_to do |format|
|
11
|
+
format.html # index.html.erb
|
12
|
+
format.json { render json: @validation_issues }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# GET /validation_issues/1
|
17
|
+
# GET /validation_issues/1.json
|
18
|
+
def show
|
19
|
+
@validation_issue = ValidationIssue.find(params[:id])
|
20
|
+
|
21
|
+
respond_to do |format|
|
22
|
+
format.html # show.html.erb
|
23
|
+
format.json { render json: @validation_issue }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# DELETE /validation_issues/1
|
28
|
+
# DELETE /validation_issues/1.json
|
29
|
+
def destroy
|
30
|
+
@validation_issue = ValidationIssue.find(params[:id])
|
31
|
+
@validation_issue.clear_data!
|
32
|
+
|
33
|
+
respond_to do |format|
|
34
|
+
format.html { redirect_to validation_admin_validation_issues_url }
|
35
|
+
format.json { head :no_content }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def redirect_if_no_privileges
|
42
|
+
redirect_to root_url and return unless has_validation_issues_admin_privileges
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class ValidationIssue < ActiveRecord::Base
|
2
|
+
attr_accessible :form_name, :issue_count, :issue_hash, :issue_type, :notes
|
3
|
+
serialize :issue_hash, Hash
|
4
|
+
|
5
|
+
validates :form_name, :presence => true, :uniqueness => true
|
6
|
+
|
7
|
+
def clear_data!
|
8
|
+
self.issue_count = 0
|
9
|
+
self.issue_hash = {}
|
10
|
+
self.notes = ''
|
11
|
+
self.save!
|
12
|
+
end
|
13
|
+
|
14
|
+
def increment_issue_count!
|
15
|
+
increment_with_sql!('issue_count')
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def increment_with_sql!(attribute, by = 1)
|
21
|
+
raise ArgumentError("Invalid attribute: #{attribute}") unless attribute_names.include?(attribute.to_s)
|
22
|
+
original_value_sql = "CASE WHEN `#{attribute}` IS NULL THEN 0 ELSE `#{attribute}` END"
|
23
|
+
self.class.update_all("`#{attribute}` = #{original_value_sql} + #{by.to_i}", "id = #{id}")
|
24
|
+
reload
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
2
|
+
|
3
|
+
<h1> Validation Issues </h1>
|
4
|
+
|
5
|
+
<table>
|
6
|
+
<tr>
|
7
|
+
<th>Type</th>
|
8
|
+
<th>Form Name</th>
|
9
|
+
<th>Count</th>
|
10
|
+
<th></th>
|
11
|
+
<th></th>
|
12
|
+
</tr>
|
13
|
+
|
14
|
+
<% @validation_issues.each do |validation_issue| %>
|
15
|
+
<tr>
|
16
|
+
<td><%= validation_issue.issue_type %></td>
|
17
|
+
<td><%= validation_issue.form_name %></td>
|
18
|
+
<td><%= validation_issue.issue_count %></td>
|
19
|
+
<td><%= link_to 'Show', validation_admin_validation_issue_path(validation_issue) %></td>
|
20
|
+
<td><%= link_to 'Reset!',
|
21
|
+
validation_admin_validation_issue_path(validation_issue),
|
22
|
+
method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
23
|
+
</tr>
|
24
|
+
<% end %>
|
25
|
+
</table>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
2
|
+
|
3
|
+
<h2> <%= @validation_issue.issue_type %>: <%= @validation_issue.form_name %> </h2>
|
4
|
+
|
5
|
+
<p>
|
6
|
+
<b>Issues (<%= @validation_issue.issue_count %>):</b>
|
7
|
+
<ul>
|
8
|
+
<% @validation_issue.issue_hash.each do |k, v| %>
|
9
|
+
<li><label> <%= k %>: </label> <%= v %></li>
|
10
|
+
<% end %>
|
11
|
+
</ul>
|
12
|
+
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<% unless @validation_issue.notes.blank? %>
|
16
|
+
<p>
|
17
|
+
<b>Notes:</b>
|
18
|
+
<%= @validation_issue.notes %>
|
19
|
+
</p>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<%= link_to 'Back', validation_admin_validation_issues_path, :class => 'button small-dark-orange-button' %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateValidationIssues < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :validation_issues do |t|
|
4
|
+
t.string :issue_type
|
5
|
+
t.string :form_name, :null => false
|
6
|
+
t.text :issue_hash, :null => false
|
7
|
+
t.text :notes, :default => ''
|
8
|
+
t.integer :issue_count
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
add_index :validation_issues, :form_name# , :length => 10
|
13
|
+
add_index :validation_issues, :issue_type
|
14
|
+
add_index :validation_issues, [:form_name, :issue_type], :unique => true
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class CreateValidationIssues < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :validation_issues do |t|
|
4
|
+
|
5
|
+
t.string :issue_type, :null => false
|
6
|
+
t.string :form_name, :null => false
|
7
|
+
t.text :issue_hash, :null => false
|
8
|
+
#t.text :issued_by_ids
|
9
|
+
t.text :notes
|
10
|
+
t.integer :issue_count
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
add_index :validation_issues, :form_name
|
15
|
+
add_index :validation_issues, :issue_type
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.down
|
20
|
+
drop_table :versions
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# CURRENT FILE :: lib/generators/valid_issues/valid_issues_generator.rb
|
2
|
+
# Requires
|
3
|
+
require 'rails/generators'
|
4
|
+
require 'rails/generators/migration'
|
5
|
+
|
6
|
+
class ValidIssuesGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
def self.source_root
|
9
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.next_migration_number(dirname)
|
13
|
+
if ActiveRecord::Base.timestamped_migrations
|
14
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
15
|
+
else
|
16
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_migration_file
|
21
|
+
migration_template 'migration.rb', 'db/migrate/create_validation_issues_table.rb'
|
22
|
+
end
|
23
|
+
end
|