reactive 0.1.0
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/History.txt +3 -0
- data/MIT-LICENSE +21 -0
- data/Manifest.txt +60 -0
- data/README.txt +130 -0
- data/Rakefile +14 -0
- data/app_generators/reactive/USAGE +11 -0
- data/app_generators/reactive/reactive_generator.rb +160 -0
- data/app_generators/reactive/templates/README +130 -0
- data/app_generators/reactive/templates/Rakefile +10 -0
- data/app_generators/reactive/templates/app/controllers/application_controller.rb +2 -0
- data/app_generators/reactive/templates/app/helpers/application_helper.rb +2 -0
- data/app_generators/reactive/templates/config/boot.rb +94 -0
- data/app_generators/reactive/templates/config/databases/frontbase.yml +28 -0
- data/app_generators/reactive/templates/config/databases/mysql.yml +54 -0
- data/app_generators/reactive/templates/config/databases/oracle.yml +39 -0
- data/app_generators/reactive/templates/config/databases/postgresql.yml +48 -0
- data/app_generators/reactive/templates/config/databases/sqlite2.yml +16 -0
- data/app_generators/reactive/templates/config/databases/sqlite3.yml +19 -0
- data/app_generators/reactive/templates/config/empty.log +0 -0
- data/app_generators/reactive/templates/config/environment.rb +11 -0
- data/app_generators/reactive/templates/script/destroy +12 -0
- data/app_generators/reactive/templates/script/generate +12 -0
- data/app_generators/reactive/templates/script/run +5 -0
- data/app_generators/reactive/templates/script/win_script.cmd +1 -0
- data/bin/reactive +16 -0
- data/lib/code_statistics.rb +107 -0
- data/lib/controller.rb +23 -0
- data/lib/controller/base.rb +442 -0
- data/lib/controller/filters.rb +767 -0
- data/lib/controller/flash.rb +161 -0
- data/lib/controller/helpers.rb +204 -0
- data/lib/controller/layout.rb +326 -0
- data/lib/dispatcher.rb +46 -0
- data/lib/generated_attribute.rb +40 -0
- data/lib/initializer.rb +425 -0
- data/lib/named_base_generator.rb +92 -0
- data/lib/reactive.rb +6 -0
- data/lib/request.rb +17 -0
- data/lib/source_annotation_extractor.rb +62 -0
- data/lib/tasks/annotations.rake +23 -0
- data/lib/tasks/databases.rake +347 -0
- data/lib/tasks/log.rake +9 -0
- data/lib/tasks/misc.rake +5 -0
- data/lib/tasks/reactive.rb +16 -0
- data/lib/tasks/statistics.rake +17 -0
- data/lib/tasks/testing.rake +118 -0
- data/lib/version.rb +9 -0
- data/lib/view.rb +1 -0
- data/lib/view/base.rb +33 -0
- data/reactive_generators/model/USAGE +27 -0
- data/reactive_generators/model/model_generator.rb +52 -0
- data/reactive_generators/model/templates/fixtures.yml +19 -0
- data/reactive_generators/model/templates/migration.rb +16 -0
- data/reactive_generators/model/templates/model.rb +2 -0
- data/reactive_generators/model/templates/unit_test.rb +8 -0
- data/reactive_generators/scaffold/USAGE +26 -0
- data/reactive_generators/scaffold/scaffold_generator.rb +75 -0
- data/reactive_generators/scaffold/templates/controller.rb +51 -0
- data/reactive_generators/scaffold/templates/functional_test.rb +49 -0
- data/reactive_generators/scaffold/templates/helper.rb +2 -0
- metadata +142 -0
data/lib/tasks/log.rake
ADDED
data/lib/tasks/misc.rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$VERBOSE = nil
|
2
|
+
|
3
|
+
REACTIVE_ROOT = Dir.pwd
|
4
|
+
require "#{REACTIVE_ROOT}/config/boot.rb"
|
5
|
+
Reactive.boot
|
6
|
+
|
7
|
+
# Load Reactive rakefile extensions
|
8
|
+
Dir["#{File.dirname(__FILE__)}/*.rake"].each { |ext| load ext }
|
9
|
+
|
10
|
+
# Load any custom rakefile extensions
|
11
|
+
Dir["#{REACTIVE_ROOT}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
|
12
|
+
|
13
|
+
# Load also the ones from the plugins
|
14
|
+
Gem.loaded_specs.values.each do |spec|
|
15
|
+
Dir["#{spec.full_gem_path}/**/tasks/**/*.rake"].sort.each { |ext| load ext }
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
STATS_DIRECTORIES = [
|
2
|
+
%w(Controllers app/controllers),
|
3
|
+
%w(Helpers app/helpers),
|
4
|
+
%w(Models app/models),
|
5
|
+
%w(Views app/models),
|
6
|
+
%w(Libraries lib/),
|
7
|
+
%w(Integration\ tests test/integration),
|
8
|
+
%w(Functional\ tests test/functional),
|
9
|
+
%w(Unit\ tests test/unit)
|
10
|
+
|
11
|
+
].collect { |name, dir| [ name, "#{REACTIVE_ROOT}/#{dir}" ] }.select { |name, dir| File.directory?(dir) }
|
12
|
+
|
13
|
+
desc "Report code statistics (KLOCs, etc) from the application"
|
14
|
+
task :stats do
|
15
|
+
require 'code_statistics'
|
16
|
+
CodeStatistics.new(*STATS_DIRECTORIES).to_s
|
17
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
TEST_CHANGES_SINCE = Time.now - 600
|
2
|
+
|
3
|
+
# Look up tests for recently modified sources.
|
4
|
+
def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
|
5
|
+
FileList[source_pattern].map do |path|
|
6
|
+
if File.mtime(path) > touched_since
|
7
|
+
tests = []
|
8
|
+
source_dir = File.dirname(path).split("/")
|
9
|
+
source_file = File.basename(path, '.rb')
|
10
|
+
|
11
|
+
# Support subdirs in app/models and app/controllers
|
12
|
+
modified_test_path = source_dir.length > 2 ? "#{test_path}/" << source_dir[1..source_dir.length].join('/') : test_path
|
13
|
+
|
14
|
+
# For modified files in app/ run the tests for it. ex. /test/functional/account_controller.rb
|
15
|
+
test = "#{modified_test_path}/#{source_file}_test.rb"
|
16
|
+
tests.push test if File.exists?(test)
|
17
|
+
|
18
|
+
# For modified files in app, run tests in subdirs too. ex. /test/functional/account/*_test.rb
|
19
|
+
test = "#{modified_test_path}/#{File.basename(path, '.rb').sub("_controller","")}"
|
20
|
+
FileList["#{test}/*_test.rb"].each { |f| tests.push f } if File.exists?(test)
|
21
|
+
|
22
|
+
return tests
|
23
|
+
|
24
|
+
end
|
25
|
+
end.flatten.compact
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# Recreated here from ActiveSupport because :uncommitted needs it before Reactive is available
|
30
|
+
module Kernel
|
31
|
+
def silence_stderr
|
32
|
+
old_stderr = STDERR.dup
|
33
|
+
STDERR.reopen(RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'NUL:' : '/dev/null')
|
34
|
+
STDERR.sync = true
|
35
|
+
yield
|
36
|
+
ensure
|
37
|
+
STDERR.reopen(old_stderr)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Test all units and functionals'
|
42
|
+
task :test do
|
43
|
+
errors = %w(test:units test:functionals test:integration).collect do |task|
|
44
|
+
begin
|
45
|
+
Rake::Task[task].invoke
|
46
|
+
nil
|
47
|
+
rescue => e
|
48
|
+
task
|
49
|
+
end
|
50
|
+
end.compact
|
51
|
+
abort "Errors running #{errors.to_sentence}!" if errors.any?
|
52
|
+
end
|
53
|
+
|
54
|
+
namespace :test do
|
55
|
+
Rake::TestTask.new(:recent => "db:test:prepare") do |t|
|
56
|
+
since = TEST_CHANGES_SINCE
|
57
|
+
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
|
58
|
+
recent_tests('app/models/**/*.rb', 'test/unit', since) +
|
59
|
+
recent_tests('app/controllers/**/*.rb', 'test/functional', since)
|
60
|
+
|
61
|
+
t.libs << 'test'
|
62
|
+
t.verbose = true
|
63
|
+
t.test_files = touched.uniq
|
64
|
+
end
|
65
|
+
Rake::Task['test:recent'].comment = "Test recent changes"
|
66
|
+
|
67
|
+
Rake::TestTask.new(:uncommitted => "db:test:prepare") do |t|
|
68
|
+
def t.file_list
|
69
|
+
changed_since_checkin = silence_stderr { `svn status` }.map { |path| path.chomp[7 .. -1] }
|
70
|
+
|
71
|
+
models = changed_since_checkin.select { |path| path =~ /app[\\\/]models[\\\/].*\.rb/ }
|
72
|
+
controllers = changed_since_checkin.select { |path| path =~ /app[\\\/]controllers[\\\/].*\.rb/ }
|
73
|
+
|
74
|
+
unit_tests = models.map { |model| "test/unit/#{File.basename(model, '.rb')}_test.rb" }
|
75
|
+
functional_tests = controllers.map { |controller| "test/functional/#{File.basename(controller, '.rb')}_test.rb" }
|
76
|
+
|
77
|
+
unit_tests.uniq + functional_tests.uniq
|
78
|
+
end
|
79
|
+
|
80
|
+
t.libs << 'test'
|
81
|
+
t.verbose = true
|
82
|
+
end
|
83
|
+
Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion)"
|
84
|
+
|
85
|
+
Rake::TestTask.new(:units => "db:test:prepare") do |t|
|
86
|
+
t.libs << "test"
|
87
|
+
t.pattern = 'test/unit/**/*_test.rb'
|
88
|
+
t.verbose = true
|
89
|
+
end
|
90
|
+
Rake::Task['test:units'].comment = "Run the unit tests in test/unit"
|
91
|
+
|
92
|
+
Rake::TestTask.new(:functionals => "db:test:prepare") do |t|
|
93
|
+
t.libs << "test"
|
94
|
+
t.pattern = 'test/functional/**/*_test.rb'
|
95
|
+
t.verbose = true
|
96
|
+
end
|
97
|
+
Rake::Task['test:functionals'].comment = "Run the functional tests in test/functional"
|
98
|
+
|
99
|
+
Rake::TestTask.new(:integration => "db:test:prepare") do |t|
|
100
|
+
t.libs << "test"
|
101
|
+
t.pattern = 'test/integration/**/*_test.rb'
|
102
|
+
t.verbose = true
|
103
|
+
end
|
104
|
+
Rake::Task['test:integration'].comment = "Run the integration tests in test/integration"
|
105
|
+
|
106
|
+
Rake::TestTask.new(:plugins => :environment) do |t|
|
107
|
+
t.libs << "test"
|
108
|
+
|
109
|
+
if ENV['PLUGIN']
|
110
|
+
t.pattern = "vendor/plugins/#{ENV['PLUGIN']}/test/**/*_test.rb"
|
111
|
+
else
|
112
|
+
t.pattern = 'vendor/plugins/*/**/test/**/*_test.rb'
|
113
|
+
end
|
114
|
+
|
115
|
+
t.verbose = true
|
116
|
+
end
|
117
|
+
Rake::Task['test:plugins'].comment = "Run the plugin tests in vendor/plugins/*/**/test (or specify with PLUGIN=name)"
|
118
|
+
end
|
data/lib/version.rb
ADDED
data/lib/view.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'view/base'
|
data/lib/view/base.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Reactive
|
2
|
+
module View
|
3
|
+
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
class Base
|
7
|
+
class << self
|
8
|
+
attr_writer :view_paths
|
9
|
+
def view_paths
|
10
|
+
@view_paths ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_writer :asset_paths
|
14
|
+
def asset_paths
|
15
|
+
@asset_paths ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
def handle_request(request)
|
19
|
+
Dispatcher.dispatch(request)
|
20
|
+
end
|
21
|
+
|
22
|
+
def asset_pathname_for(filename)
|
23
|
+
asset_paths.each do |path|
|
24
|
+
pathname = File.join(path, filename)
|
25
|
+
return pathname if File.file?(pathname)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Description:
|
2
|
+
Stubs out a new model. Pass the model name, either CamelCased or
|
3
|
+
under_scored, and an optional list of attribute pairs as arguments.
|
4
|
+
|
5
|
+
Attribute pairs are column_name:sql_type arguments specifying the
|
6
|
+
model's attributes. Timestamps are added by default, so you don't have to
|
7
|
+
specify them by hand as 'created_at:datetime updated_at:datetime'.
|
8
|
+
|
9
|
+
You don't have to think up every attribute up front, but it helps to
|
10
|
+
sketch out a few so you can start working with the model immediately.
|
11
|
+
|
12
|
+
This generates a model class in app/models, a unit test in test/unit,
|
13
|
+
a test fixture in test/fixtures/singular_name.yml, and a migration in
|
14
|
+
db/migrate.
|
15
|
+
|
16
|
+
Examples:
|
17
|
+
`./script/generate model account`
|
18
|
+
|
19
|
+
creates an Account model, test, fixture, and migration:
|
20
|
+
Model: app/models/account.rb
|
21
|
+
Test: test/unit/account_test.rb
|
22
|
+
Fixtures: test/fixtures/accounts.yml
|
23
|
+
Migration: db/migrate/XXX_add_accounts.rb
|
24
|
+
|
25
|
+
`./script/generate model post title:string body:text published:boolean`
|
26
|
+
|
27
|
+
creates a Post model with a string title, text body, and published flag.
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'named_base_generator'
|
2
|
+
|
3
|
+
class ModelGenerator < Reactive::NamedBaseGenerator
|
4
|
+
default_options :skip_timestamps => false, :skip_migration => false, :skip_fixture => false
|
5
|
+
|
6
|
+
def initialize(runtime_args, runtime_options = {})
|
7
|
+
usage "Sorry, you disabled ActiveRecord in your config (see environment.rb). This generator is thus also disabled." unless defined? ActiveRecord
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def manifest
|
12
|
+
record do |m|
|
13
|
+
# Check for class naming collisions.
|
14
|
+
m.class_collisions class_path, class_name, "#{class_name}Test"
|
15
|
+
|
16
|
+
# Model, test, and fixture directories.
|
17
|
+
m.directory File.join('app/models', class_path)
|
18
|
+
m.directory File.join('test/unit', class_path)
|
19
|
+
m.directory File.join('test/fixtures', class_path)
|
20
|
+
|
21
|
+
# Model class, unit test, and fixtures.
|
22
|
+
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
|
23
|
+
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
|
24
|
+
|
25
|
+
unless options[:skip_fixture]
|
26
|
+
m.template 'fixtures.yml', File.join('test/fixtures', "#{table_name}.yml")
|
27
|
+
end
|
28
|
+
|
29
|
+
unless options[:skip_migration]
|
30
|
+
m.migration_template 'migration.rb', 'db/migrate', :assigns => {
|
31
|
+
:migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
|
32
|
+
}, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
def banner
|
39
|
+
"Usage: #{$0} #{spec.name} ModelName [field:type, field:type]"
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_options!(opt)
|
43
|
+
opt.separator ''
|
44
|
+
opt.separator 'Options:'
|
45
|
+
opt.on("--skip-timestamps",
|
46
|
+
"Don't add timestamps to the migration file for this model") { |v| options[:skip_timestamps] = v }
|
47
|
+
opt.on("--skip-migration",
|
48
|
+
"Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
|
49
|
+
opt.on("--skip-fixture",
|
50
|
+
"Don't generation a fixture file for this model") { |v| options[:skip_fixture] = v}
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
2
|
+
|
3
|
+
<% unless attributes.empty? -%>
|
4
|
+
one:
|
5
|
+
<% for attribute in attributes -%>
|
6
|
+
<%= attribute.name %>: <%= attribute.default %>
|
7
|
+
<% end -%>
|
8
|
+
|
9
|
+
two:
|
10
|
+
<% for attribute in attributes -%>
|
11
|
+
<%= attribute.name %>: <%= attribute.default %>
|
12
|
+
<% end -%>
|
13
|
+
<% else -%>
|
14
|
+
# one:
|
15
|
+
# column: value
|
16
|
+
#
|
17
|
+
# two:
|
18
|
+
# column: value
|
19
|
+
<% end -%>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
<% for attribute in attributes -%>
|
5
|
+
t.<%= attribute.type %> :<%= attribute.name %>
|
6
|
+
<% end -%>
|
7
|
+
<% unless options[:skip_timestamps] %>
|
8
|
+
t.timestamps
|
9
|
+
<% end -%>
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :<%= table_name %>
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Description:
|
2
|
+
Scaffolds an entire resource, from model and migration to controller and
|
3
|
+
views, along with a full test suite. The resource is ready to use as a
|
4
|
+
starting point for your CRUD resource-oriented application.
|
5
|
+
The generated actions are:
|
6
|
+
index, show, new, create, edit, update, delete, destroy
|
7
|
+
|
8
|
+
Pass the name of the model, either CamelCased or under_scored, as the first
|
9
|
+
argument, and an optional list of attribute pairs.
|
10
|
+
|
11
|
+
Attribute pairs are column_name:sql_type arguments specifying the
|
12
|
+
model's attributes. Timestamps are added by default, so you don't have to
|
13
|
+
specify them by hand as 'created_at:datetime updated_at:datetime'.
|
14
|
+
|
15
|
+
You don't have to think up every attribute up front, but it helps to
|
16
|
+
sketch out a few so you can start working with the resource immediately.
|
17
|
+
|
18
|
+
For example, `scaffold product name:string description:text price:decimal`
|
19
|
+
gives you a model with those three attributes, a controller that handles
|
20
|
+
the create/show/update/destroy, forms to create and edit your products,
|
21
|
+
and an index that lists them all.
|
22
|
+
|
23
|
+
Examples:
|
24
|
+
`./script/generate scaffold product` # no attributes, view will be anemic
|
25
|
+
`./script/generate scaffold product name:string description:text price:decimal`
|
26
|
+
`./script/generate scaffold purchase order_id:integer amount:decimal`
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'named_base_generator'
|
2
|
+
|
3
|
+
class ScaffoldGenerator < Reactive::NamedBaseGenerator
|
4
|
+
default_options :skip_timestamps => false, :skip_migration => false
|
5
|
+
|
6
|
+
attr_reader :controller_name,
|
7
|
+
:controller_class_path,
|
8
|
+
:controller_file_path,
|
9
|
+
:controller_class_nesting,
|
10
|
+
:controller_class_nesting_depth,
|
11
|
+
:controller_class_name,
|
12
|
+
:controller_underscore_name,
|
13
|
+
:controller_singular_name,
|
14
|
+
:controller_plural_name
|
15
|
+
alias_method :controller_file_name, :controller_underscore_name
|
16
|
+
alias_method :controller_table_name, :controller_plural_name
|
17
|
+
|
18
|
+
def initialize(runtime_args, runtime_options = {})
|
19
|
+
super
|
20
|
+
|
21
|
+
@controller_name = @name.pluralize
|
22
|
+
|
23
|
+
base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
|
24
|
+
@controller_class_name_without_nesting, @controller_underscore_name, @controller_plural_name = inflect_names(base_name)
|
25
|
+
@controller_singular_name=base_name.singularize
|
26
|
+
if @controller_class_nesting.empty?
|
27
|
+
@controller_class_name = @controller_class_name_without_nesting
|
28
|
+
else
|
29
|
+
@controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def manifest
|
34
|
+
record do |m|
|
35
|
+
# Check for class naming collisions.
|
36
|
+
m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper")
|
37
|
+
m.class_collisions(class_path, "#{class_name}")
|
38
|
+
|
39
|
+
# Controller, helper, views, and test directories.
|
40
|
+
m.directory(File.join('app/models', class_path))
|
41
|
+
m.directory(File.join('app/controllers', controller_class_path))
|
42
|
+
m.directory(File.join('app/helpers', controller_class_path))
|
43
|
+
m.directory(File.join('test/functional', controller_class_path))
|
44
|
+
m.directory(File.join('test/unit', class_path))
|
45
|
+
|
46
|
+
self.class.prepend_sources(Gem.loaded_specs.values.collect{|spec| RubiGen::PathFilteredSource.new(:GemPlugins, spec.full_gem_path, [:reactive, :test_unit]) })
|
47
|
+
m.dependency('model', [name] + @args, :collision => :skip) if defined? ActiveRecord
|
48
|
+
m.dependency('view', [name] + @args, :collision => :ask)
|
49
|
+
|
50
|
+
m.template('controller.rb', File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb"))
|
51
|
+
m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
|
52
|
+
m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
# Override with your own usage banner.
|
59
|
+
def banner
|
60
|
+
"Usage: #{$0} scaffold ModelName [field:type, field:type]"
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_options!(opt)
|
64
|
+
opt.separator ''
|
65
|
+
opt.separator 'Options:'
|
66
|
+
opt.on("--skip-timestamps",
|
67
|
+
"Don't add timestamps to the migration file for this model") { |v| options[:skip_timestamps] = v }
|
68
|
+
opt.on("--skip-migration",
|
69
|
+
"Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
|
70
|
+
end
|
71
|
+
|
72
|
+
def model_name
|
73
|
+
class_name.demodulize
|
74
|
+
end
|
75
|
+
end
|