rspec_for_generators 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +111 -0
  5. data/Rakefile +48 -0
  6. data/VERSION +1 -0
  7. data/lib/generators/demo/demo_generator.rb +91 -0
  8. data/lib/rspec_for_generators.rb +11 -0
  9. data/lib/rspec_for_generators/fixtures/routes.rb +2 -0
  10. data/lib/rspec_for_generators/generator_spec_helper.rb +73 -0
  11. data/lib/rspec_for_generators/main.rb +7 -0
  12. data/lib/rspec_for_generators/matchers/content/all.rb +1 -0
  13. data/lib/rspec_for_generators/matchers/content/have_class.rb +36 -0
  14. data/lib/rspec_for_generators/matchers/content/have_method.rb +49 -0
  15. data/lib/rspec_for_generators/matchers/content/have_module.rb +34 -0
  16. data/lib/rspec_for_generators/matchers/content/include_module.rb +36 -0
  17. data/lib/rspec_for_generators/matchers/content/inherit_from.rb +33 -0
  18. data/lib/rspec_for_generators/matchers/file/all.rb +1 -0
  19. data/lib/rspec_for_generators/matchers/file/generate_file.rb +73 -0
  20. data/lib/rspec_for_generators/matchers/file/generate_migration.rb +43 -0
  21. data/lib/rspec_for_generators/matchers/helpers/content.rb +20 -0
  22. data/lib/rspec_for_generators/matchers/helpers/file.rb +28 -0
  23. data/lib/rspec_for_generators/rails_helpers/all.rb +6 -0
  24. data/lib/rspec_for_generators/rails_helpers/rails_app.rb +55 -0
  25. data/lib/rspec_for_generators/rails_helpers/rails_controller.rb +34 -0
  26. data/lib/rspec_for_generators/rails_helpers/rails_helper.rb +36 -0
  27. data/lib/rspec_for_generators/rails_helpers/rails_mailer.rb +29 -0
  28. data/lib/rspec_for_generators/rails_helpers/rails_model.rb +94 -0
  29. data/lib/rspec_for_generators/rails_helpers/rails_view.rb +29 -0
  30. data/lib/rspec_for_generators/rails_spec_helper.rb +17 -0
  31. data/lib/rspec_for_generators/rspec_test_case.rb +26 -0
  32. data/rspec_for_generators.gemspec +96 -0
  33. data/spec/rspec_for_generators/rspec_for_generators_spec.rb +43 -0
  34. data/spec/spec.opts +1 -0
  35. data/spec/spec_helper.rb +10 -0
  36. data/tmp/rails/config/routes.rb +2 -0
  37. data/wiki/Custom Rails 3 Generators.textile +110 -0
  38. metadata +195 -0
