redmint_composer 2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/README.textile +10 -0
  3. data/bin/redmint_composer +7 -0
  4. data/lib/rails_wizard.rb +7 -0
  5. data/lib/rails_wizard/command.rb +204 -0
  6. data/lib/rails_wizard/config.rb +88 -0
  7. data/lib/rails_wizard/diagnostics.rb +58 -0
  8. data/lib/rails_wizard/recipe.rb +114 -0
  9. data/lib/rails_wizard/recipes.rb +56 -0
  10. data/lib/rails_wizard/template.rb +111 -0
  11. data/recipes/admin.rb +42 -0
  12. data/recipes/analytics.rb +41 -0
  13. data/recipes/core.rb +32 -0
  14. data/recipes/deployment.rb +178 -0
  15. data/recipes/devise.rb +34 -0
  16. data/recipes/email.rb +65 -0
  17. data/recipes/email_dev.rb +92 -0
  18. data/recipes/example.rb +63 -0
  19. data/recipes/extras.rb +283 -0
  20. data/recipes/frontend.rb +33 -0
  21. data/recipes/gems.rb +274 -0
  22. data/recipes/git.rb +27 -0
  23. data/recipes/init.rb +179 -0
  24. data/recipes/learn_rails.rb +89 -0
  25. data/recipes/locale.rb +31 -0
  26. data/recipes/omniauth.rb +38 -0
  27. data/recipes/pages.rb +91 -0
  28. data/recipes/rails_bootstrap.rb +29 -0
  29. data/recipes/rails_devise.rb +26 -0
  30. data/recipes/rails_devise_pundit.rb +25 -0
  31. data/recipes/rails_devise_roles.rb +25 -0
  32. data/recipes/rails_foundation.rb +29 -0
  33. data/recipes/rails_mailinglist_activejob.rb +76 -0
  34. data/recipes/rails_omniauth.rb +27 -0
  35. data/recipes/rails_signup_download.rb +69 -0
  36. data/recipes/rails_stripe_checkout.rb +84 -0
  37. data/recipes/rails_stripe_coupons.rb +125 -0
  38. data/recipes/rails_stripe_membership_saas.rb +112 -0
  39. data/recipes/railsapps.rb +77 -0
  40. data/recipes/readme.rb +161 -0
  41. data/recipes/roles.rb +40 -0
  42. data/recipes/setup.rb +162 -0
  43. data/recipes/tests.rb +59 -0
  44. data/spec/rails_wizard/config_spec.rb +108 -0
  45. data/spec/rails_wizard/recipe_spec.rb +115 -0
  46. data/spec/rails_wizard/recipes/sanity_spec.rb +30 -0
  47. data/spec/rails_wizard/recipes_spec.rb +41 -0
  48. data/spec/rails_wizard/template_spec.rb +92 -0
  49. data/spec/spec_helper.rb +11 -0
  50. data/spec/support/rails_directory.rb +17 -0
  51. data/spec/support/template_runner.rb +28 -0
  52. data/spec/test_recipes/test_recipe_in_file.rb +9 -0
  53. data/templates/helpers.erb +138 -0
  54. data/templates/layout.erb +231 -0
  55. data/templates/recipe.erb +13 -0
  56. data/version.rb +3 -0
  57. metadata +201 -0
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsWizard::Recipe do
4
+ context "with a generated recipe" do
5
+ subject{ RailsWizard::Recipe.generate('recipe_example', "# this is a test", :category => 'example', :name => "RailsWizard Example") }
6
+
7
+ context 'string setter methods' do
8
+ (RailsWizard::Recipe::ATTRIBUTES - ['config']).each do |setter|
9
+ it "should be able to set #{setter} with an argument" do
10
+ subject.send(setter + '=', "test")
11
+ subject.send(setter).should == 'test'
12
+ end
13
+
14
+ it 'should be able to get the value from the instance' do
15
+ subject.send(setter + '=', 'test')
16
+ subject.new.send(setter).should == subject.send(setter)
17
+ end
18
+ end
19
+ end
20
+
21
+ describe '.attributes' do
22
+ it 'should be accessible from the instance' do
23
+ subject.new.attributes.should == subject.attributes
24
+ end
25
+ end
26
+
27
+ describe '.generate' do
28
+ it 'should work with a string and hash as arguments' do
29
+ recipe = RailsWizard::Recipe.generate('some_key', '# some code', :name => "Example")
30
+ recipe.superclass.should == RailsWizard::Recipe
31
+ end
32
+
33
+ it 'should work with an IO object' do
34
+ file = StringIO.new <<-RUBY
35
+ # this is an example
36
+
37
+ __END__
38
+
39
+ category: example
40
+ name: This is an Example
41
+ description: You know it's an exmaple.
42
+ RUBY
43
+ recipe = RailsWizard::Recipe.generate('just_a_test', file)
44
+ recipe.template.should == '# this is an example'
45
+ recipe.category.should == 'example'
46
+ recipe.name.should == 'This is an Example'
47
+ end
48
+
49
+ it 'should raise an exception if the file is incorrectly formatted' do
50
+ file = StringIO.new <<-RUBY
51
+ # just ruby, no YAML
52
+ RUBY
53
+ lambda{RailsWizard::Recipe.generate('testing',file)}.should raise_error(ArgumentError)
54
+ end
55
+ end
56
+
57
+ describe '#compile' do
58
+ it 'should say the name' do
59
+ subject.name = "Awesome Sauce"
60
+ subject.new.compile.should be_include("say_recipe 'Awesome Sauce'")
61
+ end
62
+
63
+ it 'should include the template' do
64
+ subject.template = "This is only a test."
65
+ subject.new.compile.should be_include(subject.template)
66
+ end
67
+ end
68
+ end
69
+
70
+ it 'should set default attributes' do
71
+ recipe = RailsWizard::Recipe.generate('abc','# test')
72
+
73
+ RailsWizard::Recipe::DEFAULT_ATTRIBUTES.each_pair do |k,v|
74
+ recipe.send(k).should == v
75
+ end
76
+ end
77
+
78
+ describe ".from_mongo" do
79
+ context "when asked for a known recipe" do
80
+ before(:all) do
81
+ @recipe_key = 'recipe_example'
82
+ @recipe = RailsWizard::Recipe.generate(@recipe_key, '# this is a test', {
83
+ :category => 'example',
84
+ :name => 'RailsWizard Example',
85
+ } )
86
+ RailsWizard::Recipes.add(@recipe)
87
+ @recipe_klass = Kernel.
88
+ const_get('RailsWizard' ).
89
+ const_get('Recipes' ).
90
+ const_get('RecipeExample')
91
+ end
92
+
93
+ context "by key" do
94
+ it "returns the recipe" do
95
+ RailsWizard::Recipe.from_mongo(@recipe_key).should == @recipe_klass
96
+ end
97
+ end
98
+ context "by class" do
99
+ it "returns the recipe" do
100
+ RailsWizard::Recipe.from_mongo(@recipe_klass).should == @recipe_klass
101
+ end
102
+ end
103
+ end
104
+
105
+ context "when asked for an unknown recipe" do
106
+ it "raises an UnknownRecipeError" do
107
+ expect { RailsWizard::Recipe.from_mongo("foo") }.to raise_error RailsWizard::UnknownRecipeError, "No recipe found with name 'foo'"
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ __END__
114
+
115
+ this is a test
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ # This is a simple set of tests to make sure that
4
+ # all of the recipes conform to the base requirements.
5
+
6
+ RailsWizard::Recipes.list_classes.each do |recipe|
7
+ describe recipe do
8
+ it("should have a name"){ recipe.name.should be_kind_of(String) }
9
+ it("should have a description"){ recipe.description.should be_kind_of(String) }
10
+ it("should have a template"){ recipe.template.should be_kind_of(String) }
11
+ it("should be able to compile"){ recipe.new.compile.should be_kind_of(String) }
12
+
13
+ it "should have a string or nil category" do
14
+ if recipe.category
15
+ recipe.category.should be_kind_of(String)
16
+ end
17
+ end
18
+
19
+ it "should have a Config or nil config" do
20
+ if recipe.config
21
+ recipe.config.should be_kind_of(RailsWizard::Config)
22
+ end
23
+ end
24
+
25
+ it "should be in the list" do
26
+ RailsWizard::Recipes.list_classes.should be_include(recipe)
27
+ RailsWizard::Recipes.list.should be_include(recipe.key)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsWizard::Recipes do
4
+ subject{ RailsWizard::Recipes }
5
+
6
+ before(:all) do
7
+ @recipe = RailsWizard::Recipe.generate( "recipe_test", "# Testing", {
8
+ :category => 'test',
9
+ :description => 'Just a test.',
10
+ :name => 'Test Recipe',
11
+ } )
12
+ RailsWizard::Recipes.add(@recipe)
13
+ end
14
+
15
+ it '.list_classes should include recipe classes' do
16
+ subject.list_classes.should be_include(@recipe)
17
+ end
18
+
19
+ it '.list should include recipe keys' do
20
+ subject.list.should be_include('recipe_test')
21
+ end
22
+
23
+ describe '.for' do
24
+ it 'should find for a given category' do
25
+ RailsWizard::Recipes.for('test').should be_include('recipe_test')
26
+ end
27
+ end
28
+
29
+ it 'should add recipes in a directory with add_from_directory' do
30
+ subject.add_from_directory(File.join(File.dirname(__FILE__), '..', 'test_recipes'))
31
+ subject.list.should include 'test_recipe_in_file'
32
+ end
33
+
34
+ describe '.clear' do
35
+ it 'should remove all current recipes' do
36
+ RailsWizard::Recipes.clear
37
+ subject.list.should == []
38
+ subject.categories.should == []
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsWizard::Template do
4
+ subject{ RailsWizard::Template }
5
+ let(:recipe){ RailsWizard::Recipe.generate('name','# test') }
6
+ let(:defaults){ { "some_option" => "value" } }
7
+ let(:gems){ ['foogem'] }
8
+ let(:args){ [] }
9
+
10
+ describe '.template_root' do
11
+ it 'returns the gem ./templates directory by default' do
12
+ template_root = File.expand_path(subject.template_root)
13
+ template_root.should == File.expand_path('../../../templates', __FILE__)
14
+ end
15
+
16
+ it 'can be set to another directory' do
17
+ subject.template_root = '/tmp/templates'
18
+ subject.template_root.should == '/tmp/templates'
19
+ end
20
+ end
21
+
22
+ describe '#initialize' do
23
+ it 'should work with classes' do
24
+ subject.new([recipe], gems).recipes.should == [recipe]
25
+ end
26
+
27
+ it 'should accept optional defaults' do
28
+ subject.new([recipe], gems, args, defaults).defaults.should == defaults
29
+ end
30
+ end
31
+
32
+ describe '#resolve_dependencies' do
33
+ def recipe(name, opts={})
34
+ RailsWizard::Recipe.generate(name, '', opts)
35
+ end
36
+
37
+ subject do
38
+ @template = RailsWizard::Template.new([])
39
+ @template.stub(:recipes_with_dependencies).and_return(@recipes)
40
+ @template.resolve_recipes.map { |r| r.key }
41
+ end
42
+
43
+ it 'should sort properly' do
44
+ @recipes = [
45
+ recipe('add_user', :run_after => ['devise']),
46
+ recipe('devise', :run_after => ['omniauth']),
47
+ recipe('omniauth'),
48
+ recipe('haml'),
49
+ recipe('compass')
50
+ ]
51
+
52
+ subject.index('devise').should > subject.index('omniauth')
53
+ end
54
+
55
+ end
56
+
57
+ describe '#recipes_with_dependencies' do
58
+ def r(*deps)
59
+ double(:Class, :requires => deps, :superclass => RailsWizard::Recipe)
60
+ end
61
+
62
+ subject do
63
+ @template = RailsWizard::Template.new([])
64
+ @template.stub(:recipes).and_return(@recipes)
65
+ @template.stub(:recipe_classes).and_return(@recipes)
66
+ @template
67
+ end
68
+
69
+ it 'should return the same number recipes if none have dependencies' do
70
+ @recipes = [r, r]
71
+ subject.recipes_with_dependencies.size.should == 2
72
+ end
73
+
74
+ it 'should handle simple dependencies' do
75
+ @recipes = [r(r, r), r(r)]
76
+ subject.recipes_with_dependencies.size.should == 5
77
+ end
78
+
79
+ it 'should handle multi-level dependencies' do
80
+ @recipes = [r(r(r))]
81
+ subject.recipes_with_dependencies.size.should == 3
82
+ end
83
+
84
+ it 'should uniqify' do
85
+ a = r
86
+ b = r(a)
87
+ c = r(r, a, b)
88
+ @recipes = [a,b,c]
89
+ subject.recipes_with_dependencies.size.should == 4
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ require 'rspec'
4
+
5
+ Dir[File.dirname(__FILE__) + '/support/*'].each{|path| require path}
6
+
7
+ require 'rails_wizard'
8
+
9
+ RSpec.configure do |config|
10
+
11
+ end
@@ -0,0 +1,17 @@
1
+ class RailsDirectory
2
+ def initialize(path)
3
+ @path = path
4
+ end
5
+
6
+ def file_path(path)
7
+ File.join(@path, path)
8
+ end
9
+
10
+ def has_file?(path)
11
+ File.exist?(file_path(path))
12
+ end
13
+
14
+ def [](path)
15
+ File.open(file_path(path)).read
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ class TemplateRunner
2
+ attr_reader :template, :config, :app_name, :dir, :rails_dir, :output
3
+ def initialize(template, config)
4
+ @template = template
5
+ @config = config
6
+ end
7
+
8
+ def run(app_name = 'rails_app')
9
+ @app_name = app_name
10
+ @dir = Dir.mktmpdir
11
+ @rails_dir = File.join(@dir, @app_name)
12
+ Dir.chrdir(@dir) do
13
+ template_file = File.open 'template.rb', 'w'
14
+ template_file.write
15
+ template_file.close
16
+ @output = `rails new #{@app_name} -m template.rb`
17
+ end
18
+ @output
19
+ end
20
+
21
+ def rails
22
+ RailsDirectory.new(@rails_dir)
23
+ end
24
+
25
+ def clean
26
+ FileUtils.remove_entry_secure @dir
27
+ end
28
+ end
@@ -0,0 +1,9 @@
1
+ say_wizard "Hi! I am a test."
2
+
3
+ __END__
4
+
5
+ name: test_recipe_in_file
6
+ description: "this is test file"
7
+ author: githubname
8
+
9
+ category: test
@@ -0,0 +1,138 @@
1
+ def recipes; @recipes end
2
+ def recipe?(name); @recipes.include?(name) end
3
+ def prefs; @prefs end
4
+ def prefer(key, value); @prefs[key].eql? value end
5
+ def gems; @gems end
6
+ def diagnostics_recipes; @diagnostics_recipes end
7
+ def diagnostics_prefs; @diagnostics_prefs end
8
+
9
+ def say_custom(tag, text); say "\033[1m\033[36m" + tag.to_s.rjust(10) + "\033[0m" + " #{text}" end
10
+ def say_loud(tag, text); say "\033[1m\033[36m" + tag.to_s.rjust(10) + " #{text}" + "\033[0m" end
11
+ def say_recipe(name); say "\033[1m\033[36m" + "recipe".rjust(10) + "\033[0m" + " Running #{name} recipe..." end
12
+ def say_wizard(text); say_custom(@current_recipe || 'composer', text) end
13
+
14
+ def ask_wizard(question)
15
+ ask "\033[1m\033[36m" + ("option").rjust(10) + "\033[1m\033[36m" + " #{question}\033[0m"
16
+ end
17
+
18
+ def whisper_ask_wizard(question)
19
+ ask "\033[1m\033[36m" + ("choose").rjust(10) + "\033[0m" + " #{question}"
20
+ end
21
+
22
+ def yes_wizard?(question)
23
+ answer = ask_wizard(question + " \033[33m(y/n)\033[0m")
24
+ case answer.downcase
25
+ when "yes", "y"
26
+ true
27
+ when "no", "n"
28
+ false
29
+ else
30
+ yes_wizard?(question)
31
+ end
32
+ end
33
+
34
+ def no_wizard?(question); !yes_wizard?(question) end
35
+
36
+ def multiple_choice(question, choices)
37
+ say_custom('option', "\033[1m\033[36m" + "#{question}\033[0m")
38
+ values = {}
39
+ choices.each_with_index do |choice,i|
40
+ values[(i + 1).to_s] = choice[1]
41
+ say_custom( (i + 1).to_s + ')', choice[0] )
42
+ end
43
+ answer = whisper_ask_wizard("Enter your selection:") while !values.keys.include?(answer)
44
+ values[answer]
45
+ end
46
+
47
+ @current_recipe = nil
48
+ @configs = {}
49
+
50
+ @after_blocks = []
51
+ def stage_two(&block); @after_blocks << [@current_recipe, block]; end
52
+ @stage_three_blocks = []
53
+ def stage_three(&block); @stage_three_blocks << [@current_recipe, block]; end
54
+ @stage_four_blocks = []
55
+ def stage_four(&block); @stage_four_blocks << [@current_recipe, block]; end
56
+ @before_configs = {}
57
+ def before_config(&block); @before_configs[@current_recipe] = block; end
58
+
59
+ def copy_from(source, destination)
60
+ begin
61
+ remove_file destination
62
+ get source, destination
63
+ rescue OpenURI::HTTPError
64
+ say_wizard "Unable to obtain #{source}"
65
+ end
66
+ end
67
+
68
+ def copy_from_repo(filename, opts = {})
69
+ repo = 'https://raw.github.com/RailsApps/rails-composer/master/files/'
70
+ repo = opts[:repo] unless opts[:repo].nil?
71
+ if (!opts[:prefs].nil?) && (!prefs.has_value? opts[:prefs])
72
+ return
73
+ end
74
+ source_filename = filename
75
+ destination_filename = filename
76
+ unless opts[:prefs].nil?
77
+ if filename.include? opts[:prefs]
78
+ destination_filename = filename.gsub(/\-#{opts[:prefs]}/, '')
79
+ end
80
+ end
81
+ if (prefer :templates, 'haml') && (filename.include? 'views')
82
+ remove_file destination_filename
83
+ destination_filename = destination_filename.gsub(/.erb/, '.haml')
84
+ end
85
+ if (prefer :templates, 'slim') && (filename.include? 'views')
86
+ remove_file destination_filename
87
+ destination_filename = destination_filename.gsub(/.erb/, '.slim')
88
+ end
89
+ begin
90
+ remove_file destination_filename
91
+ if (prefer :templates, 'haml') && (filename.include? 'views')
92
+ create_file destination_filename, html_to_haml(repo + source_filename)
93
+ elsif (prefer :templates, 'slim') && (filename.include? 'views')
94
+ create_file destination_filename, html_to_slim(repo + source_filename)
95
+ else
96
+ get repo + source_filename, destination_filename
97
+ end
98
+ rescue OpenURI::HTTPError
99
+ say_wizard "Unable to obtain #{source_filename} from the repo #{repo}"
100
+ end
101
+ end
102
+
103
+ def html_to_haml(source)
104
+ begin
105
+ html = open(source) {|input| input.binmode.read }
106
+ Html2haml::HTML.new(html, :erb => true, :xhtml => true).render
107
+ rescue RubyParser::SyntaxError
108
+ say_wizard "Ignoring RubyParser::SyntaxError"
109
+ # special case to accommodate https://github.com/RailsApps/rails-composer/issues/55
110
+ html = open(source) {|input| input.binmode.read }
111
+ say_wizard "applying patch" if html.include? 'card_month'
112
+ say_wizard "applying patch" if html.include? 'card_year'
113
+ html = html.gsub(/, {add_month_numbers: true}, {name: nil, id: "card_month"}/, '')
114
+ html = html.gsub(/, {start_year: Date\.today\.year, end_year: Date\.today\.year\+10}, {name: nil, id: "card_year"}/, '')
115
+ result = Html2haml::HTML.new(html, :erb => true, :xhtml => true).render
116
+ result = result.gsub(/select_month nil/, "select_month nil, {add_month_numbers: true}, {name: nil, id: \"card_month\"}")
117
+ result = result.gsub(/select_year nil/, "select_year nil, {start_year: Date.today.year, end_year: Date.today.year+10}, {name: nil, id: \"card_year\"}")
118
+ end
119
+ end
120
+
121
+ def html_to_slim(source)
122
+ html = open(source) {|input| input.binmode.read }
123
+ haml = Html2haml::HTML.new(html, :erb => true, :xhtml => true).render
124
+ Haml2Slim.convert!(haml)
125
+ end
126
+
127
+ # full credit to @mislav in this StackOverflow answer for the #which() method:
128
+ # - http://stackoverflow.com/a/5471032
129
+ def which(cmd)
130
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
131
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
132
+ exts.each do |ext|
133
+ exe = "#{path}#{File::SEPARATOR}#{cmd}#{ext}"
134
+ return exe if File.executable? exe
135
+ end
136
+ end
137
+ return nil
138
+ end