aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--railties/lib/generators/active_record/model/model_generator.rb33
-rw-r--r--railties/lib/generators/active_record/model/templates/migration.rb16
-rw-r--r--railties/lib/generators/active_record/model/templates/model.rb5
-rw-r--r--railties/lib/generators/base.rb5
-rw-r--r--railties/lib/generators/generated_attribute.rb3
-rw-r--r--railties/lib/generators/named_base.rb4
-rw-r--r--railties/lib/generators/rails/app/templates/config/environment.rb6
-rw-r--r--railties/lib/generators/rails/model/USAGE27
-rw-r--r--railties/lib/generators/rails/model/model_generator.rb8
-rw-r--r--railties/lib/generators/test_unit/model/model_generator.rb24
-rw-r--r--railties/lib/generators/test_unit/model/templates/fixtures.yml19
-rw-r--r--railties/lib/generators/test_unit/model/templates/unit_test.rb8
-rw-r--r--railties/test/generators/controller_generator_test.rb2
-rw-r--r--railties/test/generators/generators_test_helper.rb14
-rw-r--r--railties/test/generators/helper_generator_test.rb19
-rw-r--r--railties/test/generators/mailer_generator_test.rb6
-rw-r--r--railties/test/generators/model_generator_test.rb72
-rw-r--r--railties/test/generators/observer_generator_test.rb6
18 files changed, 256 insertions, 21 deletions
diff --git a/railties/lib/generators/active_record/model/model_generator.rb b/railties/lib/generators/active_record/model/model_generator.rb
new file mode 100644
index 0000000000..448bf5c37f
--- /dev/null
+++ b/railties/lib/generators/active_record/model/model_generator.rb
@@ -0,0 +1,33 @@
+module ActiveRecord
+ module Generators
+ class ModelGenerator < Base
+ argument :attributes, :type => :hash, :default => {}, :banner => "field:type, field:type"
+
+ check_class_collision
+
+ # TODO Add parent support
+
+ # TODO Add DEFAULTS support
+ class_option :skip_timestamps, :type => :boolean, :default => false,
+ :desc => "Don't add timestamps to the migration file"
+
+ # TODO Make this a invoke_if
+ # TODO Add DEFAULTS support
+ class_option :skip_migration, :type => :boolean, :default => false,
+ :desc => "Don't generate a migration file"
+
+ def create_model_file
+ template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
+ end
+
+ # TODO Add migration support
+ def create_migration_file
+# unless options[:skip_migration]
+# m.migration_template 'migration.rb', 'db/migrate', :assigns => {
+# :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
+# }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
+# end
+ end
+ end
+ end
+end
diff --git a/railties/lib/generators/active_record/model/templates/migration.rb b/railties/lib/generators/active_record/model/templates/migration.rb
new file mode 100644
index 0000000000..382fd1156e
--- /dev/null
+++ b/railties/lib/generators/active_record/model/templates/migration.rb
@@ -0,0 +1,16 @@
+class <%= migration_name %> < ActiveRecord::Migration
+ def self.up
+ create_table :<%= table_name %> do |t|
+<% for attribute in attributes -%>
+ t.<%= attribute.type %> :<%= attribute.name %>
+<% end -%>
+<% unless options[:skip_timestamps] %>
+ t.timestamps
+<% end -%>
+ end
+ end
+
+ def self.down
+ drop_table :<%= table_name %>
+ end
+end
diff --git a/railties/lib/generators/active_record/model/templates/model.rb b/railties/lib/generators/active_record/model/templates/model.rb
new file mode 100644
index 0000000000..0656b06dfe
--- /dev/null
+++ b/railties/lib/generators/active_record/model/templates/model.rb
@@ -0,0 +1,5 @@
+class <%= class_name %> < ActiveRecord::Base
+<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
+ belongs_to :<%= attribute.name %>
+<% end -%>
+end
diff --git a/railties/lib/generators/base.rb b/railties/lib/generators/base.rb
index a29bda6afd..e5e2c03b48 100644
--- a/railties/lib/generators/base.rb
+++ b/railties/lib/generators/base.rb
@@ -96,7 +96,7 @@ module Rails
class_option name, options.merge!(:type => :default, :default => DEFAULTS[name])
class_eval <<-METHOD, __FILE__, __LINE__
- def invoke_#{name}
+ def invoke_for_#{name}
return unless options[#{name.inspect}]
klass = Rails::Generators.find_by_namespace(options[#{name.inspect}],
@@ -143,10 +143,11 @@ module Rails
options = default_options.dup
options[:desc] ||= "Indicates when to use #{name.to_s.humanize}"
+ # TODO Reverse --name to --skip-name if default is given.
class_option name, options.merge!(:type => :boolean, :default => DEFAULTS[name] || false)
class_eval <<-METHOD, __FILE__, __LINE__
- def invoke_#{name}
+ def invoke_if_#{name}
return unless options[#{name.inspect}]
klass = Rails::Generators.find_by_namespace(#{name.inspect},
diff --git a/railties/lib/generators/generated_attribute.rb b/railties/lib/generators/generated_attribute.rb
index 0ead945281..7cd1fed8a4 100644
--- a/railties/lib/generators/generated_attribute.rb
+++ b/railties/lib/generators/generated_attribute.rb
@@ -1,11 +1,10 @@
module Rails
module Generators
class GeneratedAttribute
- attr_accessor :name, :type, :column
+ attr_accessor :name, :type
def initialize(name, type)
@name, @type = name, type.to_sym
- @column = ActiveRecord::ConnectionAdapters::Column.new(@name, nil, @type)
end
def field_type
diff --git a/railties/lib/generators/named_base.rb b/railties/lib/generators/named_base.rb
index 6ff5bb7644..4a5aba38d8 100644
--- a/railties/lib/generators/named_base.rb
+++ b/railties/lib/generators/named_base.rb
@@ -69,8 +69,8 @@ module Rails
# Convert attributes hash into an array with GeneratedAttribute objects.
#
def parse_attributes! #:nodoc:
- attributes.map! do |name, type|
- Rails::Generator::GeneratedAttribute.new(name, type)
+ self.attributes = (attributes || {}).map do |name, type|
+ Rails::Generators::GeneratedAttribute.new(name, type)
end
end
diff --git a/railties/lib/generators/rails/app/templates/config/environment.rb b/railties/lib/generators/rails/app/templates/config/environment.rb
index d1080cb529..84c5abf1e9 100644
--- a/railties/lib/generators/rails/app/templates/config/environment.rb
+++ b/railties/lib/generators/rails/app/templates/config/environment.rb
@@ -26,14 +26,14 @@ Rails::Initializer.run do |config|
# Skip frameworks you're not going to use. To use Rails without a database,
# you must remove the Active Record framework.
-<%- if options[:skip_activerecord] -%>
+<% if options[:skip_activerecord] -%>
config.frameworks -= [ :active_record ]
-<%- else -%>
+<% else -%>
# config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
# Activate observers that should always be running
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
-<%- end -%>
+<% end -%>
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names.
diff --git a/railties/lib/generators/rails/model/USAGE b/railties/lib/generators/rails/model/USAGE
new file mode 100644
index 0000000000..73c8b69153
--- /dev/null
+++ b/railties/lib/generators/rails/model/USAGE
@@ -0,0 +1,27 @@
+Description:
+ Stubs out a new model. Pass the model name, either CamelCased or
+ under_scored, and an optional list of attribute pairs as arguments.
+
+ Attribute pairs are field:type arguments specifying the
+ model's attributes. Timestamps are added by default, so you don't have to
+ specify them by hand as 'created_at:datetime updated_at:datetime'.
+
+ You don't have to think up every attribute up front, but it helps to
+ sketch out a few so you can start working with the model immediately.
+
+ This generator invokes your configured ORM and test framework, which
+ defaults to ActiveRecord and TestUnit.
+
+Examples:
+ `./script/generate model account`
+
+ For ActiveRecord and TestUnit it creates:
+
+ Model: app/models/account.rb
+ Test: test/unit/account_test.rb
+ Fixtures: test/fixtures/accounts.yml
+ Migration: db/migrate/XXX_add_accounts.rb
+
+ `./script/generate model post title:string body:text published:boolean`
+
+ Creates a Post model with a string title, text body, and published flag.
diff --git a/railties/lib/generators/rails/model/model_generator.rb b/railties/lib/generators/rails/model/model_generator.rb
new file mode 100644
index 0000000000..7a732bfd0d
--- /dev/null
+++ b/railties/lib/generators/rails/model/model_generator.rb
@@ -0,0 +1,8 @@
+module Rails
+ module Generators
+ class ModelGenerator < NamedBase
+ argument :attributes, :type => :hash, :default => {}, :banner => "field:type, field:type"
+ invoke_for :orm, :test_framework
+ end
+ end
+end
diff --git a/railties/lib/generators/test_unit/model/model_generator.rb b/railties/lib/generators/test_unit/model/model_generator.rb
new file mode 100644
index 0000000000..901ed70468
--- /dev/null
+++ b/railties/lib/generators/test_unit/model/model_generator.rb
@@ -0,0 +1,24 @@
+module TestUnit
+ module Generators
+ class ModelGenerator < Base
+ argument :attributes, :type => :hash, :default => {}, :banner => "field:type, field:type"
+
+ check_class_collision :suffix => "Test"
+
+ # TODO Add DEFAULTS support
+ class_option :skip_fixture, :type => :boolean, :default => false,
+ :desc => "Don't generate a fixture file"
+
+ def create_test_file
+ template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
+ end
+
+ # TODO Add fixture replacement support
+ def create_fixture_file
+ unless options[:skip_fixture]
+ template 'fixtures.yml', File.join('test/fixtures', "#{table_name}.yml")
+ end
+ end
+ end
+ end
+end
diff --git a/railties/lib/generators/test_unit/model/templates/fixtures.yml b/railties/lib/generators/test_unit/model/templates/fixtures.yml
new file mode 100644
index 0000000000..c21035113e
--- /dev/null
+++ b/railties/lib/generators/test_unit/model/templates/fixtures.yml
@@ -0,0 +1,19 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+<% unless attributes.empty? -%>
+one:
+<% for attribute in attributes -%>
+ <%= attribute.name %>: <%= attribute.default %>
+<% end -%>
+
+two:
+<% for attribute in attributes -%>
+ <%= attribute.name %>: <%= attribute.default %>
+<% end -%>
+<% else -%>
+# one:
+# column: value
+#
+# two:
+# column: value
+<% end -%>
diff --git a/railties/lib/generators/test_unit/model/templates/unit_test.rb b/railties/lib/generators/test_unit/model/templates/unit_test.rb
new file mode 100644
index 0000000000..3e0bc29d3a
--- /dev/null
+++ b/railties/lib/generators/test_unit/model/templates/unit_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class <%= class_name %>Test < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
diff --git a/railties/test/generators/controller_generator_test.rb b/railties/test/generators/controller_generator_test.rb
index e10580f40f..d0c963a9ac 100644
--- a/railties/test/generators/controller_generator_test.rb
+++ b/railties/test/generators/controller_generator_test.rb
@@ -20,6 +20,8 @@ class ControllerGeneratorTest < GeneratorsTestCase
assert_match /The name 'ObjectController' is either already used in your application or reserved/, content
end
+ # No need to spec content since it's already spec'ed on helper generator.
+ #
def test_invokes_helper
run_generator
assert_file "app/helpers/account_helper.rb"
diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb
index 1fcfdaebb9..29ff306551 100644
--- a/railties/test/generators/generators_test_helper.rb
+++ b/railties/test/generators/generators_test_helper.rb
@@ -34,15 +34,17 @@ class GeneratorsTestCase < Test::Unit::TestCase
end
alias :silence :capture
- def assert_file(relative, content=nil)
+ def assert_file(relative, *contents)
absolute = File.join(destination_root, relative)
assert File.exists?(absolute)
- case content
- when String
- assert_equal content, File.read(absolute)
- when Regexp
- assert_match content, File.read(absolute)
+ contents.each do |content|
+ case content
+ when String
+ assert_equal content, File.read(absolute)
+ when Regexp
+ assert_match content, File.read(absolute)
+ end
end
end
diff --git a/railties/test/generators/helper_generator_test.rb b/railties/test/generators/helper_generator_test.rb
index 9b2f277f54..b2533e5315 100644
--- a/railties/test/generators/helper_generator_test.rb
+++ b/railties/test/generators/helper_generator_test.rb
@@ -33,6 +33,25 @@ class HelperGeneratorTest < GeneratorsTestCase
assert_match /The name 'AnotherObjectHelperTest' is either already used in your application or reserved/, content
end
+ def test_namespaced_and_not_namespaced_helpers
+ run_generator ["products"]
+
+ # We have to require the generated helper to show the problem because
+ # the test helpers just check for generated files and contents but
+ # do not actually load them. But they have to be loaded (as in a real environment)
+ # to make the second generator run fail
+ require "#{destination_root}/app/helpers/products_helper"
+
+ assert_nothing_raised do
+ begin
+ run_generator ["admin::products"]
+ ensure
+ # cleanup
+ Object.send(:remove_const, :ProductsHelper)
+ end
+ end
+ end
+
protected
def run_generator(args=["admin"])
diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb
index 710847587d..3e5dc60361 100644
--- a/railties/test/generators/mailer_generator_test.rb
+++ b/railties/test/generators/mailer_generator_test.rb
@@ -18,9 +18,9 @@ class MailerGeneratorTest < GeneratorsTestCase
def test_invokes_default_test_framework
run_generator
- assert_file "test/unit/notifier_test.rb"
- assert_file "test/fixtures/notifier/foo"
- assert_file "test/fixtures/notifier/bar"
+ assert_file "test/unit/notifier_test.rb", /class NotifierTest < ActionMailer::TestCase/
+ assert_file "test/fixtures/notifier/foo", /app\/views\/notifier\/foo/
+ assert_file "test/fixtures/notifier/bar", /app\/views\/notifier\/bar/
end
def test_invokes_default_template_engine
diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb
new file mode 100644
index 0000000000..425c4f581a
--- /dev/null
+++ b/railties/test/generators/model_generator_test.rb
@@ -0,0 +1,72 @@
+require 'abstract_unit'
+require 'generators/generators_test_helper'
+require 'generators/active_record/model/model_generator'
+require 'generators/rails/model/model_generator'
+require 'generators/test_unit/model/model_generator'
+
+class ModelGeneratorTest < GeneratorsTestCase
+
+ def test_invokes_default_orm
+ run_generator
+ assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/
+ end
+
+ def test_invokes_default_test_framework
+ run_generator
+ assert_file "test/unit/account_test.rb", /class AccountTest < ActiveSupport::TestCase/
+ assert_file "test/fixtures/accounts.yml", /name: MyString/, /age: 1/
+ end
+
+ def test_fixtures_are_skipped
+ run_generator ["account", "--skip-fixture"]
+ assert_no_file "test/fixtures/accounts.yml"
+ end
+
+ def test_check_class_collision
+ content = capture(:stderr){ run_generator ["object"] }
+ assert_match /The name 'Object' is either already used in your application or reserved/, content
+ end
+
+# def test_model_skip_migration_skips_migration
+# run_generator('model', %w(Product name:string --skip-migration))
+
+# assert_generated_model_for :product
+# assert_generated_fixtures_for :products
+# assert_skipped_migration :create_products
+# end
+
+# def test_model_with_attributes_generates_resources_with_attributes
+# run_generator('model', %w(Product name:string supplier_id:integer created_at:timestamp))
+
+# assert_generated_model_for :product
+# assert_generated_fixtures_for :products
+# assert_generated_migration :create_products do |t|
+# assert_generated_column t, :name, :string
+# assert_generated_column t, :supplier_id, :integer
+# assert_generated_column t, :created_at, :timestamp
+# end
+# end
+
+# def test_model_with_reference_attributes_generates_belongs_to_associations
+# run_generator('model', %w(Product name:string supplier:references))
+
+# assert_generated_model_for :product do |body|
+# assert body =~ /^\s+belongs_to :supplier/, "#{body.inspect} should contain 'belongs_to :supplier'"
+# end
+# end
+
+# def test_model_with_belongs_to_attributes_generates_belongs_to_associations
+# run_generator('model', %w(Product name:string supplier:belongs_to))
+
+# assert_generated_model_for :product do |body|
+# assert body =~ /^\s+belongs_to :supplier/, "#{body.inspect} should contain 'belongs_to :supplier'"
+# end
+# end
+
+ protected
+
+ def run_generator(args=["Account", "name:string", "age:integer"])
+ silence(:stdout) { Rails::Generators::ModelGenerator.start args, :root => destination_root }
+ end
+
+end
diff --git a/railties/test/generators/observer_generator_test.rb b/railties/test/generators/observer_generator_test.rb
index 780c854d85..e2b027028a 100644
--- a/railties/test/generators/observer_generator_test.rb
+++ b/railties/test/generators/observer_generator_test.rb
@@ -6,19 +6,19 @@ require 'generators/test_unit/observer/observer_generator'
class ObserverGeneratorTest < GeneratorsTestCase
- def test_observer_skeleton_is_created
+ def test_invokes_default_orm
run_generator
assert_file "app/models/account_observer.rb", /class AccountObserver < ActiveRecord::Observer/
end
- def test_observer_with_class_path_skeleton_is_created
+ def test_invokes_default_orm_with_class_path
run_generator ["admin/account"]
assert_file "app/models/admin/account_observer.rb", /class Admin::AccountObserver < ActiveRecord::Observer/
end
def test_invokes_default_test_framework
run_generator
- assert_file "test/unit/account_observer_test.rb"
+ assert_file "test/unit/account_observer_test.rb", /class AccountObserverTest < ActiveSupport::TestCase/
end
def test_logs_if_the_test_framework_cannot_be_found