redmint_composer 2.3

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 (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