Permalink
Browse files

Clone Rails model generator, add first round of model-plus improvements

  • Loading branch information...
1 parent 4408edd commit 3604a983df20f4951a84fb2dc7f29b137923864b @ffmike ffmike committed Dec 21, 2008
@@ -1,8 +1,31 @@
Description:
- Explain the generator
+ Stubs out a new model. Pass the model name, either CamelCased or
+ under_scored, and an optional list of attribute pairs as arguments.
-Example:
- ./script/generate model_plus Thing
+ Attribute pairs are column_name:sql_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'.
- This will create:
- what/will/it/create
+ 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.
+
+ If you include an attribute with a type of :references, :belongs_to,
+ :has_many, :has_one, or :has_and_belongs_to_many, the model will contain
+ the appropriate association declaration.
+
+ This generates a model class in app/models, a unit test in test/unit,
+ a test fixture in test/fixtures/singular_name.yml, and a migration in
+ db/migrate.
+
+Examples:
+ `./script/generate model account`
+
+ creates an Account model, test, fixture, and migration:
+ 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.
@@ -1,8 +1,57 @@
+module Rails
+ module Generator
+ class GeneratedAttribute
+
+ def referenced_by?
+ [ :has_one, :has_many, :has_and_belongs_to_many ].include?(self.type)
+ end
+
+ end
+ end
+end
+
class ModelPlusGenerator < Rails::Generator::NamedBase
+ default_options :skip_timestamps => false, :skip_migration => false, :skip_fixture => false
+
def manifest
record do |m|
- # m.directory "lib"
- # m.template 'README', "README"
+ # Check for class naming collisions.
+ m.class_collisions class_name, "#{class_name}Test"
+
+ # Model, test, and fixture directories.
+ m.directory File.join('app/models', class_path)
+ m.directory File.join('test/unit', class_path)
+ m.directory File.join('test/fixtures', class_path)
+
+ # Model class, unit test, and fixtures.
+ m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
+ m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
+
+ unless options[:skip_fixture]
+ m.template 'fixtures.yml', File.join('test/fixtures', "#{table_name}.yml")
+ end
+
+ 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
+
+ protected
+ def banner
+ "Usage: #{$0} #{spec.name} ModelName [field:type, field:type]"
+ end
+
+ def add_options!(opt)
+ opt.separator ''
+ opt.separator 'Options:'
+ opt.on("--skip-timestamps",
+ "Don't add timestamps to the migration file for this model") { |v| options[:skip_timestamps] = v }
+ opt.on("--skip-migration",
+ "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
+ opt.on("--skip-fixture",
+ "Don't generation a fixture file for this model") { |v| options[:skip_fixture] = v}
+ end
end
@@ -0,0 +1,23 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+<% unless attributes.empty? -%>
+one:
+<% for attribute in attributes -%>
+ <% unless attribute.referenced_by? %>
+ <%= attribute.name %>: <%= attribute.default %>
+ <% end -%>
+<% end -%>
+
+two:
+<% for attribute in attributes -%>
+ <% unless attribute.referenced_by? %>
+ <%= attribute.name %>: <%= attribute.default %>
+ <% end -%>
+<% end -%>
+<% else -%>
+# one:
+# column: value
+#
+# two:
+# column: value
+<% end -%>
@@ -0,0 +1,18 @@
+class <%= migration_name %> < ActiveRecord::Migration
+ def self.up
+ create_table :<%= table_name %> do |t|
+<% for attribute in attributes -%>
+ <% unless attribute.referenced_by? %>
+ t.<%= attribute.type %> :<%= attribute.name %>
+ <% end -%>
+<% end -%>
+<% unless options[:skip_timestamps] %>
+ t.timestamps
+<% end -%>
+ end
+ end
+
+ def self.down
+ drop_table :<%= table_name %>
+ end
+end
@@ -0,0 +1,8 @@
+class <%= class_name %> < ActiveRecord::Base
+<% attributes.select(&:reference?).each do |attribute| -%>
+ belongs_to :<%= attribute.name %>
+<% end -%>
+<% attributes.select(&:referenced_by?).each do |attribute| -%>
+ <%= attribute.type %> :<%= attribute.name %>
+<% end -%>
+end
@@ -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
View
@@ -1 +1 @@
-# Include hook code here
+# Include hook code here

0 comments on commit 3604a98

Please sign in to comment.