@@ -0,0 +1,29 @@
1
+ module RSpec
2
+ module Rails
3
+ module Mailer
4
+ def create_mailer name, content
5
+ file = mailer_file_name(name)
6
+ unless File.exist?(file)
7
+ FileUtils.mkdir_p File.dirname(file)
8
+ File.open(file, 'w') do |f|
9
+ f.puts content
10
+ end
11
+ end
12
+ end
13
+
14
+ def remove_mailer name
15
+ file = mailer_file_name(name)
16
+ FileUtils.rm_f(file) if File.exist?(file)
17
+ end
18
+
19
+ def remove_mailers *names
20
+ names.each{|name| remove_mailer name }
21
+ end
22
+
23
+ def mailer_file_name name
24
+ File.join(::Rails.root, "app/mailers/#{name}.rb")
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,94 @@
1
+ module RSpec
2
+ module Rails
3
+ module Model
4
+ module ActiveRecord
5
+ def file_content name
6
+ %Q{class #{name.camelize} < ActiveRecord::Base
7
+ end}
8
+ end
9
+ end
10
+
11
+ module MongoMapper
12
+ def file_content name
13
+ %Q{class #{name.camelize}
14
+ include MongoMapper::Document
15
+ end}
16
+ end
17
+
18
+ def field name, type = nil
19
+ return "key :#{name}, #{type}" if type
20
+ "key :#{name}"
21
+ end
22
+ end
23
+
24
+ module Mongoid
25
+ def file_content name
26
+ %Q{class #{name.camelize}
27
+ include Mongoid::Document
28
+ end}
29
+ end
30
+
31
+ def field name, type = nil
32
+ return "field :#{name}, :type => #{type}" if type
33
+ "field :#{name}"
34
+ end
35
+ end
36
+
37
+ module DataMapper
38
+ def file_content name
39
+ %Q{class #{name.camelize}
40
+ include DataMapper::Resource
41
+ end}
42
+ end
43
+
44
+ def field name, type = nil
45
+ return "property :#{name}, #{type}" if type
46
+ "property :#{name}"
47
+ end
48
+ end
49
+
50
+ def set_orm orm
51
+ orm_module = case orm
52
+ when :active_record
53
+ ActiveRecord
54
+ when :data_mapper
55
+ DataMapper
56
+ when :mongo_mapper
57
+ MongoMapper
58
+ when :mongoid
59
+ Mongoid
60
+ end
61
+ include orm_module
62
+ end
63
+
64
+ def create_model name, &block
65
+ file = model_file_name(name)
66
+ unless File.exist?(file)
67
+ FileUtils.mkdir_p File.dirname(file)
68
+ File.open(file, 'w') do |f|
69
+ f.puts file_content(name)
70
+ yield f if block_given?
71
+ end
72
+ end
73
+ end
74
+
75
+ def remove_model name
76
+ file = model_file_name(name)
77
+ FileUtils.rm_f(file) if File.exist?(file)
78
+ end
79
+
80
+ def remove_models *names
81
+ names.each{|name| remove_model name }
82
+ end
83
+
84
+ def model_file_name name
85
+ File.join(::Rails.root, "app/models/#{name}.rb")
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ def model_helper_for orm
92
+ include RSpec::Rails::Model
93
+ set_orm orm
94
+ end
@@ -0,0 +1,29 @@
1
+ module RSpec
2
+ module Rails
3
+ module View
4
+ def create_view name, content
5
+ file = view_file_name(name)
6
+ unless File.exist?(file)
7
+ FileUtils.mkdir_p File.dirname(file)
8
+ File.open(file, 'w') do |f|
9
+ f.puts content
10
+ end
11
+ end
12
+ end
13
+
14
+ def remove_view name
15
+ file = view_file_name(name)
16
+ FileUtils.rm_f(file) if File.exist?(file)
17
+ end
18
+
19
+ def remove_views *names
20
+ names.each{|name| remove_view name }
21
+ end
22
+
23
+ def view_file_name name
24
+ File.join(::Rails.root, "app/views/#{name}.rb")
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ require 'rspec_for_generators/rails_helpers/all'
2
+
3
+ class TestApp < Rails::Application
4
+ raise StandardError, "You must define a location for Rails.config_root_dir" if !Rails.config_root_dir
5
+ config.root = Rails.config_root_dir
6
+ end
7
+
8
+ module Rails
9
+ def self.root
10
+ raise StandardError, "You must define a location for Rails.config_root_dir" if !Rails.config_root_dir
11
+ @root ||= File.expand_path(File.join(Rails.config_root_dir, '..', 'tmp', 'rails'))
12
+ end
13
+ end
14
+
15
+ Rails.application = TestApp
16
+ Rails.application.config.root = Rails.root
17
+
@@ -0,0 +1,26 @@
1
+ module RSpec
2
+ module Generators
3
+ class TestCase < ::Rails::Generators::TestCase
4
+ setup :prepare_destination
5
+ # setup :copy_routes
6
+ destination File.join(::Rails.root)
7
+
8
+ def initialize(test_method_name)
9
+ @method_name = test_method_name
10
+ @test_passed = true
11
+ @interrupted = false
12
+ routes_file = File.join(File.dirname(__FILE__), 'fixtures', 'routes.rb')
13
+ copy_routes routes_file
14
+ end
15
+
16
+ def copy_routes routes_file
17
+ routes = File.expand_path(routes_file)
18
+ raise ArgumentError, "No routes file exists at #{routes_file}" if !File.exist?(routes)
19
+ destination = File.join(::Rails.root, "config")
20
+ FileUtils.mkdir_p(destination) # create dir
21
+ FileUtils.cp routes, destination # copy
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,96 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rspec_for_generators}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kristian Mandrup"]
12
+ s.date = %q{2010-08-03}
13
+ s.description = %q{RSpec 2 matchers, helpers and utils to assist in writing generator specs}
14
+ s.email = %q{kmandrup@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.markdown",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/generators/demo/demo_generator.rb",
27
+ "lib/rspec_for_generators.rb",
28
+ "lib/rspec_for_generators/fixtures/routes.rb",
29
+ "lib/rspec_for_generators/generator_spec_helper.rb",
30
+ "lib/rspec_for_generators/main.rb",
31
+ "lib/rspec_for_generators/matchers/content/all.rb",
32
+ "lib/rspec_for_generators/matchers/content/have_class.rb",
33
+ "lib/rspec_for_generators/matchers/content/have_method.rb",
34
+ "lib/rspec_for_generators/matchers/content/have_module.rb",
35
+ "lib/rspec_for_generators/matchers/content/include_module.rb",
36
+ "lib/rspec_for_generators/matchers/content/inherit_from.rb",
37
+ "lib/rspec_for_generators/matchers/file/all.rb",
38
+ "lib/rspec_for_generators/matchers/file/generate_file.rb",
39
+ "lib/rspec_for_generators/matchers/file/generate_migration.rb",
40
+ "lib/rspec_for_generators/matchers/helpers/content.rb",
41
+ "lib/rspec_for_generators/matchers/helpers/file.rb",
42
+ "lib/rspec_for_generators/rails_helpers/all.rb",
43
+ "lib/rspec_for_generators/rails_helpers/rails_app.rb",
44
+ "lib/rspec_for_generators/rails_helpers/rails_controller.rb",
45
+ "lib/rspec_for_generators/rails_helpers/rails_helper.rb",
46
+ "lib/rspec_for_generators/rails_helpers/rails_mailer.rb",
47
+ "lib/rspec_for_generators/rails_helpers/rails_model.rb",
48
+ "lib/rspec_for_generators/rails_helpers/rails_view.rb",
49
+ "lib/rspec_for_generators/rails_spec_helper.rb",
50
+ "lib/rspec_for_generators/rspec_test_case.rb",
51
+ "rspec_for_generators.gemspec",
52
+ "spec/rspec_for_generators/rspec_for_generators_spec.rb",
53
+ "spec/spec.opts",
54
+ "spec/spec_helper.rb",
55
+ "tmp/rails/config/routes.rb",
56
+ "wiki/Custom Rails 3 Generators.textile"
57
+ ]
58
+ s.homepage = %q{http://github.com/kristianmandrup/rspec_for_generators}
59
+ s.rdoc_options = ["--charset=UTF-8"]
60
+ s.require_paths = ["lib"]
61
+ s.rubygems_version = %q{1.3.7}
62
+ s.summary = %q{RSpec 2 matchers, helpers and utils for writing generator specs}
63
+ s.test_files = [
64
+ "spec/rspec_for_generators/rspec_for_generators_spec.rb",
65
+ "spec/spec_helper.rb"
66
+ ]
67
+
68
+ if s.respond_to? :specification_version then
69
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
70
+ s.specification_version = 3
71
+
72
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
73
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta19"])
74
+ s.add_runtime_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
75
+ s.add_runtime_dependency(%q<rake>, [">= 0.8.7"])
76
+ s.add_runtime_dependency(%q<rails>, [">= 3.0.0.rc"])
77
+ s.add_runtime_dependency(%q<test-unit>, [">= 2.0.9"])
78
+ s.add_runtime_dependency(%q<require_all>, [">= 1.1.0"])
79
+ else
80
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta19"])
81
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
82
+ s.add_dependency(%q<rake>, [">= 0.8.7"])
83
+ s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
84
+ s.add_dependency(%q<test-unit>, [">= 2.0.9"])
85
+ s.add_dependency(%q<require_all>, [">= 1.1.0"])
86
+ end
87
+ else
88
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta19"])
89
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
90
+ s.add_dependency(%q<rake>, [">= 0.8.7"])
91
+ s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
92
+ s.add_dependency(%q<test-unit>, [">= 2.0.9"])
93
+ s.add_dependency(%q<require_all>, [">= 1.1.0"])
94
+ end
95
+ end
96
+
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'generators/demo/demo_generator'
3
+
4
+ describe 'model_generator' do
5
+ include RSpec::Rails::Model
6
+ include RSpec::Rails::Model::ActiveRecord
7
+
8
+ before :each do
9
+ RSpec::Generator.setup_generator 'model_generator' do
10
+ tests DemoGenerator
11
+ end
12
+ remove_model 'account'
13
+ end
14
+
15
+ after :each do
16
+ remove_model 'account'
17
+ end
18
+
19
+ it "should not work without an Account model file" do
20
+ RSpec::Generator.with_generator do |g|
21
+ name = 'account'
22
+ g.run_generator %w{account}
23
+ g.should_not generate_file name, :model
24
+ end
25
+ end
26
+
27
+ it "should decorate an existing Account model file with include Canable:Ables" do
28
+ RSpec::Generator.with_generator do |g|
29
+ name = 'account'
30
+ create_model name
31
+ g.run_generator %w{account}
32
+ g.should generate_file name, :model do |content|
33
+ content.should have_class name.camelize do |klass|
34
+ klass.should include_module 'Canable::Ables'
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+
43
+
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'rspec/autorun'
3
+
4
+ module Rails
5
+ def self.config_root_dir
6
+ File.dirname(__FILE__)
7
+ end
8
+ end
9
+
10
+ require 'rspec_for_generators'
@@ -0,0 +1,2 @@
1
+ TestApp.routes.draw do |map|
2
+ end
@@ -0,0 +1,110 @@
1
+ h2. Custom generators
2
+
3
+ <pre>
4
+ # my_plugin/lib/generators/install_generator.rb
5
+ module MyGem
6
+ class InstallGenerator < Rails::Generators::Base
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ # all public methods in here will be run in order
10
+ def add_my_initializer
11
+ template "initializer.rb", "config/initializers/my_gem_initializer.rb"
12
+ end
13
+ end
14
+ end
15
+ </pre>
16
+
17
+ If you inherit from NamedBase, you will have access to several inflections of the name passed in both in the body of your generator class, as well as in your templates.
18
+
19
+ * class_path and file_name are extracted from the name passed in. For instance, if the user passes in admin/posts, the class_path is admin and the file_name is posts
20
+ * file_path is the class_path and file_name joined by /
21
+ * class_name is the file_path, camelized. For instance, admin/posts becomes Admin::Posts
22
+ * human_name is the file_name, humanized. For instance, admin_posts would become Admin posts
23
+ * plural_name is the file_name, pluralized. For instance, post becomes posts
24
+ * i18n_scope is the file_path, with / replaced with .. For instance, admin/posts becomes admin.posts
25
+
26
+ <pre>
27
+ # my_plugin/lib/generators/templates/initializer.rb
28
+ Rails.application.configure do
29
+ # Uncomment this to turn on verbose mode
30
+ # config.my_gem.verbose = true
31
+ end
32
+ </pre>
33
+
34
+ h2. Overriding and replacing built-in Rails 3 generator
35
+
36
+ Simply inherit from the generator you want to replace and change the template source root to your own template directory
37
+ <pre>
38
+ require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
39
+ module Rails
40
+ module Generators
41
+ class RespondersControllerGenerator < ScaffoldControllerGenerator
42
+ def self.source_root
43
+ @_source_root ||= File.expand_path("templates", File.dirname(__FILE__))
44
+ end
45
+
46
+ protected
47
+
48
+ def flash?
49
+ !ApplicationController.responder.ancestors.include?(Responders::FlashResponder)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ </pre>
55
+
56
+ To hook a generator into Rails scaffold, all you need to do is to create a Rails::Railtie, which was also introduced in Rails 3.
57
+ The responders gem *railtie* is only a few lines of code:
58
+
59
+ <pre>
60
+ module Responders
61
+ class Railtie < ::Rails::Railtie
62
+ config.responders = ActiveSupport::OrderedOptions.new
63
+ config.generators.scaffold_controller = :responders_controller # important! signifies override by ResponderControllerGenerator
64
+
65
+ initializer "responders.flash_responder" do |app|
66
+ if app.config.responders.flash_keys
67
+ Responders::FlashResponder.flash_keys = app.config.responders.flash_keys
68
+ end
69
+ end
70
+ end
71
+ end
72
+ </pre>
73
+
74
+ The first line sets an instance of ActiveSupport::OrderedOptions at config.responders. This allows you to do the following inside your
75
+ Rails::Application at <code>config/application.rb</code>
76
+
77
+ <pre>
78
+ # config/application.rb
79
+ module Rails
80
+ class Blog < Rails::Application
81
+ config.responders.flash_keys = [:success, :failure]
82
+ end
83
+ end
84
+ </pre>
85
+
86
+ The second line is where the generator configuration happens. In case you are wondering, the config.generators object available in
87
+ Rails::Railtie is exactly the same object as the one in our Rails::Application.
88
+ That said, any gem can configure and manipulate the whole generators workflow in the application.
89
+
90
+ In Rails 3, gems are loaded before your application initializes. This is quite easy to notice if you look at the config/application.rb file:
91
+
92
+ <pre>
93
+ # config/application.rb
94
+
95
+ require File.expand_path('../boot', __FILE__)
96
+ require 'rails/all'
97
+
98
+ # If you have a Gemfile, require the gems listed there, including any gems
99
+ # you've limited to :test, :development, or :production.
100
+ Bundler.require(:default, Rails.env) if defined?(Bundler)
101
+
102
+ module Foo
103
+ class Application < Rails::Application
104
+ </pre>
105
+
106
+ By requiring gems earlier, Rails 3 can give more power to gems because we are sure that the final configuration value will be set by the application developer. The official API for configuring a Rails application is a Rails::Railtie as we just saw above. There is much more you can do inside a railtie, like configuring the middleware stack or any other Rails framework. Since all Rails frameworks (like Active Record, Active Resource, Action Pack…) are also railties, they are a great source of knowledge in case you are interested in learning more.
107
+
108
+ If we want to customize the _form partial generated on scaffold, all you need to do is to copy the _form partial template from Rails source code to lib/templates/erb/scaffold/_form.html.erb.
109
+
110
+ If you want to customize the show view, you just need to copy it as well, and this is true for all generators and all templates! This allows generators to grow and adapt as your application changes! For example, the simple form gem creates a template to change scaffold to use the simple_form_for instead of form_for.