tennpipes-init 3.6.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +163 -0
- data/Rakefile +1 -0
- data/bin/tennpipes-init +16 -0
- data/lib/tennpipes-init.rb +73 -0
- data/lib/tennpipes-init/command.rb +18 -0
- data/lib/tennpipes-init/generators/actions.rb +630 -0
- data/lib/tennpipes-init/generators/app.rb +75 -0
- data/lib/tennpipes-init/generators/app/app.rb.tt +72 -0
- data/lib/tennpipes-init/generators/app/app.rb.tt~ +72 -0
- data/lib/tennpipes-init/generators/cli.rb +57 -0
- data/lib/tennpipes-init/generators/component.rb +73 -0
- data/lib/tennpipes-init/generators/components/actions.rb +208 -0
- data/lib/tennpipes-init/generators/components/mocks/mocha.rb +10 -0
- data/lib/tennpipes-init/generators/components/mocks/rr.rb +13 -0
- data/lib/tennpipes-init/generators/components/orms/activerecord.rb +201 -0
- data/lib/tennpipes-init/generators/components/orms/couchrest.rb +55 -0
- data/lib/tennpipes-init/generators/components/orms/datamapper.rb +140 -0
- data/lib/tennpipes-init/generators/components/orms/dynamoid.rb +67 -0
- data/lib/tennpipes-init/generators/components/orms/minirecord.rb +165 -0
- data/lib/tennpipes-init/generators/components/orms/mongoid.rb +113 -0
- data/lib/tennpipes-init/generators/components/orms/mongomapper.rb +43 -0
- data/lib/tennpipes-init/generators/components/orms/mongomatic.rb +84 -0
- data/lib/tennpipes-init/generators/components/orms/ohm.rb +65 -0
- data/lib/tennpipes-init/generators/components/orms/ripple.rb +75 -0
- data/lib/tennpipes-init/generators/components/orms/sequel.rb +99 -0
- data/lib/tennpipes-init/generators/components/renderers/erb.rb +3 -0
- data/lib/tennpipes-init/generators/components/renderers/haml.rb +3 -0
- data/lib/tennpipes-init/generators/components/renderers/liquid.rb +4 -0
- data/lib/tennpipes-init/generators/components/renderers/slim.rb +3 -0
- data/lib/tennpipes-init/generators/components/scripts/dojo.rb +10 -0
- data/lib/tennpipes-init/generators/components/scripts/extcore.rb +10 -0
- data/lib/tennpipes-init/generators/components/scripts/jquery.rb +10 -0
- data/lib/tennpipes-init/generators/components/scripts/mootools.rb +10 -0
- data/lib/tennpipes-init/generators/components/scripts/prototype.rb +12 -0
- data/lib/tennpipes-init/generators/components/scripts/rightjs.rb +10 -0
- data/lib/tennpipes-init/generators/components/stylesheets/compass.rb +39 -0
- data/lib/tennpipes-init/generators/components/stylesheets/compass/application.scss +43 -0
- data/lib/tennpipes-init/generators/components/stylesheets/compass/partials/_base.scss +12 -0
- data/lib/tennpipes-init/generators/components/stylesheets/less.rb +25 -0
- data/lib/tennpipes-init/generators/components/stylesheets/sass.rb +15 -0
- data/lib/tennpipes-init/generators/components/stylesheets/scss.rb +16 -0
- data/lib/tennpipes-init/generators/components/tests/bacon.rb +103 -0
- data/lib/tennpipes-init/generators/components/tests/cucumber.rb +86 -0
- data/lib/tennpipes-init/generators/components/tests/minitest.rb +110 -0
- data/lib/tennpipes-init/generators/components/tests/riot.rb +117 -0
- data/lib/tennpipes-init/generators/components/tests/rspec.rb +111 -0
- data/lib/tennpipes-init/generators/components/tests/shoulda.rb +114 -0
- data/lib/tennpipes-init/generators/components/tests/steak.rb +114 -0
- data/lib/tennpipes-init/generators/controller.rb +77 -0
- data/lib/tennpipes-init/generators/helper.rb +50 -0
- data/lib/tennpipes-init/generators/mailer.rb +52 -0
- data/lib/tennpipes-init/generators/migration.rb +43 -0
- data/lib/tennpipes-init/generators/model.rb +113 -0
- data/lib/tennpipes-init/generators/plugin.rb +67 -0
- data/lib/tennpipes-init/generators/project.rb +160 -0
- data/lib/tennpipes-init/generators/project/config.ru +9 -0
- data/lib/tennpipes-init/generators/project/config/apps.rb.tt +35 -0
- data/lib/tennpipes-init/generators/project/config/boot.rb +49 -0
- data/lib/tennpipes-init/generators/project/public/favicon.ico +0 -0
- data/lib/tennpipes-init/generators/project/public/images/booking.com.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/causes.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/ennkeypee_bg.jpg +0 -0
- data/lib/tennpipes-init/generators/project/public/images/ennkeypee_bluelogo.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/ennkeypee_bluelogo.svg +68 -0
- data/lib/tennpipes-init/generators/project/public/images/ennkeypee_whitelogo.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/ennkeypee_whitelogo.svg +65 -0
- data/lib/tennpipes-init/generators/project/public/images/forever21.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.eot +0 -0
- data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.svg +970 -0
- data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.ttf +0 -0
- data/lib/tennpipes-init/generators/project/public/images/icons/foundation-icons.woff +0 -0
- data/lib/tennpipes-init/generators/project/public/images/icons/tennpipes-icons.css +598 -0
- data/lib/tennpipes-init/generators/project/public/images/image1.jpg +0 -0
- data/lib/tennpipes-init/generators/project/public/images/image11.jpg +0 -0
- data/lib/tennpipes-init/generators/project/public/images/image2.jpg +0 -0
- data/lib/tennpipes-init/generators/project/public/images/image3.jpg +0 -0
- data/lib/tennpipes-init/generators/project/public/images/intuit.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/krispykreme.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/README.md +302 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/bower.json +4 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/composer.json +34 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/gulpfile.js +92 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/holder.js +1920 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/holder.min.js +12 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/package.json +46 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/src/holder.js +1411 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/src/lib/augment.js +27 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/src/lib/ondomready.js +155 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/src/lib/polyfills.js +177 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/src/scenegraph.js +101 -0
- data/lib/tennpipes-init/generators/project/public/images/placeholders/src/utils.js +129 -0
- data/lib/tennpipes-init/generators/project/public/images/priceline.com.png +0 -0
- data/lib/tennpipes-init/generators/project/public/images/stripe.png +0 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes.min.js +6081 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.abide.js +340 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.accordion.js +67 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.alert.js +43 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.clearing.js +556 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.dropdown.js +448 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.equalizer.js +77 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.interchange.js +354 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.joyride.js +932 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.js +703 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.magellan.js +203 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.offcanvas.js +152 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.orbit.js +476 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.reveal.js +471 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.slider.js +263 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.tab.js +237 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.tooltip.js +307 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/tennpipes/tennpipes.topbar.js +452 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/vendor/fastclick.js +8 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/vendor/jquery.cookie.js +8 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/vendor/jquery.js +26 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/vendor/modernizr.js +8 -0
- data/lib/tennpipes-init/generators/project/public/javascripts/vendor/placeholder.js +2 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/app.css~ +178 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/app1.css~ +177 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/ennkeypee.css +214 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/ennkeypee.css~ +214 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/normalize.css +427 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/tennpipes.css +6201 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/tennpipes.css~ +6201 -0
- data/lib/tennpipes-init/generators/project/public/stylesheets/tennpipes.min.css +1 -0
- data/lib/tennpipes-init/generators/runner.rb +139 -0
- data/lib/tennpipes-init/generators/task.rb +45 -0
- data/lib/tennpipes-init/generators/templates/Gemfile.tt +32 -0
- data/lib/tennpipes-init/generators/templates/Rakefile.tt +8 -0
- data/lib/tennpipes-init/generators/templates/controller.rb.tt +22 -0
- data/lib/tennpipes-init/generators/templates/gem/README.md.tt +29 -0
- data/lib/tennpipes-init/generators/templates/gem/gemspec.tt +19 -0
- data/lib/tennpipes-init/generators/templates/gem/lib/libname.tt +6 -0
- data/lib/tennpipes-init/generators/templates/gem/lib/libname/version.tt +3 -0
- data/lib/tennpipes-init/generators/templates/helper.rb.tt +13 -0
- data/lib/tennpipes-init/generators/templates/initializer.rb.tt +5 -0
- data/lib/tennpipes-init/generators/templates/mailer.rb.tt +54 -0
- data/lib/tennpipes-init/generators/templates/project_bin.tt +14 -0
- data/lib/tennpipes-init/generators/templates/task.rb.tt +7 -0
- data/lib/tennpipes-init/tennpipes-tasks/activerecord.rb +377 -0
- data/lib/tennpipes-init/tennpipes-tasks/database.rb +12 -0
- data/lib/tennpipes-init/tennpipes-tasks/datamapper.rb +94 -0
- data/lib/tennpipes-init/tennpipes-tasks/minirecord.rb +19 -0
- data/lib/tennpipes-init/tennpipes-tasks/mongoid.rb +215 -0
- data/lib/tennpipes-init/tennpipes-tasks/mongomapper.rb +55 -0
- data/lib/tennpipes-init/tennpipes-tasks/sequel.rb +85 -0
- data/lib/tennpipes-init/tennpipes-tasks/sql-helpers.rb +72 -0
- data/test/fixtures/admin_template.rb +7 -0
- data/test/fixtures/example_template.rb +15 -0
- data/test/fixtures/git_template.rb +4 -0
- data/test/fixtures/plugin_template.rb +13 -0
- data/test/fixtures/rake_template.rb +9 -0
- data/test/helper.rb +103 -0
- data/test/test_app_generator.rb +142 -0
- data/test/test_cli.rb +27 -0
- data/test/test_component_generator.rb +98 -0
- data/test/test_controller_generator.rb +272 -0
- data/test/test_generator.rb +13 -0
- data/test/test_helper_generator.rb +133 -0
- data/test/test_mailer_generator.rb +69 -0
- data/test/test_migration_generator.rb +222 -0
- data/test/test_model_generator.rb +553 -0
- data/test/test_plugin_generator.rb +152 -0
- data/test/test_project_generator.rb +757 -0
- data/test/test_task_generator.rb +53 -0
- metadata +285 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c7ceae2eea5dffe4f6251675777b082af7ff26fd
|
4
|
+
data.tar.gz: 30e12698ffc27d64b3e719a0444be4c4e47597aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 39f426e683fb4166564fb2297ddbf4a1a93d0fdd4917f1a53a10686fc3c1c89cfd22779aa5561c2a21a4935566761a0be4dc564b1e030f373db0bd091e1f47b5
|
7
|
+
data.tar.gz: 2b208aec0720a1ee5d24df9591261882cec35ddd8ae77f5cddc49f37a3ea3aff59e3bedf8227be1f5519307265605cb393d373f0c7ff5122d994436b56aaf281
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Tennpipes
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
= Agnostic Application Generators (tennpipes-init)
|
2
|
+
|
3
|
+
=== Overview
|
4
|
+
|
5
|
+
Tennpipes comes preloaded with flexible code generators powered in part by the excellent Thor gem
|
6
|
+
(incidentally also used in the Rails 3 generators). These generators are intended to allow for easy code generation
|
7
|
+
both in creating new applications and building on existing ones. The generators have been built to be as library agnostic
|
8
|
+
as possible, supporting a myriad of test frameworks, js libraries, mocking libraries, etc.
|
9
|
+
|
10
|
+
See the guide for {Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators] for a
|
11
|
+
more in-depth look at the system.
|
12
|
+
|
13
|
+
=== Project Generator
|
14
|
+
|
15
|
+
Tennpipes provides generator support for quickly creating new Tennpipes applications. This provides many benefits
|
16
|
+
such as constructing the recommended Tennpipes application structure, auto-generating a Gemfile listing
|
17
|
+
all starting dependencies and guidelines provided within the generated files to help orient a new user
|
18
|
+
to using Tennpipes.
|
19
|
+
|
20
|
+
One important feature of the generators is that they were built from the ground up to support a wide variety
|
21
|
+
of tools, libraries and gems for use within your tennpipes application.
|
22
|
+
|
23
|
+
The simplest possible command to generate a base application would be:
|
24
|
+
|
25
|
+
$ tennpipes-init project demo_project
|
26
|
+
|
27
|
+
This would construct a Tennpipes application DemoApp (which extends from Tennpipes::Application)
|
28
|
+
inside the folder 'demo_project' at our current path. Inside the application there would be configuration and
|
29
|
+
setup performed for the default components.
|
30
|
+
|
31
|
+
You can define specific components to be used:
|
32
|
+
|
33
|
+
$ tennpipes-init project demo_project -t rspec -r haml -m rr -s jquery -d datamapper
|
34
|
+
|
35
|
+
You can also instruct the generator to skip a certain component to avoid using one at all (or to use your own):
|
36
|
+
|
37
|
+
$ tennpipes-init project demo_project --test none --renderer none
|
38
|
+
|
39
|
+
The available components and their default options are listed below:
|
40
|
+
|
41
|
+
test:: none (default), bacon, shoulda, cucumber, riot, rspec, minitest, steak
|
42
|
+
renderer:: slim (default), erb, erubis, liquid, haml
|
43
|
+
stylesheet:: none (default), less, compass, sass, scss
|
44
|
+
mock:: none (default), mocha, rr
|
45
|
+
script:: none (default), jquery, prototype, mootools, rightjs, extcore, dojo
|
46
|
+
orm:: none (default), datamapper, mongomapper, mongoid, activerecord, minirecord, sequel, couchrest, ohm, mongomatic, ripple, dynamoid
|
47
|
+
|
48
|
+
In addition, you can generate projects based on existing templates:
|
49
|
+
|
50
|
+
$ tennpipes-init project demo_project --template sampleblog
|
51
|
+
|
52
|
+
To learn more about the project generator, check out the guide to
|
53
|
+
{Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
|
54
|
+
|
55
|
+
=== Plugin System
|
56
|
+
|
57
|
+
Tennpipes provides support for plugins to be executed within your application. For example:
|
58
|
+
|
59
|
+
$ tennpipes-init plugin hoptoad
|
60
|
+
|
61
|
+
would install the hoptoad middleware into your application automatically.
|
62
|
+
|
63
|
+
To learn more about the plugin system, check out the guide to
|
64
|
+
{Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
|
65
|
+
|
66
|
+
=== Sub App Generator
|
67
|
+
|
68
|
+
Unlike other ruby frameworks Tennpipes is principally designed for mounting multiple apps at the same time.
|
69
|
+
|
70
|
+
First you need to create a project
|
71
|
+
|
72
|
+
$ tennpipes-init project demo_project
|
73
|
+
$ cd demo_project
|
74
|
+
|
75
|
+
Now you are in demo_project and you can create your apps:
|
76
|
+
|
77
|
+
$ tennpipes-init app one
|
78
|
+
$ tennpipes-init app two
|
79
|
+
|
80
|
+
By default these apps are mounted under:
|
81
|
+
|
82
|
+
* /one
|
83
|
+
* /two
|
84
|
+
|
85
|
+
but you can edit config/apps.rb and change it.
|
86
|
+
|
87
|
+
To learn more about the subapp generator, check out the guide to
|
88
|
+
{Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
|
89
|
+
|
90
|
+
=== Model Generator
|
91
|
+
|
92
|
+
Tennpipes provides generator support for quickly creating new models within your Tennpipes application. Note that
|
93
|
+
the models (and migrations) generated are specifically tailored towards the ORM component and testing framework
|
94
|
+
chosen during application generation.
|
95
|
+
|
96
|
+
Very important to note that model generators are intended primarily to work within applications
|
97
|
+
created through the Tennpipes application generator and that follow Tennpipes conventions. Using model generators
|
98
|
+
within an existing application not generated by Tennpipes will likely not work as expected.
|
99
|
+
|
100
|
+
Using the model generator is as simple as:
|
101
|
+
|
102
|
+
$ tennpipes-init model User
|
103
|
+
|
104
|
+
You can also specify desired fields to be contained within your User model:
|
105
|
+
|
106
|
+
$ tennpipes-init model User name:string age:integer email:string
|
107
|
+
|
108
|
+
To learn more about the model generator, check out the guide to
|
109
|
+
{Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
|
110
|
+
|
111
|
+
=== Migration Generator
|
112
|
+
|
113
|
+
Tennpipes provides generator for quickly generating new migrations to change or manipulate the database schema.
|
114
|
+
These migrations generated will be tailored towards the ORM chosen when generating the application.
|
115
|
+
|
116
|
+
Very important to note that migration generators are intended primarily to work within applications
|
117
|
+
created through the Tennpipes application generator and that follow Tennpipes conventions. Using migration generators
|
118
|
+
within an existing application not generated by Tennpipes will likely not work as expected.
|
119
|
+
|
120
|
+
Using the migration generator is as simple as:
|
121
|
+
|
122
|
+
$ tennpipes-init migration AddFieldsToUsers
|
123
|
+
$ tennpipes-init migration RemoveFieldsFromUsers
|
124
|
+
|
125
|
+
To learn more about the migration generator, check out the guide to
|
126
|
+
{Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
|
127
|
+
|
128
|
+
=== Controller Generator
|
129
|
+
|
130
|
+
Tennpipes provides generator support for quickly creating new controllers within your Tennpipes application. Note that
|
131
|
+
the controller tests are generated specifically tailored towards the testing framework chosen
|
132
|
+
during application generation.
|
133
|
+
|
134
|
+
Very important to note that controller generators are intended primarily to work within applications
|
135
|
+
created through the Tennpipes application generator and that follow Tennpipes conventions.
|
136
|
+
|
137
|
+
Using the controller generator is as simple as:
|
138
|
+
|
139
|
+
$ tennpipes-init controller Admin
|
140
|
+
|
141
|
+
You can also specify desired actions to be added to your controller:
|
142
|
+
|
143
|
+
$ tennpipes-init controller Admin get:index get:new post:create
|
144
|
+
|
145
|
+
To learn more about the controller generator, check out the guide to
|
146
|
+
{Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
|
147
|
+
|
148
|
+
=== Mailer Generator
|
149
|
+
|
150
|
+
Tennpipes provides generator support for quickly creating new mailers within your Tennpipes application.
|
151
|
+
Very important to note that mailer generators are intended primarily to work within applications
|
152
|
+
created through the Tennpipes application generator and that follow Tennpipes conventions.
|
153
|
+
|
154
|
+
Using the mailer generator is as simple as:
|
155
|
+
|
156
|
+
$ tennpipes-init mailer UserNotifier
|
157
|
+
|
158
|
+
To learn more about the mailer generator, check out the guide to
|
159
|
+
{Tennpipes Generators}[http://www.tennpipesrb.com/guides/generators].
|
160
|
+
|
161
|
+
== Copyright
|
162
|
+
|
163
|
+
Copyright (c) 2011-2013 Tennpipes. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper')
|
data/bin/tennpipes-init
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems' unless defined?(Gem) # Useful only on --dev mode
|
3
|
+
require 'bundler/setup' if %w(Gemfile .components).all? { |f| File.exist?(f) }
|
4
|
+
|
5
|
+
tennpipes_gen_path = File.expand_path('../../lib', __FILE__)
|
6
|
+
$:.unshift(tennpipes_gen_path) if File.directory?(tennpipes_gen_path) && !$:.include?(tennpipes_gen_path)
|
7
|
+
|
8
|
+
# We try to load the vendored tennpipes-base if exist (useful also for --dev mode)
|
9
|
+
tennpipes_core_path = File.expand_path('../../../tennpipes-base/lib', __FILE__)
|
10
|
+
$:.unshift(tennpipes_core_path) if File.directory?(tennpipes_core_path) && !$:.include?(tennpipes_core_path)
|
11
|
+
|
12
|
+
require 'tennpipes-init'
|
13
|
+
require 'tennpipes-init/generators/cli'
|
14
|
+
|
15
|
+
# We need our config boot because we need to load registered generators so:
|
16
|
+
Tennpipes::Generators::Cli.start(ARGV)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'tennpipes-base/tasks'
|
2
|
+
require 'tennpipes-init/command'
|
3
|
+
require 'active_support/ordered_hash'
|
4
|
+
|
5
|
+
module Tennpipes
|
6
|
+
##
|
7
|
+
# This module it's used for register generators.
|
8
|
+
#
|
9
|
+
# Can be useful for 3rd party generators:
|
10
|
+
#
|
11
|
+
# # custom_generator.rb
|
12
|
+
# class CustomGenerator < Thor::Group
|
13
|
+
# Tennpipes::Generators.add_generator(:custom_generator, self)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Now for handle generators in tennpipes you need to add it to into +load_paths+.
|
17
|
+
#
|
18
|
+
# Tennpipes::Generators.load_paths << "custom_generator.rb"
|
19
|
+
#
|
20
|
+
module Generators
|
21
|
+
# Defines the absolute path to the tennpipes source folder.
|
22
|
+
DEV_PATH = File.expand_path("../../", File.dirname(__FILE__))
|
23
|
+
|
24
|
+
class << self
|
25
|
+
##
|
26
|
+
# Store our generators paths.
|
27
|
+
#
|
28
|
+
def load_paths
|
29
|
+
@_files ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Return an ordered list of task with their class.
|
34
|
+
#
|
35
|
+
def mappings
|
36
|
+
@_mappings ||= ActiveSupport::OrderedHash.new
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Global add a new generator class to +tennpipes-init+.
|
41
|
+
#
|
42
|
+
# @param [Symbol] name
|
43
|
+
# Key name for generator mapping.
|
44
|
+
# @param [Class] klass
|
45
|
+
# Class of generator.
|
46
|
+
#
|
47
|
+
# @return [Hash] generator mappings
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# Tennpipes::Generators.add_generator(:controller, Controller)
|
51
|
+
#
|
52
|
+
def add_generator(name, klass)
|
53
|
+
mappings[name] = klass
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Load Global Actions and Component Actions then all files in +load_path+.
|
58
|
+
#
|
59
|
+
def load_components!
|
60
|
+
require 'tennpipes-init/generators/actions'
|
61
|
+
require 'tennpipes-init/generators/components/actions'
|
62
|
+
require 'tennpipes-init/generators/runner'
|
63
|
+
load_paths.flatten.each { |file| require file }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Add our generators to Tennpipes::Generators.
|
70
|
+
Tennpipes::Generators.load_paths << Dir[File.dirname(__FILE__) + '/tennpipes-init/generators/{project,app,mailer,controller,helper,model,migration,plugin,component,task}.rb']
|
71
|
+
|
72
|
+
# Add our tasks to tennpipes-base.
|
73
|
+
Tennpipes::Tasks.files << Dir[File.dirname(__FILE__) + "/tennpipes-init/tennpipes-tasks/**/*.rb"]
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'tennpipes-base/command'
|
2
|
+
|
3
|
+
module Tennpipes
|
4
|
+
##
|
5
|
+
# This method return the correct location of tennpipes-init bin or
|
6
|
+
# exec it using Kernel#system with the given args.
|
7
|
+
#
|
8
|
+
# @param [Array<String>] args.
|
9
|
+
# Splat of arguments to pass to tennpipes-init.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# Tennpipes.bin_gen(:app, name.to_s, "-r=#{destination_root}")
|
13
|
+
#
|
14
|
+
def self.bin_gen(*args)
|
15
|
+
@_tennpipes_gen_bin ||= [Tennpipes.ruby_command, File.expand_path("../../../bin/tennpipes-init", __FILE__)]
|
16
|
+
system args.unshift(@_tennpipes_gen_bin).join(" ")
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,630 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Tennpipes
|
4
|
+
module Generators
|
5
|
+
# Raised when an application does not have a resolved root path.
|
6
|
+
class AppRootNotFound < RuntimeError; end
|
7
|
+
##
|
8
|
+
# Default helper name for use in tiny app skeleton generator.
|
9
|
+
#
|
10
|
+
DEFAULT_HELPER_NAME = "Helper".freeze
|
11
|
+
##
|
12
|
+
# Common actions needed to support project and component generation.
|
13
|
+
#
|
14
|
+
module Actions
|
15
|
+
def self.included(base)
|
16
|
+
base.extend(ClassMethods)
|
17
|
+
end
|
18
|
+
##
|
19
|
+
# Avoids editing destination file if it does not exist.
|
20
|
+
#
|
21
|
+
def inject_into_file(destination, *args, &block)
|
22
|
+
destination_path = Pathname.new(destination).absolute? ? destination : destination_root(destination)
|
23
|
+
return unless File.exist?(destination_path)
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Performs the necessary generator for a given component choice.
|
29
|
+
#
|
30
|
+
# @param [Symbol] component
|
31
|
+
# The type of component module.
|
32
|
+
# @param [String] choice
|
33
|
+
# The name of the component module choice.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# execute_component_setup(:mock, 'rr')
|
37
|
+
#
|
38
|
+
def execute_component_setup(component, choice)
|
39
|
+
return true && say_status(:skipping, "#{component} component...") if choice.to_s == 'none'
|
40
|
+
say_status(:applying, "#{choice} (#{component})...")
|
41
|
+
apply_component_for(choice, component)
|
42
|
+
send("setup_#{component}") if respond_to?("setup_#{component}")
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Returns the related module for a given component and option.
|
47
|
+
#
|
48
|
+
# @param [String] choice
|
49
|
+
# The name of the component module.
|
50
|
+
# @param [Symbol] component
|
51
|
+
# The type of the component module.
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# apply_component_for('rr', :mock)
|
55
|
+
#
|
56
|
+
def apply_component_for(choice, component)
|
57
|
+
# I need to override Thor#apply because for unknow reason :verbose => false break tasks.
|
58
|
+
path = File.expand_path(File.dirname(__FILE__) + "/components/#{component.to_s.pluralize}/#{choice}.rb")
|
59
|
+
say_status :apply, "#{component.to_s.pluralize}/#{choice}"
|
60
|
+
shell.padding += 1
|
61
|
+
instance_eval(File.read(path))
|
62
|
+
shell.padding -= 1
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Includes the component module for the given component and choice.
|
67
|
+
# It determines the choice using .components file.
|
68
|
+
#
|
69
|
+
# @param [Symbol] component
|
70
|
+
# The type of component module.
|
71
|
+
# @param [String] choice
|
72
|
+
# The name of the component module.
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
# include_component_module_for(:mock)
|
76
|
+
# include_component_module_for(:mock, 'rr')
|
77
|
+
#
|
78
|
+
def include_component_module_for(component, choice=nil)
|
79
|
+
choice = fetch_component_choice(component) unless choice
|
80
|
+
return false if choice.to_s == 'none'
|
81
|
+
apply_component_for(choice, component)
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Returns the component choice stored within the .component file of an application.
|
86
|
+
#
|
87
|
+
# @param [Symbol] component
|
88
|
+
# The type of component module.
|
89
|
+
#
|
90
|
+
# @return [String] Name of the component module.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# fetch_component_choice(:mock)
|
94
|
+
#
|
95
|
+
def fetch_component_choice(component)
|
96
|
+
retrieve_component_config(destination_root('.components'))[component]
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Set the component choice in the .component file of the application.
|
101
|
+
#
|
102
|
+
# @param [Symbol] key
|
103
|
+
# The type of component module.
|
104
|
+
# @param [Symbol] value
|
105
|
+
# The name of the component module.
|
106
|
+
#
|
107
|
+
# @return [Symbol] The name of the component module.
|
108
|
+
#
|
109
|
+
# @example
|
110
|
+
# store_component_choice(:renderer, :haml)
|
111
|
+
#
|
112
|
+
def store_component_choice(key, value)
|
113
|
+
path = destination_root('.components')
|
114
|
+
config = retrieve_component_config(path)
|
115
|
+
config[key] = value
|
116
|
+
create_file(path, :force => true) { config.to_yaml }
|
117
|
+
value
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Loads the component config back into a hash.
|
122
|
+
#
|
123
|
+
# @param [String] target
|
124
|
+
# Path to component config file.
|
125
|
+
#
|
126
|
+
# @return [Hash] Loaded YAML file.
|
127
|
+
#
|
128
|
+
# @example
|
129
|
+
# retrieve_component_config(...)
|
130
|
+
# # => { :mock => 'rr', :test => 'riot', ... }
|
131
|
+
#
|
132
|
+
def retrieve_component_config(target)
|
133
|
+
YAML.load_file(target)
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Prompts the user if necessary until a valid choice is returned for the component.
|
138
|
+
#
|
139
|
+
# @param [Symbol] component
|
140
|
+
# The type of component module.
|
141
|
+
#
|
142
|
+
# @return [String] Name of component if valid, otherwise ask for valid choice.
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# resolve_valid_choice(:mock)
|
146
|
+
#
|
147
|
+
def resolve_valid_choice(component)
|
148
|
+
available_string = self.class.available_choices_for(component).join(", ")
|
149
|
+
choice = options[component]
|
150
|
+
until valid_choice?(component, choice)
|
151
|
+
say("Option for --#{component} '#{choice}' is not available.", :red)
|
152
|
+
choice = ask("Please enter a valid option for #{component} (#{available_string}):")
|
153
|
+
end
|
154
|
+
choice
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Returns true if the option passed is a valid choice for component.
|
159
|
+
#
|
160
|
+
# @param [Symbol] component
|
161
|
+
# The type of component module.
|
162
|
+
# @param [String] choice
|
163
|
+
# The name of the component module.
|
164
|
+
#
|
165
|
+
# @return [Boolean] Boolean of whether the choice is valid.
|
166
|
+
#
|
167
|
+
# @example
|
168
|
+
# valid_choice?(:mock, 'rr')
|
169
|
+
#
|
170
|
+
def valid_choice?(component, choice)
|
171
|
+
choice.present? && self.class.available_choices_for(component).include?(choice.to_sym)
|
172
|
+
end
|
173
|
+
|
174
|
+
##
|
175
|
+
# Creates a component_config file at the destination containing all component options.
|
176
|
+
# Content is a YAMLized version of a hash containing component name mapping to chosen value.
|
177
|
+
#
|
178
|
+
# @param [String] destination
|
179
|
+
# The file path to store the component config.
|
180
|
+
#
|
181
|
+
# @example
|
182
|
+
# store_component_config('/foo/bar')
|
183
|
+
#
|
184
|
+
def store_component_config(destination)
|
185
|
+
components = @_components || options
|
186
|
+
create_file(destination) do
|
187
|
+
self.class.component_types.inject({}) { |result, comp|
|
188
|
+
result[comp] = components[comp].to_s; result
|
189
|
+
}.to_yaml
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Returns the root for this Thor class (also aliased as destination root).
|
195
|
+
#
|
196
|
+
# @param [Array<String>] paths
|
197
|
+
# The relative path from destination root.
|
198
|
+
#
|
199
|
+
# @return [String] The full path
|
200
|
+
#
|
201
|
+
# @example
|
202
|
+
# destination_root('config/boot.rb')
|
203
|
+
#
|
204
|
+
def destination_root(*paths)
|
205
|
+
File.expand_path(File.join(@destination_stack.last, paths))
|
206
|
+
end
|
207
|
+
|
208
|
+
##
|
209
|
+
# Returns true if inside a Tennpipes application.
|
210
|
+
#
|
211
|
+
def in_app_root?
|
212
|
+
File.exist?(destination_root('config/boot.rb'))
|
213
|
+
end
|
214
|
+
|
215
|
+
##
|
216
|
+
# Returns true if constant name already exists.
|
217
|
+
#
|
218
|
+
def already_exists?(name, project_name = nil)
|
219
|
+
project_name = project_name ? (Object.const_get(project_name) rescue nil) : nil
|
220
|
+
Object.const_defined?(name) || (project_name && project_name.const_defined?(name))
|
221
|
+
end
|
222
|
+
|
223
|
+
##
|
224
|
+
# Returns the field with an unacceptable name(for symbol) else returns nil.
|
225
|
+
#
|
226
|
+
# @param [Array<String>] fields
|
227
|
+
# Field names for generators.
|
228
|
+
#
|
229
|
+
# @return [Array<String>] array of invalid fields
|
230
|
+
#
|
231
|
+
# @example
|
232
|
+
# invalid_fields ['foo:bar', 'hello:world']
|
233
|
+
#
|
234
|
+
def invalid_fields(fields)
|
235
|
+
results = fields.select { |field| field.split(":").first =~ /\W/ }
|
236
|
+
results.empty? ? nil : results
|
237
|
+
end
|
238
|
+
|
239
|
+
##
|
240
|
+
# Apply default field types.
|
241
|
+
#
|
242
|
+
# @param [Array<String>] fields
|
243
|
+
# Field names for generators.
|
244
|
+
#
|
245
|
+
# @return [Array<String>] fields with default types
|
246
|
+
#
|
247
|
+
def apply_default_fields(fields)
|
248
|
+
fields.map! { |field| field =~ /:/ ? field : "#{field}:string" }
|
249
|
+
end
|
250
|
+
|
251
|
+
# Returns the namespace for the project.
|
252
|
+
#
|
253
|
+
# @param [String] app
|
254
|
+
# folder name of application.
|
255
|
+
#
|
256
|
+
# @return [String] namespace for application.
|
257
|
+
#
|
258
|
+
# @example
|
259
|
+
# fetch_project_name
|
260
|
+
#
|
261
|
+
def fetch_project_name(app='app')
|
262
|
+
app_path = destination_root(app, 'app.rb')
|
263
|
+
@project_name = fetch_component_choice(:namespace) if @project_name.empty?
|
264
|
+
@project_name ||= begin
|
265
|
+
say "Autodetecting project namespace using folder name.", :red
|
266
|
+
say ""
|
267
|
+
detected_namespace = File.basename(destination_root('.')).gsub(/\W/, '_').camelize
|
268
|
+
say(<<-WARNING, :red)
|
269
|
+
From v0.11.0 on, applications should have a `namespace` setting
|
270
|
+
in their .components file. Please include a line like the following
|
271
|
+
in your .components file:
|
272
|
+
WARNING
|
273
|
+
say "\t:namespace: #{detected_namespace}", :yellow
|
274
|
+
say ""
|
275
|
+
|
276
|
+
detected_namespace
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
##
|
281
|
+
# Returns the app_name for the application at root.
|
282
|
+
#
|
283
|
+
# @param [String] app
|
284
|
+
# folder name of application.
|
285
|
+
#
|
286
|
+
# @return [String] class name for application.
|
287
|
+
#
|
288
|
+
# @example
|
289
|
+
# fetch_app_name('subapp')
|
290
|
+
#
|
291
|
+
def fetch_app_name(app='app')
|
292
|
+
app_path = destination_root(app, 'app.rb')
|
293
|
+
@app_name ||= File.read(app_path).scan(/class\s(.*?)\s</).flatten[0]
|
294
|
+
end
|
295
|
+
|
296
|
+
##
|
297
|
+
# Adds all the specified gems into the Gemfile for bundler.
|
298
|
+
#
|
299
|
+
# @param [Array<String>] gem_names
|
300
|
+
# Splat of gems to require in Gemfile.
|
301
|
+
# @param [Hash] options
|
302
|
+
# The options to pass to gem in Gemfile.
|
303
|
+
#
|
304
|
+
# @example
|
305
|
+
# require_dependencies('active_record')
|
306
|
+
# require_dependencies('mocha', 'bacon', :group => 'test')
|
307
|
+
# require_dependencies('json', :version => ">=1.2.3")
|
308
|
+
#
|
309
|
+
def require_dependencies(*gem_names)
|
310
|
+
options = gem_names.extract_options!
|
311
|
+
gem_names.reverse_each { |lib| insert_into_gemfile(lib, options) }
|
312
|
+
end
|
313
|
+
|
314
|
+
##
|
315
|
+
# Inserts a required gem into the Gemfile to add the bundler dependency.
|
316
|
+
#
|
317
|
+
# @param [String] name
|
318
|
+
# Name of gem to insert into Gemfile.
|
319
|
+
# @param [Hash] options
|
320
|
+
# Options to generate into Gemfile for gem.
|
321
|
+
#
|
322
|
+
# @example
|
323
|
+
# insert_into_gemfile(name)
|
324
|
+
# insert_into_gemfile(name, :group => 'test', :require => 'foo')
|
325
|
+
# insert_into_gemfile(name, :group => 'test', :version => ">1.2.3")
|
326
|
+
#
|
327
|
+
def insert_into_gemfile(name, options={})
|
328
|
+
after_pattern = options[:group] ? "#{options[:group].to_s.capitalize} requirements\n" : "Component requirements\n"
|
329
|
+
version = options.delete(:version)
|
330
|
+
gem_options = options.map { |k, v| k.to_s == 'require' && [true,false].include?(v) ? ":#{k} => #{v}" : ":#{k} => '#{v}'" }.join(", ")
|
331
|
+
write_option = gem_options.present? ? ", #{gem_options}" : ''
|
332
|
+
write_version = version.present? ? ", '#{version}'" : ''
|
333
|
+
include_text = "gem '#{name}'" << write_version << write_option << "\n"
|
334
|
+
inject_into_file('Gemfile', include_text, :after => after_pattern)
|
335
|
+
end
|
336
|
+
|
337
|
+
##
|
338
|
+
# Inserts an hook before or after load in our boot.rb.
|
339
|
+
#
|
340
|
+
# @param [String] include_text
|
341
|
+
# Text to include into hooks in boot.rb.
|
342
|
+
# @param [Symbol] where
|
343
|
+
# method hook to call from Tennpipes, i.e :after_load, :before_load.
|
344
|
+
#
|
345
|
+
# @example
|
346
|
+
# insert_hook("DataMapper.finalize", :after_load)
|
347
|
+
#
|
348
|
+
def insert_hook(include_text, where)
|
349
|
+
inject_into_file('config/boot.rb', " #{include_text}\n", :after => "Tennpipes.#{where} do\n")
|
350
|
+
end
|
351
|
+
|
352
|
+
##
|
353
|
+
# Inserts a middleware inside app.rb.
|
354
|
+
#
|
355
|
+
# @param [String] include_text
|
356
|
+
# Text to include into hooks in boot.rb.
|
357
|
+
#
|
358
|
+
# @example
|
359
|
+
# insert_middleware(ActiveRecord::ConnectionAdapters::ConnectionManagement)
|
360
|
+
#
|
361
|
+
def insert_middleware(include_text, app=nil)
|
362
|
+
name = app || (options[:name].present? ? @app_name.downcase : 'app')
|
363
|
+
inject_into_file("#{name}/app.rb", " use #{include_text}\n", :after => "Tennpipes::Application\n")
|
364
|
+
end
|
365
|
+
|
366
|
+
##
|
367
|
+
# Registers and creates initializer.
|
368
|
+
#
|
369
|
+
# @param [Symbol] name
|
370
|
+
# Name of the initializer.
|
371
|
+
# @param [String] data
|
372
|
+
# Text to generate into the initializer file.
|
373
|
+
#
|
374
|
+
# @example
|
375
|
+
# initializer(:test, "some stuff here")
|
376
|
+
# #=> generates 'lib/test_init.rb'
|
377
|
+
#
|
378
|
+
def initializer(name, data=nil)
|
379
|
+
@_init_name, @_init_data = name, data
|
380
|
+
register = data.present? ? " register #{name.to_s.underscore.camelize}Initializer\n" : " register #{name}\n"
|
381
|
+
inject_into_file destination_root("/app/app.rb"), register, :after => "Tennpipes::Application\n"
|
382
|
+
template "templates/initializer.rb.tt", destination_root("/lib/#{name}_initializer.rb") if data.present?
|
383
|
+
end
|
384
|
+
|
385
|
+
##
|
386
|
+
# Creates and inserts middleware.
|
387
|
+
# @param [Symbol, String] name
|
388
|
+
# Name of the middleware.
|
389
|
+
# @param [String] source
|
390
|
+
# Text to generate into the middleware file.
|
391
|
+
#
|
392
|
+
# @example
|
393
|
+
# middleware(:hello, "class Hello\nend")
|
394
|
+
# #=> generates 'lib/hello_middleware.rb'
|
395
|
+
#
|
396
|
+
def middleware(name, source)
|
397
|
+
create_file destination_root("lib/#{name}_middleware.rb"), source
|
398
|
+
insert_middleware name.to_s.underscore.camelize
|
399
|
+
end
|
400
|
+
|
401
|
+
##
|
402
|
+
# Insert the regired gem and add in boot.rb custom contribs.
|
403
|
+
#
|
404
|
+
# @param [String] contrib
|
405
|
+
# name of library from tennpipes-contrib
|
406
|
+
#
|
407
|
+
# @example
|
408
|
+
# require_contrib('auto_locale')
|
409
|
+
#
|
410
|
+
def require_contrib(contrib)
|
411
|
+
insert_into_gemfile 'tennpipes-contrib'
|
412
|
+
contrib = "require '" + File.join("tennpipes-contrib", contrib) + "'\n"
|
413
|
+
inject_into_file destination_root("/config/boot.rb"), contrib, :before => "\nTennpipes.load!"
|
414
|
+
end
|
415
|
+
|
416
|
+
##
|
417
|
+
# Return true if our project has test component.
|
418
|
+
#
|
419
|
+
def test?
|
420
|
+
fetch_component_choice(:test).to_s != 'none'
|
421
|
+
end
|
422
|
+
|
423
|
+
##
|
424
|
+
# Return true if we have a tiny skeleton.
|
425
|
+
#
|
426
|
+
def tiny?
|
427
|
+
File.exist?(destination_root('app/controllers.rb'))
|
428
|
+
end
|
429
|
+
|
430
|
+
##
|
431
|
+
# Run the bundler.
|
432
|
+
#
|
433
|
+
def run_bundler
|
434
|
+
say 'Bundling application dependencies using bundler...', :yellow
|
435
|
+
in_root { run 'bundle install' }
|
436
|
+
end
|
437
|
+
|
438
|
+
##
|
439
|
+
# Ask something to the user and receives a response.
|
440
|
+
#
|
441
|
+
# @param [String] statement
|
442
|
+
# String of statement to display for input.
|
443
|
+
# @param [String] default
|
444
|
+
# Default value for input.
|
445
|
+
# @param [String] color
|
446
|
+
# Name of color to display input.
|
447
|
+
#auto_locale
|
448
|
+
# @return [String] Input value
|
449
|
+
#
|
450
|
+
# @example
|
451
|
+
# ask("What is your name?")
|
452
|
+
# ask("Path for ruby", "/usr/local/bin/ruby") => "Path for ruby (leave blank for /usr/local/bin/ruby):"
|
453
|
+
#
|
454
|
+
def ask(statement, default=nil, color=nil)
|
455
|
+
default_text = default ? " (leave blank for #{default}):" : nil
|
456
|
+
say("#{statement}#{default_text} ", color)
|
457
|
+
result = $stdin.gets.strip
|
458
|
+
result.blank? ? default : result
|
459
|
+
end
|
460
|
+
|
461
|
+
##
|
462
|
+
# Raise SystemExit if the app does not exist.
|
463
|
+
#
|
464
|
+
# @param [String] app
|
465
|
+
# Directory name of application.
|
466
|
+
#
|
467
|
+
# @example
|
468
|
+
# check_app_existence 'app'
|
469
|
+
#
|
470
|
+
def check_app_existence(app)
|
471
|
+
unless File.exist?(destination_root(app))
|
472
|
+
say
|
473
|
+
say "================================================================="
|
474
|
+
say "Unable to locate '#{app.underscore.camelize}' application "
|
475
|
+
say "================================================================="
|
476
|
+
say
|
477
|
+
raise SystemExit
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
##
|
482
|
+
# Generates standard and tiny applications within a project.
|
483
|
+
#
|
484
|
+
# @param [String] app
|
485
|
+
# Name of application.
|
486
|
+
# @param [Boolean] tiny
|
487
|
+
# Boolean to generate a tiny structure.
|
488
|
+
#
|
489
|
+
# @example
|
490
|
+
# app_skeleton 'some_app'
|
491
|
+
# app_skeleton 'sub_app', true
|
492
|
+
#
|
493
|
+
def app_skeleton(app, tiny=false)
|
494
|
+
directory('app/', destination_root(app))
|
495
|
+
if tiny
|
496
|
+
template 'templates/controller.rb.tt', destination_root(app, 'controllers.rb')
|
497
|
+
@helper_name = DEFAULT_HELPER_NAME
|
498
|
+
template 'templates/helper.rb.tt', destination_root(app, 'helpers.rb')
|
499
|
+
@short_name = 'notifier'
|
500
|
+
template 'templates/mailer.rb.tt', destination_root(app, 'mailers.rb')
|
501
|
+
else
|
502
|
+
empty_directory destination_root(app, 'controllers')
|
503
|
+
empty_directory destination_root(app, 'helpers')
|
504
|
+
empty_directory destination_root(app, 'views')
|
505
|
+
empty_directory destination_root(app, 'views', 'layouts')
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
##
|
510
|
+
# Ensure that project name is valid, else raise an NameError.
|
511
|
+
#
|
512
|
+
# @param [String] name
|
513
|
+
# Name of project.
|
514
|
+
#
|
515
|
+
# @return [Exception] Exception with error message if not valid.
|
516
|
+
#
|
517
|
+
# @example
|
518
|
+
# valid_constant '1235Stuff'
|
519
|
+
# valid_constant '#Abc'
|
520
|
+
#
|
521
|
+
def valid_constant?(name)
|
522
|
+
if name =~ /^\d/
|
523
|
+
raise ::NameError, "Project name #{name} cannot start with numbers"
|
524
|
+
elsif name =~ /^\W/
|
525
|
+
raise ::NameError, "Project name #{name} cannot start with non-word character"
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
##
|
530
|
+
# Recognizes the path of application.
|
531
|
+
#
|
532
|
+
def recognize_path
|
533
|
+
options[:app] == '.' ? '/..' : '/../..'
|
534
|
+
end
|
535
|
+
|
536
|
+
##
|
537
|
+
# Creates an empty directory with .keep file
|
538
|
+
#
|
539
|
+
def empty_directory_with_keep_file(destination, config = {})
|
540
|
+
empty_directory(destination, config)
|
541
|
+
keep_file(destination)
|
542
|
+
end
|
543
|
+
|
544
|
+
##
|
545
|
+
# Creates an empty .keep file
|
546
|
+
#
|
547
|
+
def keep_file(destination)
|
548
|
+
create_file("#{destination}/.keep")
|
549
|
+
end
|
550
|
+
|
551
|
+
# Class methods for Thor generators to support the generators and component choices.
|
552
|
+
module ClassMethods
|
553
|
+
##
|
554
|
+
# Defines a class option to allow a component to be chosen and add to component type list.
|
555
|
+
# Also builds the available_choices hash of which component choices are supported.
|
556
|
+
#
|
557
|
+
# @param [Symbol] name
|
558
|
+
# Name of component.
|
559
|
+
# @param [String] caption
|
560
|
+
# Description of the component.
|
561
|
+
# @param [Hash] options
|
562
|
+
# Additional parameters for component choice.
|
563
|
+
#
|
564
|
+
# @example
|
565
|
+
# component_option :test, "Testing framework", :aliases => '-t', :choices => [:bacon, :shoulda]
|
566
|
+
#
|
567
|
+
def component_option(name, caption, options = {})
|
568
|
+
(@component_types ||= []) << name # TODO use ordered hash and combine with choices below
|
569
|
+
(@available_choices ||= Hash.new)[name] = options[:choices]
|
570
|
+
description = "The #{caption} component (#{options[:choices].join(', ')}, none)"
|
571
|
+
class_option name, :default => options[:default] || options[:choices].first, :aliases => options[:aliases], :desc => description
|
572
|
+
end
|
573
|
+
|
574
|
+
##
|
575
|
+
# Definitions for the available customizable components.
|
576
|
+
#
|
577
|
+
def defines_component_options(options = {})
|
578
|
+
[
|
579
|
+
[ :orm, 'database engine', { :aliases => '-d', :default => :none }],
|
580
|
+
[ :test, 'testing framework', { :aliases => '-t', :default => :none }],
|
581
|
+
[ :mock, 'mocking library', { :aliases => '-m', :default => :none }],
|
582
|
+
[ :script, 'javascript library', { :aliases => '-s', :default => :none }],
|
583
|
+
[ :renderer, 'template engine', { :aliases => '-e', :default => :none }],
|
584
|
+
[ :stylesheet, 'stylesheet engine', { :aliases => '-c', :default => :none }]
|
585
|
+
].each do |name, caption, opts|
|
586
|
+
opts[:default] = '' if options[:default] == false
|
587
|
+
component_option name, caption, opts.merge(:choices => Dir["#{File.dirname(__FILE__)}/components/#{name.to_s.pluralize}/*.rb"].map{|lib| File.basename(lib, '.rb').to_sym})
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
##
|
592
|
+
# Tell Tennpipes that for this Thor::Group it is a necessary task to run.
|
593
|
+
#
|
594
|
+
def require_arguments!
|
595
|
+
@require_arguments = true
|
596
|
+
end
|
597
|
+
|
598
|
+
##
|
599
|
+
# Return true if we need an arguments for our Thor::Group.
|
600
|
+
#
|
601
|
+
def require_arguments?
|
602
|
+
@require_arguments
|
603
|
+
end
|
604
|
+
|
605
|
+
##
|
606
|
+
# Returns the compiled list of component types which can be specified.
|
607
|
+
#
|
608
|
+
def component_types
|
609
|
+
@component_types
|
610
|
+
end
|
611
|
+
|
612
|
+
##
|
613
|
+
# Returns the list of available choices for the given component (including none).
|
614
|
+
#
|
615
|
+
# @param [Symbol] component
|
616
|
+
# The type of the component module.
|
617
|
+
#
|
618
|
+
# @return [Array<Symbol>] Array of component choices.
|
619
|
+
#
|
620
|
+
# @example
|
621
|
+
# available_choices_for :test
|
622
|
+
# => [:shoulda, :bacon, :riot, :minitest]
|
623
|
+
#
|
624
|
+
def available_choices_for(component)
|
625
|
+
@available_choices[component] + [:none]
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
end
|