michel-dry_scaffold 0.3.5

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 (74) hide show
  1. data/CHANGELOG.textile +51 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.textile +461 -0
  4. data/Rakefile +48 -0
  5. data/TODO.textile +40 -0
  6. data/bin/dmodel +3 -0
  7. data/bin/dry_model +3 -0
  8. data/bin/dry_scaffold +3 -0
  9. data/bin/dscaffold +3 -0
  10. data/config/scaffold.yml +34 -0
  11. data/generators/dmodel/dmodel_generator.rb +15 -0
  12. data/generators/dry_model/USAGE +9 -0
  13. data/generators/dry_model/dry_model_generator.rb +134 -0
  14. data/generators/dry_model/prototypes/active_record_migration.rb +17 -0
  15. data/generators/dry_model/prototypes/active_record_model.rb +9 -0
  16. data/generators/dry_model/prototypes/fixture_data/active_record_fixtures.yml +3 -0
  17. data/generators/dry_model/prototypes/fixture_data/factory_girl_factories.rb +4 -0
  18. data/generators/dry_model/prototypes/fixture_data/machinist_blueprints.rb +8 -0
  19. data/generators/dry_model/prototypes/tests/rspec/unit_test.rb +9 -0
  20. data/generators/dry_model/prototypes/tests/shoulda/unit_test.rb +20 -0
  21. data/generators/dry_model/prototypes/tests/test_unit/unit_test.rb +15 -0
  22. data/generators/dry_model/templates/models/active_record_migration.rb +23 -0
  23. data/generators/dry_model/templates/models/active_record_model.rb +15 -0
  24. data/generators/dry_model/templates/models/fixture_data/active_record_fixtures.yml +6 -0
  25. data/generators/dry_model/templates/models/fixture_data/factory_girl_factories.rb +5 -0
  26. data/generators/dry_model/templates/models/fixture_data/machinist_blueprints.rb +9 -0
  27. data/generators/dry_model/templates/models/tests/rspec/unit_test.rb +11 -0
  28. data/generators/dry_model/templates/models/tests/shoulda/unit_test.rb +23 -0
  29. data/generators/dry_model/templates/models/tests/test_unit/unit_test.rb +17 -0
  30. data/generators/dry_scaffold/USAGE +11 -0
  31. data/generators/dry_scaffold/dry_scaffold_generator.rb +415 -0
  32. data/generators/dry_scaffold/prototypes/controllers/action_controller.rb +135 -0
  33. data/generators/dry_scaffold/prototypes/controllers/inherited_resources_controller.rb +25 -0
  34. data/generators/dry_scaffold/prototypes/controllers/tests/rspec/functional_test.rb +57 -0
  35. data/generators/dry_scaffold/prototypes/controllers/tests/shoulda/functional_test.rb +99 -0
  36. data/generators/dry_scaffold/prototypes/controllers/tests/test_unit/functional_test.rb +70 -0
  37. data/generators/dry_scaffold/prototypes/helpers/helper.rb +3 -0
  38. data/generators/dry_scaffold/prototypes/helpers/tests/rspec/unit_test.rb +9 -0
  39. data/generators/dry_scaffold/prototypes/helpers/tests/shoulda/unit_test.rb +9 -0
  40. data/generators/dry_scaffold/prototypes/helpers/tests/test_unit/unit_test.rb +9 -0
  41. data/generators/dry_scaffold/prototypes/views/builder/index.atom.builder +20 -0
  42. data/generators/dry_scaffold/prototypes/views/builder/index.rss.builder +21 -0
  43. data/generators/dry_scaffold/prototypes/views/haml/_form.html.haml +3 -0
  44. data/generators/dry_scaffold/prototypes/views/haml/_item.html.haml +9 -0
  45. data/generators/dry_scaffold/prototypes/views/haml/edit.html.haml +10 -0
  46. data/generators/dry_scaffold/prototypes/views/haml/index.html.haml +17 -0
  47. data/generators/dry_scaffold/prototypes/views/haml/layout.html.haml +18 -0
  48. data/generators/dry_scaffold/prototypes/views/haml/new.html.haml +10 -0
  49. data/generators/dry_scaffold/prototypes/views/haml/show.html.haml +13 -0
  50. data/generators/dry_scaffold/templates/controllers/action_controller.rb +250 -0
  51. data/generators/dry_scaffold/templates/controllers/inherited_resources_controller.rb +36 -0
  52. data/generators/dry_scaffold/templates/controllers/tests/rspec/functional_test.rb +85 -0
  53. data/generators/dry_scaffold/templates/controllers/tests/shoulda/functional_test.rb +90 -0
  54. data/generators/dry_scaffold/templates/controllers/tests/test_unit/functional_test.rb +87 -0
  55. data/generators/dry_scaffold/templates/helpers/helper.rb +3 -0
  56. data/generators/dry_scaffold/templates/helpers/tests/rspec/unit_test.rb +9 -0
  57. data/generators/dry_scaffold/templates/helpers/tests/shoulda/unit_test.rb +9 -0
  58. data/generators/dry_scaffold/templates/helpers/tests/test_unit/unit_test.rb +9 -0
  59. data/generators/dry_scaffold/templates/views/builder/index.atom.builder +20 -0
  60. data/generators/dry_scaffold/templates/views/builder/index.rss.builder +21 -0
  61. data/generators/dry_scaffold/templates/views/haml/_form.html.haml +13 -0
  62. data/generators/dry_scaffold/templates/views/haml/_item.html.haml +10 -0
  63. data/generators/dry_scaffold/templates/views/haml/edit.html.haml +18 -0
  64. data/generators/dry_scaffold/templates/views/haml/index.html.haml +38 -0
  65. data/generators/dry_scaffold/templates/views/haml/layout.html.haml +19 -0
  66. data/generators/dry_scaffold/templates/views/haml/new.html.haml +18 -0
  67. data/generators/dry_scaffold/templates/views/haml/show.html.haml +13 -0
  68. data/generators/dscaffold/dscaffold_generator.rb +15 -0
  69. data/lib/dry_generator.rb +197 -0
  70. data/lib/dry_scaffold/tasks.rb +5 -0
  71. data/lib/setup_helper.rb +36 -0
  72. data/rails/init.rb +3 -0
  73. data/tasks/dry_scaffold.rake +95 -0
  74. metadata +132 -0
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ NAME = "michel-dry_scaffold"
6
+ SUMMARY = %Q{A DRYer scaffold generator for Rails. Generates dry semantic and standards compliant views, and dry RESTful controllers.}
7
+ HOMEPAGE = "http://github.com/michel/#{NAME}/tree/master"
8
+ AUTHOR = "Jonas Grimfelt,Michel de Graaf"
9
+ EMAIL = "grimen@gmail.com, michel@re-invention.nl"
10
+ SUPPORT_FILES = %w(README.textile TODO.textile CHANGELOG.textile)
11
+
12
+ begin
13
+ require 'jeweler'
14
+ Jeweler::Tasks.new do |gem|
15
+ gem.name = NAME
16
+ gem.summary = SUMMARY
17
+ gem.description = SUMMARY
18
+ gem.homepage = HOMEPAGE
19
+ gem.author = AUTHOR
20
+ gem.email = EMAIL
21
+
22
+ gem.require_paths = %w{lib}
23
+ gem.files = %w(MIT-LICENSE Rakefile) + SUPPORT_FILES + Dir.glob(File.join('{bin,config,generators,lib,rails,tasks}', '**', '*'))
24
+ gem.executables = %w(dscaffold dry_scaffold dmodel dry_model)
25
+ gem.extra_rdoc_files = SUPPORT_FILES
26
+ end
27
+ rescue LoadError
28
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
29
+ end
30
+
31
+ desc %Q{Run unit tests for "#{NAME}".}
32
+ task :default => :test
33
+
34
+ desc %Q{Run unit tests for "#{NAME}".}
35
+ Rake::TestTask.new(:test) do |test|
36
+ test.libs << 'lib'
37
+ test.pattern = 'test/**/*_test.rb'
38
+ test.verbose = true
39
+ end
40
+
41
+ desc %Q{Generate documentation for "#{NAME}".}
42
+ Rake::RDocTask.new(:rdoc) do |rdoc|
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = NAME
45
+ rdoc.options << '--line-numbers' << '--inline-source' << '--charset=UTF-8'
46
+ rdoc.rdoc_files.include(SUPPORT_FILES)
47
+ rdoc.rdoc_files.include(File.join('lib', '**', '*.rb'))
48
+ end
data/TODO.textile ADDED
@@ -0,0 +1,40 @@
1
+ h1. TODO
2
+
3
+ h2. Next
4
+
5
+ * Bug/Issue: InheritedResources functional testing issue.
6
+ * Feature: RSpec-templates?
7
+ * Optimization: Write even better functional tests for REST-actions. Goal: Killer-tests, i.e. "best practice"-tests. Suggestion: Routing, formats, ...
8
+ * Feature: Auto-detection of testing frameworks in working project.
9
+
10
+ h2. Maybe
11
+
12
+ * Feature: Check for overridden templates in: RAILS_ROOT/lib/dry_scaffold/templates/
13
+ * Feature: Handle belongs_to, i.e. specify MODEL --belongs-to PARENT_MODEL, which generates proper routes, proper before-filters if inherited_resources-controller, adding belongs_to-association in model, and correct form_for arguments.
14
+ * Feature: Builder for podcast-feed, similar to RSS/Atom-builders. http://wiki.github.com/radiant/radiant/host-a-podcast
15
+ * Tests: Generator tests. =P (Not very straightforward...)
16
+
17
+ h2. Issues
18
+
19
+ * Contact José regarding the InheritedResources-issue:
20
+
21
+ ActionController::RoutingError: parrot_url failed to generate from {:controller=>"parrots", :id=>#<Parrot id: nil, name: "Hello", created_at: "2009-07-21 18:53:25", updated_at: "2009-07-21 18:53:25">, :action=>"show"}, expected: {:controller=>"parrots", :action=>"show"}, diff: {:id=>#<Parrot id: nil, name: "Hello", created_at: "2009-07-21 18:53:25", updated_at: "2009-07-21 18:53:25">}
22
+ (eval):16:in `parrot_url'
23
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/url_helpers.rb:194:in `resource_url'
24
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/base_helpers.rb:311:in `send'
25
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/base_helpers.rb:311:in `parse_redirect_url'
26
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/base.rb:79:in `create'
27
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/respond_to.rb:301:in `call'
28
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/respond_to.rb:301:in `respond_any'
29
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/respond_to.rb:233:in `respond_to'
30
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/base_helpers.rb:283:in `respond_to_with_dual_blocks'
31
+ /opt/local/lib/ruby/gems/1.8/gems/josevalim-inherited_resources-0.7.3/lib/inherited_resources/base.rb:78:in `create'
32
+ haml (2.0.9) rails/./lib/sass/plugin/rails.rb:19:in `process'
33
+ /test/functional/donkeys_controller_test.rb:8:in `test_create'
34
+
35
+ test 'create' do
36
+ Donkey.any_instance.expects(:save).returns(true)
37
+ @donkey = donkeys(:basic)
38
+ post :create, :donkey => @donkey.attributes # <<<<<<<<<<<<< donkeys_controller_test.rb:8
39
+ assert_response :redirect
40
+ end
data/bin/dmodel ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ `ruby script/generate dmodel #{ARGV.join(' ')}`
data/bin/dry_model ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ `ruby script/generate dry_model #{ARGV.join(' ')}`
data/bin/dry_scaffold ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ `ruby script/generate dry_scaffold #{ARGV.join(' ')}`
data/bin/dscaffold ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ `ruby script/generate dscaffold #{ARGV.join(' ')}`
@@ -0,0 +1,34 @@
1
+ ---
2
+ dry_scaffold:
3
+ args:
4
+ actions: index,show,new,edit,create,update,destroy
5
+ formats: html,js,xml,json
6
+ options:
7
+ formtastic: true
8
+ resourceful: true
9
+ search: true
10
+ pagination: true
11
+ layout: false
12
+ views: true
13
+ helpers: true
14
+ tests: true
15
+ controller_tests: true
16
+ test_unit: true
17
+ shoulda: false
18
+ rspec: false
19
+ fixtures: true
20
+ fgirl: false
21
+ machinist: false
22
+ object_daddy: false
23
+ dry_model:
24
+ options:
25
+ migration: true
26
+ timestamps: true
27
+ tests: true
28
+ test_unit: true
29
+ shoulda: false
30
+ rspec: false
31
+ fixtures: true
32
+ fgirl: false
33
+ machinist: false
34
+ object_daddy: false
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'dry_model', 'dry_model_generator')
2
+
3
+ class DmodelGenerator < DryModelGenerator
4
+
5
+ def initialize(runtime_args, runtime_options = {})
6
+ super
7
+ # Make Rails look for templates within generator "dry_model" path
8
+ @source_root = options[:source] || File.join(spec.path, '..', 'dry_model', 'templates')
9
+ end
10
+
11
+ def usage_message
12
+ File.read(File.join(spec.path, '..', 'dry_model', 'USAGE')) rescue ''
13
+ end
14
+
15
+ end
@@ -0,0 +1,9 @@
1
+ NAME
2
+ dry_model/dmodel - A Rails scaffold generator that generates DRYer, cleaner, and more useful code - for models.
3
+
4
+ DESCRIPTION
5
+ A replacement for the Rails model generator - a part of the dry_generator toolset.
6
+
7
+ EXAMPLE
8
+ ./script/generate dmodel GoldFish name:string about:text _indexes:name --fgirl
9
+ ./script/generate dmodel Frog name:string about:text _indexes:name,name+about --fixtures
@@ -0,0 +1,134 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'dry_generator'))
2
+
3
+ class DryModelGenerator < DryGenerator
4
+
5
+ # Banner: Generator arguments and options.
6
+ BANNER_ARGS = [
7
+ "[_indexes:field,field+field,field,...]"
8
+ ].freeze
9
+ BANNER_OPTIONS = [
10
+ "[--skip-timestamps]",
11
+ "[--skip-migration]"
12
+ ].freeze
13
+
14
+ # Paths.
15
+ MODELS_PATH = File.join('app', 'models').freeze
16
+ MIGRATIONS_PATH = File.join('db', 'migrate').freeze
17
+
18
+ attr_reader :indexes,
19
+ :references
20
+
21
+ def initialize(runtime_args, runtime_options = {})
22
+ super(runtime_args, runtime_options)
23
+
24
+ @attributes ||= []
25
+ args_for_model = []
26
+
27
+ @args.each do |arg|
28
+ arg_entities = arg.split(':')
29
+ if arg =~ /^#{NON_ATTR_ARG_KEY_PREFIX}/
30
+ if arg =~ /^#{NON_ATTR_ARG_KEY_PREFIX}index/
31
+ arg_indexes = arg_entities[1].split(',').compact.uniq
32
+ @indexes = arg_indexes.collect do |index|
33
+ if index =~ /\+/
34
+ index.split('+').collect { |i| i.downcase.to_sym }
35
+ else
36
+ index.downcase.to_sym
37
+ end
38
+ end
39
+ end
40
+ else
41
+ @attributes << Rails::Generator::GeneratedAttribute.new(*arg_entities)
42
+ args_for_model << arg
43
+ end
44
+ end
45
+
46
+ @args = args_for_model
47
+ @references = attributes.select(&:reference?)
48
+ @options = DEFAULT_OPTIONS.merge(options)
49
+ end
50
+
51
+ def manifest
52
+ record do |m|
53
+ # Check for class naming collisions.
54
+ m.class_collisions class_name, "#{class_name}Test"
55
+
56
+ # Model.
57
+ m.directory File.join(MODELS_PATH, class_path)
58
+ m.template File.join('models', 'active_record_model.rb'),
59
+ File.join(MODELS_PATH, class_path, "#{file_name}.rb")
60
+
61
+ # Model Tests.
62
+ unless options[:skip_tests]
63
+ model_tests_path = File.join(TEST_PATHS[test_framework], UNIT_TESTS_PATH[test_framework])
64
+ m.directory File.join(model_tests_path, class_path)
65
+ m.template File.join('models', 'tests', "#{test_framework}", 'unit_test.rb'),
66
+ File.join(model_tests_path, class_path, "#{file_name}_#{TEST_POST_FIX[test_framework]}.rb")
67
+
68
+ # Fixtures/Factories.
69
+ if options[:fixtures]
70
+ fixtures_path = File.join(TEST_PATHS[test_framework], 'fixtures')
71
+ m.directory File.join(fixtures_path, class_path)
72
+ m.template File.join('models', 'fixture_data', 'active_record_fixtures.yml'),
73
+ File.join(fixtures_path, class_path, "#{table_name}.yml")
74
+ end
75
+ if options[:factory_girl]
76
+ factory_girl_path = File.join(TEST_PATHS[test_framework], 'factories')
77
+ m.directory File.join(factory_girl_path, class_path)
78
+ m.template File.join('models', 'fixture_data', 'factory_girl_factories.rb'),
79
+ File.join(factory_girl_path, class_path, "#{plural_name}.rb")
80
+ end
81
+ if options[:machinist]
82
+ machinist_path = File.join(TEST_PATHS[test_framework], 'blueprints')
83
+ m.directory File.join(machinist_path, class_path)
84
+ m.template File.join('models', 'fixture_data', 'machinist_blueprints.rb'),
85
+ File.join(machinist_path, class_path, "#{plural_name}.rb")
86
+ end
87
+ # NOTE: :object_daddy handled in model
88
+ end
89
+
90
+ # Migration.
91
+ unless options[:skip_migration]
92
+ m.migration_template File.join('models', 'active_record_migration.rb'), MIGRATIONS_PATH,
93
+ :assigns => {:migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"},
94
+ :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
95
+ end
96
+ end
97
+ end
98
+
99
+ protected
100
+
101
+ def add_options!(opt)
102
+ super(opt)
103
+
104
+ opt.separator ' '
105
+ opt.separator 'Model Options:'
106
+
107
+ opt.on("--skip-timestamps", "Don't add timestamps to the migration file.") do |v|
108
+ options[:skip_timestamps] = v
109
+ end
110
+
111
+ opt.on("--skip-migration", "Skip generation of migration file.") do |v|
112
+ options[:skip_migration] = v
113
+ end
114
+
115
+ opt.on("--skip-tests", "Skip generation of tests.") do |v|
116
+ options[:skip_tests] = v
117
+ end
118
+
119
+ opt.separator ' '
120
+ end
121
+
122
+ def banner_args
123
+ [BANNER_ARGS, super].flatten.join(' ')
124
+ end
125
+
126
+ def banner_options
127
+ [BANNER_OPTIONS, super].flatten.join(' ')
128
+ end
129
+
130
+ def banner
131
+ [super, banner_args, banner_options].join(' ')
132
+ end
133
+
134
+ end
@@ -0,0 +1,17 @@
1
+ class CreateDucks < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :resources, :force => true do |t|
4
+ t.string :name
5
+ t.text :description
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :resources, :name
11
+ add_index :resources, [:name, :description]
12
+ end
13
+
14
+ def self.down
15
+ drop_table :resources
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ class Duck < ActiveRecord::Base
2
+
3
+ belongs_to :owner
4
+
5
+ # object_daddy
6
+ generator_for(:name) { "AString" }
7
+ generator_for(:description) { "SomeText" }
8
+
9
+ end
@@ -0,0 +1,3 @@
1
+ default:
2
+ name: "AString"
3
+ description: "SomeText"
@@ -0,0 +1,4 @@
1
+ Factory.define :duck, :class => Duck do |f|
2
+ f.name "AString"
3
+ f.description "SomeText"
4
+ end
@@ -0,0 +1,8 @@
1
+ Sham.define do
2
+
3
+ end
4
+
5
+ Resource.blueprint do
6
+ name { "AString" }
7
+ description { "SomeText" }
8
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe DuckTest do
4
+ fixtures :ducks
5
+
6
+ it "should be valid" do
7
+ DuckTest.new.should be_valid
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class DuckTest < ActiveRecord::TestCase
4
+
5
+ fixtures :ducks
6
+
7
+ should_have_db_column :name
8
+ should_have_db_column :description
9
+
10
+ context "A test context" do
11
+ setup do
12
+
13
+ end
14
+
15
+ should 'test something' do
16
+ assert true
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class DuckTest < ActiveRecord::TestCase
4
+
5
+ fixtures :ducks
6
+
7
+ setup do
8
+
9
+ end
10
+
11
+ test 'something' do
12
+ assert true
13
+ end
14
+
15
+ end
@@ -0,0 +1,23 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= table_name %> do |t|
4
+ <% attributes.each do |attribute| -%>
5
+ t.<%= attribute.type %> :<%= attribute.name %>
6
+ <% end -%>
7
+
8
+ <% unless options[:skip_timestamps] -%>
9
+ t.timestamps
10
+ <% end -%>
11
+ end
12
+ <% unless indexes.blank? -%>
13
+
14
+ <% indexes.each do |index| -%>
15
+ add_index :<%= table_name %>, <%= index.is_a?(Array) ? "[:#{index.join(', :')}]" : ":#{index}" %>
16
+ <% end -%>
17
+ <% end -%>
18
+ end
19
+
20
+ def self.down
21
+ drop_table :<%= table_name %>
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ class <%= class_name %> < ActiveRecord::Base
2
+
3
+ <% unless references.empty? -%>
4
+ <% references.each do |attribute| -%>
5
+ belongs_to :<%= attribute.name %>
6
+ <% end -%>
7
+
8
+ <% end -%>
9
+ <% if options[:object_daddy] -%>
10
+ <% attributes.each do |attribute| -%>
11
+ generator_for(:<%= attribute.name %>) { <%= attribute.default_for_factory %> }
12
+ <% end -%>
13
+
14
+ <% end -%>
15
+ end