├── .DS_Store ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── README.md ├── app ├── index.js └── templates │ ├── Bowerfile │ ├── Gemfile │ ├── apis │ ├── base.rb │ └── v1 │ │ ├── base.rb │ │ ├── defaults.rb │ │ └── person_api.rb │ ├── app │ ├── default.css.scss │ ├── home │ │ ├── home.coffee.erb │ │ └── home.tpl.html │ └── main.coffee │ ├── config │ ├── angular_template_assets.rb │ └── requirejs.yml │ ├── jasmine_rails │ ├── jasmine.yml │ ├── spec_helper.rb │ └── spec_runner.html.erb │ ├── protractor.config.js │ ├── spec │ ├── apis │ │ └── person_spec.rb │ └── javascripts │ │ ├── e2espec │ │ └── home_e2espec.coffee │ │ ├── helpers │ │ ├── .gitkeep │ │ └── angular_template_helper.coffee.erb │ │ └── spec │ │ └── home_unitspec.coffee │ └── view │ ├── application.html.erb │ └── index.html ├── controller ├── index.js └── templates │ ├── controller-template.coffee.erb │ ├── controller-template.spec.coffee │ └── controller-template.tpl.html ├── directive ├── index.js └── templates │ ├── directive-template.coffee.erb │ ├── directive-template.spec.coffee │ └── directive-template.tpl.html ├── filter ├── index.js └── templates │ ├── filter-template.coffee │ └── filter-template.spec.coffee ├── package.json ├── service ├── index.js └── templates │ ├── service-template.coffee │ └── service-template.spec.coffee └── test ├── test-creation.js └── test-load.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hung-phan/generator-rails-angular-require/a176294a371f718dd5a3167b5af84f37376c6ea3/.DS_Store -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | temp/ 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # generator-rails-angular-require 2 | 3 | > [Yeoman](http://yeoman.io) generator 4 | 5 | [![NPM](https://nodei.co/npm/generator-rails-angular-require.png?downloads=true)](https://nodei.co/npm/generator-rails-angular-require/) 6 | 7 | ## Getting Started 8 | 9 | To run this version of yeoman generator. First, make sure that you have already installed yeoman 10 | 11 | ```bash 12 | $ npm install -g yo 13 | ``` 14 | 15 | To install generator-rails-angular-require from npm, run: 16 | 17 | ```bash 18 | $ npm install -g generator-rails-angular-require 19 | ``` 20 | 21 | To be able to support template preprocessor, make sure you install the right `gem` first: 22 | 23 | ```bash 24 | $ gem install slim # for slim 25 | $ gem install haml # for haml 26 | ``` 27 | Other dependencies 28 | 29 | 1. SASS (gem install sass) 30 | 31 | 2. Compass (gem install compass) 32 | 33 | 34 | ## Usage for Rails 4.* 35 | 36 | Firstly, create Ruby on Rails project with normal rails command, but skip it bundle: 37 | 38 | ```bash 39 | $ rails new app-name --skip-bundle 40 | ``` 41 | 42 | Finally, initiate the generator: 43 | 44 | ```bash 45 | $ cd app-name 46 | $ yo rails-angular-require 47 | ``` 48 | 49 | Answer 'Yes' to all 'Overwrite' actions. Then config the 'config/database.yml' if you use different 50 | database than sqlite3. 51 | 52 | ## Assets compile 53 | 54 | Compile your assets before deploying to production server 55 | 56 | ```bash 57 | $ rake assets:precompile RAILS_ENV=production 58 | ``` 59 | 60 | ## Options 61 | 62 | Name: mongoid (for mongodb) 63 | 64 | add `--skip-active-record` option to your `rails new app --skip-active-record` command before selecting this option. 65 | 66 | ## Template 67 | 68 | I define all the templates with suffix __.tpl.*__ to load those into __$templateCache__, which make them testable 69 | with directives that rely on partial template. However, this is configurable by setting in `lib/jasmine_rails/spec_helper.rb`. 70 | 71 | ## Task 72 | 73 | ### Live reload 74 | 75 | For using livereload utility, firstly, install [guard](https://github.com/guard/guard-livereload). Then, use [rack-livereload](https://github.com/johnbintz/rack-livereload) 76 | or install [LiveReload Safari/Chrome extension](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) 77 | 78 | ```bash 79 | $ bundle exec guard # to run the guard server and enjoy coding 80 | ``` 81 | 82 | ### Testing 83 | 84 | Run: 85 | 86 | ```bash 87 | $ rails server 88 | ``` 89 | 90 | For unit testing, access `localhost:3000/specs` 91 | 92 | For e2e testing, run: 93 | 94 | ```bash 95 | $ protractor protractor.config.js 96 | ``` 97 | 98 | ### Subgenerators 99 | 100 | This also supports for subgenerator for `controller`, `filter`, `service`, and `directive` as well. Make sure you link them in your 101 | __main.js__ 102 | ```bash 103 | $ yo rails-angular-require:controller "name" #replace the name with your module name 104 | $ yo rails-angular-require:service "name" #replace the name with your module name 105 | $ yo rails-angular-require:directive "name" #replace the name with your module name 106 | $ yo rails-angular-require:filter "name" #replace the name with your module name 107 | 108 | ``` 109 | ## Structure 110 | 111 | ``` 112 | application/ 113 | |- app/ 114 | | |- apis/ 115 | | | |- v1/ 116 | | | | |- base.rb 117 | | | | |- person_api.rb 118 | | | |- base.rb 119 | | |- assets/ 120 | | | |- images/ 121 | | | |- javascripts/ 122 | | | | |- / 123 | | | | | |- codeModule.tpl.html # also support other templates like haml, and slim 124 | | | | | |- codeModule.js.coffee 125 | | | | |- application.js 126 | | | | |- main.js.coffee # main file 127 | | | |- stylesheets/ 128 | | | | |- application.css 129 | | |- controllers/ 130 | | |- helpers/ 131 | | |- mailers/ 132 | | |- models/ 133 | | |- views/ 134 | | | |- application/ 135 | | | | |- index.html # default template navigation by angular-ui-router 136 | | | |- layouts/ 137 | | | | |- jasmine_rails/ 138 | | | | | |- spec_runner.html.erb # jasmine spec runner template 139 | | | | |- application.html.erb 140 | |- bin/ 141 | |- config/ 142 | | |- initializers/ 143 | | | |- angular_template_assets.rb # Add template support 144 | | | |- bower_rails.rb # bower rails config 145 | | |- requirejs.yml # requirejs config file 146 | |- db/ 147 | |- lib/ 148 | | |- jasmine_rails/ 149 | | | |- spec_helper.rb # jasmine rails helper 150 | |- log/ 151 | |- public/ 152 | |- spec/ 153 | | |- javascripts/ 154 | | | |- helpers/ 155 | | | |- e2espec/ 156 | | | | |- codeSpec.{js, coffee} # suffix by _e2espec.{js, coffee} 157 | | | |- spec/ 158 | | | | |- codeSpec.{js, coffee} # suffix by _unitspec.{js, coffee} 159 | | | |- support/ 160 | | | | |- jasmine.yml # jasmine config 161 | |- test/ 162 | |- tmp/ 163 | |- vendor/ 164 | | |- assets/ 165 | | | |- bower_components/ 166 | | | | |- third libararies/ 167 | |- | |- bower.json 168 | |- Bowerfile # define all bower_components here 169 | |- config.ru 170 | |- Gemfile 171 | |- Gemfile.lock 172 | |- Guardfile # Guard file for livereload 173 | |- Rakefile 174 | |- README.rdoc 175 | ``` 176 | 177 | ## Contribution 178 | All contributions are welcomed. 179 | 180 | ## License 181 | 182 | [MIT License](http://en.wikipedia.org/wiki/MIT_License) 183 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var path = require('path'); 4 | var yeoman = require('yeoman-generator'); 5 | var yosay = require('yosay'); 6 | var chalk = require('chalk'); 7 | var magenta = chalk.magenta; 8 | var shell = require('shelljs'); 9 | 10 | var RailsAngularRequireGenerator = yeoman.generators.Base.extend({ 11 | init: function () { 12 | this.on('end', function () { 13 | if (!this.options['skip-install']) { 14 | console.log(magenta("Thank for using")); 15 | } 16 | }); 17 | }, 18 | 19 | askForCSSLibrary: function () { 20 | var cb = this.async(); 21 | 22 | var prompts = [{ 23 | type: 'checkbox', 24 | name: 'cssFile', 25 | message: 'What css library would you like to include?', 26 | choices: [ 27 | { name: 'SASS Button by Alexwolfe' , value: 'includeButtonCss' , checked: false }, 28 | { name: 'Animate SCSS' , value: 'includeAnimateCss' , checked: false }, 29 | { name: 'Bootstrap font-awesome' , value: 'includeFontAwesome' , checked: true } 30 | ] 31 | }]; 32 | 33 | this.prompt(prompts, function (props) { 34 | function includeCSS(css) { return props.cssFile.indexOf(css) !== -1; } 35 | 36 | // CSS 37 | this.includeButtonCss = includeCSS('includeButtonCss'); 38 | this.includeAnimateCss = includeCSS('includeAnimateCss'); 39 | this.includeFontAwesome = includeCSS('includeFontAwesome'); 40 | 41 | cb(); 42 | }.bind(this)); 43 | }, 44 | 45 | assForTemplateSupport: function() { 46 | var cb = this.async(); 47 | 48 | var prompts = [{ 49 | type: 'checkbox', 50 | name: 'htmlFile', 51 | message: 'What template support would you like to include?', 52 | choices: [ 53 | { name: 'HAML' , value: 'includeHaml' , checked: true }, 54 | { name: 'SLIM' , value: 'includeSlim' , checked: true } 55 | ] 56 | }]; 57 | 58 | this.prompt(prompts, function (props) { 59 | function includeTemplate(template) { return props.htmlFile.indexOf(template) !== -1; } 60 | 61 | // template support 62 | this.includeHaml = includeTemplate('includeHaml'); 63 | this.includeSlim = includeTemplate('includeSlim'); 64 | 65 | cb(); 66 | }.bind(this)); 67 | }, 68 | 69 | assForUtility: function() { 70 | var cb = this.async(); 71 | 72 | var prompts = [{ 73 | type: 'checkbox', 74 | name: 'tool', 75 | message: 'What tool support would you like to include?', 76 | choices: [ 77 | { name: 'Grape Rest' , value: 'includeGrape' , checked: true } , 78 | { name: 'therubyracer' , value: 'includeRubyRacer' , checked: false } , 79 | { name: 'mongoid (for mongodb)' , value: 'includeMongodb' , checked: false } , 80 | { name: 'Livereload' , value: 'includeLiveReload' , checked: false } 81 | ] 82 | }]; 83 | 84 | this.prompt(prompts, function (props) { 85 | function includeTool(tool) { return props.tool.indexOf(tool) !== -1; } 86 | 87 | // template support 88 | this.includeRubyRacer = includeTool('includeRubyRacer'); 89 | this.includeMongodb = includeTool('includeMongodb'); 90 | this.includeLiveReload = includeTool('includeLiveReload'); 91 | this.includeGrape = includeTool('includeGrape'); 92 | 93 | cb(); 94 | }.bind(this)); 95 | }, 96 | 97 | assForJSFile: function() { 98 | var cb = this.async(); 99 | 100 | var prompts = [{ 101 | type: 'checkbox', 102 | name: 'jsFile', 103 | message: 'What js library would you like to include?', 104 | choices: [ 105 | { name: 'Lodash.js' , value: 'includeLodash' , checked: true } , 106 | { name: 'Angular UI-Bootstrap' , value: 'includeUIBootstrap' , checked: false } , 107 | { name: 'Angular animate' , value: 'includeAngularAnimate' , checked: false } , 108 | { name: 'Modernizr' , value: 'includeModernizr' , checked: true } 109 | ] 110 | }]; 111 | 112 | this.prompt(prompts, function (props) { 113 | function includeJS(js) { return props.jsFile.indexOf(js) !== -1; } 114 | 115 | // JS 116 | this.includeLodash = includeJS('includeLodash'); 117 | this.includeUIBootstrap = includeJS('includeUIBootstrap'); 118 | this.includeAngularAnimate = includeJS('includeAngularAnimate'); 119 | this.includeModernizr = includeJS('includeModernizr'); 120 | cb(); 121 | }.bind(this)); 122 | }, 123 | 124 | processingGemfileTemplate: function() { 125 | console.log(magenta('Processing Gemfile')); 126 | this.template('Gemfile', 'tmp/yeoman/Gemfile'); 127 | }, 128 | 129 | gemfile: function() { 130 | //process Gemfile 131 | var path = 'tmp/yeoman/Gemfile', 132 | dest = 'Gemfile', 133 | file = this.readFileAsString(dest), 134 | insert = this.readFileAsString(path); 135 | 136 | //modify file before insert 137 | file = file.replace("# Use jquery as the JavaScript library\n", '') 138 | .replace("# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks\n", '') 139 | .replace("gem 'turbolinks'\n", ''); 140 | 141 | if (file.indexOf(insert) === -1) { 142 | this.write(dest, file + insert); 143 | } 144 | }, 145 | 146 | bundleInstall: function() { 147 | shell.exec("bundle install"); 148 | }, 149 | 150 | executeBowerTask: function() { 151 | console.log(magenta('Processing Bowerfile')); 152 | shell.exec("rails g bower_rails:initialize"); 153 | }, 154 | 155 | processingBowerfileTemplate: function() { 156 | this.template('Bowerfile', 'tmp/yeoman/Bowerfile'); 157 | }, 158 | 159 | bower: function() { 160 | //process bower 161 | var path = 'tmp/yeoman/Bowerfile', 162 | dest = 'Bowerfile', 163 | file = this.readFileAsString(dest), 164 | insert = this.readFileAsString(path); 165 | 166 | if (file.indexOf(insert) === -1) { 167 | this.write(dest, file + insert); 168 | } 169 | }, 170 | 171 | bowerInstall: function() { 172 | shell.exec("rake bower:install"); 173 | }, 174 | 175 | templateSupport: function() { 176 | console.log(magenta('Adding template support: angular_template_assets.rb')); 177 | this.template('config/angular_template_assets.rb', 'config/initializers/angular_template_assets.rb'); 178 | }, 179 | 180 | requirejs: function() { 181 | //requirejs config 182 | console.log(magenta('Requirejs config/requirejs.yml')); 183 | this.template('config/requirejs.yml', 'config/requirejs.yml'); 184 | }, 185 | 186 | mongodb: function() { 187 | if (this.includeMongodb) { 188 | shell.exec("rails g mongoid:config"); 189 | } 190 | }, 191 | 192 | grape: function() { 193 | if (this.includeGrape) { 194 | console.log(magenta('Insert Grape API into config/routes.rb')); 195 | var path = 'config/routes.rb', 196 | hook = 'Rails.application.routes.draw do\n', 197 | file = this.readFileAsString(path), 198 | insert = " mount APIS::Base => '/api'\n"; 199 | 200 | if (file.indexOf(insert) === -1) { 201 | this.write(path, file.replace(hook, hook + insert)); 202 | } 203 | } 204 | }, 205 | 206 | grapeInitFile: function() { 207 | if (this.includeGrape) { 208 | this.directory('apis', 'app/apis'); 209 | } 210 | }, 211 | 212 | autoLoadPath: function() { 213 | //include config into config/application.rb 214 | var path = 'config/application.rb', 215 | hook = 'class Application < Rails::Application\n', 216 | file = this.readFileAsString(path), 217 | insert = ' config.autoload_paths += %W(#{config.root}/lib #{Rails.root}/app)\n'; 218 | 219 | if (file.indexOf(insert) === -1) { 220 | this.write(path, file.replace(hook, hook + insert)); 221 | } 222 | }, 223 | 224 | jasmineInit: function() { 225 | console.log(magenta('Integrate jasmine for frontend testing')); 226 | shell.exec("rails generate jasmine_rails:install"); 227 | }, 228 | 229 | jasmine: function() { 230 | //init template and rooting at localhost:3000/specs 231 | this.mkdir('spec/javascripts/helpers'); 232 | this.mkdir('spec/javascripts/spec'); 233 | this.copy('jasmine_rails/jasmine.yml', 'spec/javascripts/support/jasmine.yml'); 234 | this.copy('spec/javascripts/helpers/angular_template_helper.coffee.erb', 'spec/javascripts/helpers/angular_template_helper.coffee.erb'); 235 | this.copy('spec/javascripts/spec/home_unitspec.coffee', 'spec/javascripts/spec/home_unitspec.coffee'); 236 | this.copy('jasmine_rails/spec_helper.rb', 'lib/jasmine_rails/spec_helper.rb'); 237 | this.copy('jasmine_rails/spec_runner.html.erb', 'app/views/layouts/jasmine_rails/spec_runner.html.erb'); 238 | }, 239 | 240 | rspecRails: function() { 241 | shell.exec("rails generate rspec:install"); 242 | }, 243 | 244 | guardRspec: function() { 245 | shell.exec("guard init rspec"); 246 | }, 247 | 248 | e2eTesting: function() { 249 | //process e2e testing 250 | console.log(magenta('Processing e2e testing template')); 251 | this.copy('protractor.config.js', 'protractor.config.js'); 252 | this.copy('spec/javascripts/e2espec/home_e2espec.coffee', 'spec/javascripts/e2espec/home_e2espec.coffee'); 253 | }, 254 | 255 | guard: function() { 256 | //process livereload 257 | if (this.includeLiveReload) { 258 | console.log(magenta('Add livereload utility')); 259 | shell.exec("guard init livereload"); 260 | } 261 | }, 262 | 263 | view: function () { 264 | console.log(magenta('Processing view')); 265 | this.copy('view/index.html', 'app/views/application/index.html'); 266 | this.template('view/application.html.erb', 'app/views/layouts/application.html.erb'); 267 | }, 268 | 269 | appJs: function() { 270 | console.log(magenta('Processing app js')); 271 | var path = 'app/assets/javascripts/application.js', 272 | file = this.readFileAsString(path); 273 | 274 | //modify file before insert 275 | file = file.replace("//= require jquery\n", '') 276 | .replace("//= require jquery_ujs\n", '') 277 | .replace("//= require turbolinks\n", '') 278 | .replace("//= require_tree .", '//= require main'); 279 | 280 | this.write(path, file); 281 | this.template('app/main.coffee', 'app/assets/javascripts/main.coffee'); 282 | this.directory('app/home', 'app/assets/javascripts/home'); 283 | }, 284 | 285 | routes: function() { 286 | console.log(magenta('Processing config/routes.rb')); 287 | var path = 'config/routes.rb', 288 | hook = 'Rails.application.routes.draw do\n', 289 | file = this.readFileAsString(path), 290 | insert = " root 'application#index'\n"; 291 | 292 | if (file.indexOf(insert) === -1) { 293 | this.write(path, file.replace(hook, hook + insert)); 294 | } 295 | }, 296 | 297 | rspecHelper: function() { 298 | console.log(magenta('Update spec/rails_helper.rb for DatabaseCleaner and Grape api')); 299 | var path = 'spec/rails_helper.rb', 300 | hook = 'RSpec.configure do |config|\n', 301 | file = this.readFileAsString(path), 302 | insert = ' config.include RSpec::Rails::RequestExampleGroup, type: :request, file_path: /spec\\/apis/\n' + 303 | ' config.before(:suite) do\n' + 304 | ' DatabaseCleaner.strategy = :transaction\n' + 305 | ' DatabaseCleaner.clean_with(:truncation)\n' + 306 | ' end\n'; 307 | 308 | if (file.indexOf(insert) === -1) { 309 | this.write(path, file.replace(hook, hook + insert)); 310 | } 311 | }, 312 | 313 | copySpecs: function() { 314 | this.copy('spec/apis/person_spec.rb', 'spec/apis/person_spec.rb'); 315 | }, 316 | 317 | defaultStylesheet: function() { 318 | console.log(magenta('Copy default.css.scss file')); 319 | this.template('app/default.css.scss', 'app/assets/stylesheets/default.css.scss'); 320 | }, 321 | 322 | stylesheets: function() { 323 | console.log(magenta('Processing app stylesheets')); 324 | var extra = ''; 325 | if (this.includeButtonCss) { 326 | extra += " *= require Buttons/scss/buttons.scss\n"; 327 | } 328 | if (this.includeAnimateCss) { 329 | extra += " *= require animate-sass/_animate.scss\n"; 330 | } 331 | var path = 'app/assets/stylesheets/application.css', 332 | hook = ' *= require_tree .\n', 333 | file = this.readFileAsString(path), 334 | insert = ' *= require default\n' + extra + ' *= require_tree .\n'; 335 | 336 | if (file.indexOf(insert) === -1) { 337 | this.write(path, file.replace(hook, insert)); 338 | } 339 | } 340 | }); 341 | 342 | module.exports = RailsAngularRequireGenerator; 343 | -------------------------------------------------------------------------------- /app/templates/Bowerfile: -------------------------------------------------------------------------------- 1 | # auto generate bower assets<% if (includeLodash) { %> 2 | # 3 | asset 'lodash'<% } %> 4 | asset 'angular' 5 | asset 'angular-mocks' 6 | asset 'restangular' 7 | asset 'angular-ui-router', '0.2.13'<% if (includeUIBootstrap) { %> 8 | asset 'angular-bootstrap'<% } %><% if (includeAngularAnimate) { %> 9 | asset 'angular-animate'<% } %><% if (includeButtonCss) { %> 10 | asset 'Buttons'<% } %><% if (includeAnimateCss) { %> 11 | asset 'animate-sass'<% } %> 12 | -------------------------------------------------------------------------------- /app/templates/Gemfile: -------------------------------------------------------------------------------- 1 | # twitter bootstrap 2 | gem 'bootstrap-sass' 3 | # auto prefixer 4 | gem 'autoprefixer-rails' 5 | # bower dependencies manager for rails 6 | gem 'bower-rails'<% if (includeModernizr) { %> 7 | # modernizr 8 | gem 'modernizr-rails', '~> 2.7.1'<% } %> 9 | # requirejs 10 | gem 'requirejs-rails'<% if (includeButtonCss) { %> 11 | # button sass 12 | gem 'compass-rails'<% } %><% if (includeFontAwesome) { %> 13 | # font awesome 14 | gem 'font-awesome-rails'<% } %><% if (includeMongodb) { %> 15 | # mongoid 16 | gem 'mongoid'<% } %> 17 | 18 | group :development, :test do 19 | gem 'quiet_assets' 20 | gem 'faker' # https://github.com/stympy/faker 21 | gem 'factory_girl_rails' # https://github.com/thoughtbot/factory_girl_rails 22 | gem 'database_cleaner' 23 | gem 'rspec' 24 | gem 'rspec-rails' # https://github.com/rspec/rspec-rails 25 | gem 'guard' 26 | gem 'guard-rspec' 27 | gem 'shoulda-matchers' # https://github.com/thoughtbot/shoulda-matchers 28 | gem 'shoulda-callback-matchers', '~> 1.0' 29 | gem 'spring-commands-rspec' 30 | gem 'jasmine' 31 | gem 'jasmine-rails' 32 | gem 'mailcatcher' 33 | gem 'did_you_mean'<% if (includeLiveReload) { %> 34 | gem 'guard-livereload', require: false<% } %> 35 | end 36 | group :development do 37 | gem "better_errors" 38 | gem "binding_of_caller" 39 | gem 'meta_request' 40 | end 41 | group :test do 42 | gem 'airborne' # api test 43 | end 44 | <% if (includeHaml) { %> 45 | # haml template 46 | gem 'haml'<% } %><% if (includeSlim) { %> 47 | # slim template 48 | gem 'slim'<% } %><% if (includeGrape) { %> 49 | # grape api 50 | gem 'grape-entity' 51 | gem 'grape'<% } %><% if (includeRubyRacer) { %> 52 | # embed the V8 Javascript Interpreter into Ruby 53 | gem 'therubyracer', platforms: :ruby<% } %> 54 | -------------------------------------------------------------------------------- /app/templates/apis/base.rb: -------------------------------------------------------------------------------- 1 | module APIS 2 | class Base < Grape::API 3 | mount APIS::V1::Base 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/templates/apis/v1/base.rb: -------------------------------------------------------------------------------- 1 | module APIS 2 | module V1 3 | class Base < Grape::API 4 | # base api for v1 5 | mount APIS::V1::PersonApi 6 | end 7 | end 8 | end 9 | 10 | -------------------------------------------------------------------------------- /app/templates/apis/v1/defaults.rb: -------------------------------------------------------------------------------- 1 | module APIS 2 | module V1 3 | module Defaults 4 | # if you're using Grape outside of Rails, you'll have to use Module#included hook 5 | extend ActiveSupport::Concern 6 | 7 | included do 8 | # common Grape settings 9 | version 'v1' 10 | format :json 11 | 12 | # global handler for simple not found case 13 | rescue_from ActiveRecord::RecordNotFound do |e| 14 | error_response(message: e.message, status: 404) 15 | end 16 | 17 | # global exception handler, used for error notifications 18 | rescue_from :all do |e| 19 | if Rails.env.development? 20 | raise e 21 | else 22 | error_response(message: e.message, status: 500) 23 | end 24 | end 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /app/templates/apis/v1/person_api.rb: -------------------------------------------------------------------------------- 1 | module APIS 2 | module V1 3 | class PersonApi < Grape::API 4 | include APIS::V1::Defaults 5 | 6 | # GET /api/v1/people 7 | resource :people do 8 | # GET /api/v1/people 9 | desc "Get all people" 10 | get "/" do 11 | [ 12 | { 13 | firstName: 'John', 14 | lastName: 'Smith', 15 | age: 25, 16 | address: { 17 | streetAddress: '21 2nd Street', 18 | city: 'New York', 19 | state: 'NY', 20 | postalCode: '10021' 21 | }, 22 | phoneNumber: [ 23 | { 24 | type: 'home', 25 | number: '212 555-1234' 26 | }, 27 | { 28 | type: 'fax', 29 | number: '646 555-4567' 30 | } 31 | ] 32 | } 33 | ] 34 | end 35 | end 36 | end 37 | end 38 | end 39 | 40 | -------------------------------------------------------------------------------- /app/templates/app/default.css.scss: -------------------------------------------------------------------------------- 1 | @import "bootstrap-sprockets"; 2 | @import "bootstrap";<% if (includeFontAwesome) { %> 3 | @import "font-awesome";<% } %> 4 | 5 | $xs-small-screen: 320px; 6 | $small-screen: 480px; 7 | $medium-screen: 768px; 8 | $large-screen: 992px; 9 | $xs-large-screen: 1200px; 10 | 11 | // Custom mixins 12 | 13 | @mixin utility-responsive($width) { 14 | @media only screen and (min-width: $width) { @content; } 15 | } 16 | 17 | // @include responsive(wide-screens) { width: 80%; } 18 | 19 | @mixin custom-retinize($file, $type, $width, $height) { 20 | background-image: image-url('' + $file + '.' + $type); 21 | 22 | @media (-webkit-min-device-pixel-ratio: 1.5), 23 | (min--moz-device-pixel-ratio: 1.5), 24 | (-o-min-device-pixel-ratio: 3/2), 25 | (min-device-pixel-ratio: 1.5), 26 | (min-resolution: 1.5dppx) { 27 | & { 28 | background-image: image-url('' + $file + '.' + $type); 29 | -webkit-background-size: $width $height; 30 | -moz-background-size: $width $height; 31 | background-size: $width $height; 32 | } 33 | } 34 | } 35 | 36 | // how to use @include retinize('icon-dribbble', 'png', 24px, 24px); 37 | 38 | @mixin custom-background-body($file, $type) { 39 | background: image-url('' + $file + '.' + $type) no-repeat center center fixed; 40 | -webkit-background-size: cover; 41 | -moz-background-size: cover; 42 | -o-background-size: cover; 43 | background-size: cover; 44 | } 45 | 46 | // how to use @include retinize('icon-dribbble', 'png', 24px, 24px); 47 | @mixin custom-rounded($radius) { 48 | -webkit-border-radius: $radius; 49 | -moz-border-radius: $radius; 50 | border-radius: $radius; 51 | } 52 | @mixin custom-shadow($x, $y, $z, $blur, $color) { 53 | -webkit-box-shadow: $x $y $z $blur $color; 54 | -moz-box-shadow: $x $y $z $blur $color; 55 | box-shadow: $x $y $z $blur $color; 56 | } 57 | @mixin custom-shadow-inset($x, $y, $z, $blur, $color) { 58 | -webkit-box-shadow: inset $x $y $z $blur $color; 59 | -moz-box-shadow: inset $x $y $z $blur $color; 60 | box-shadow: inset $x $y $z $blur $color; 61 | } 62 | @mixin custom-transition($property) { 63 | -webkit-transition: $property .2s ease; 64 | -moz-transition: $property .2s ease; 65 | -o-transition: $property .2s ease; 66 | transition: $property .2s ease; 67 | } 68 | @mixin custom-box-sizing { 69 | -webkit-box-sizing: border-box; 70 | -moz-box-sizing: border-box; 71 | box-sizing: border-box; 72 | } 73 | @mixin custom-linear-gradient($from, $to) { 74 | /* Fallback for sad browsers */ 75 | background-color: $to; 76 | /* Mozilla Firefox */ 77 | background-image:-moz-linear-gradient($from, $to); 78 | /* Opera */ 79 | background-image:-o-linear-gradient($from, $to); 80 | /* WebKit (Chrome 11+) */ 81 | background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, $from), color-stop(1, $to)); 82 | /* WebKit (Safari 5.1+, Chrome 10+) */ 83 | background-image: -webkit-linear-gradient($from, $to); 84 | /* IE10 */ 85 | background-image: -ms-linear-gradient($from, $to); 86 | /* W3C */ 87 | background-image: linear-gradient($from, $to); 88 | } 89 | 90 | @mixin text-highlight-selection($background, $color) { 91 | ::selection { background: $background; color: $color; text-shadow: none; } 92 | ::-webkit-selection{ background: $background; color: $color; text-shadow: none; } 93 | ::-moz-selection{ background: $background; color: $color; text-shadow: none; } 94 | } 95 | 96 | @mixin bootstrap-column($name, $percent-width) { 97 | $grid-width: $grid-columns * $percent-width / 100; 98 | 99 | .col-lg-#{$name} { @include make-lg-column($grid-width); } 100 | .col-md-#{$name} { @include make-md-column($grid-width); } 101 | .col-sm-#{$name} { @include make-sm-column($grid-width); } 102 | .col-xs-#{$name} { @include make-xs-column($grid-width); } 103 | } 104 | 105 | // use @include bootstrap-column(15, 20); 106 | -------------------------------------------------------------------------------- /app/templates/app/home/home.coffee.erb: -------------------------------------------------------------------------------- 1 | define [ 2 | "angular" 3 | "angular-ui-router" 4 | ], (angular) -> 5 | 6 | #config path for home page 7 | angular.module("homeModule", ["ui.router"]).config([ 8 | "$stateProvider" 9 | ($stateProvider) -> 10 | $stateProvider.state "home", 11 | url: "/" 12 | templateUrl: "<%= asset_path("home/home.tpl.html") %>" 13 | controller: "HomeController" 14 | 15 | ]).controller "HomeController", [ 16 | "$scope" 17 | "$location" 18 | ($scope, $location) -> 19 | 20 | # initialize 21 | $scope.pageTitle = "dummy" 22 | ] 23 | -------------------------------------------------------------------------------- /app/templates/app/home/home.tpl.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 14 |

15 | Home module testing {{pageTitle}} 16 | 17 |

18 |
19 |
20 |

'Allo, 'Allo!

21 |

Always a pleasure scaffolding your apps.

22 |

23 | Splendid! 24 |

25 |
26 |
27 |
28 |

HTML5 Boilerplate

29 |

HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.

30 |

Bootstrap

31 |

Sleek, intuitive, and powerful mobile first front-end framework for faster and easier web development.

32 |

Modernizr

33 |

Modernizr is an open-source JavaScript library that helps you build the next generation of HTML5 and CSS3-powered websites.

34 |
35 |
36 |

AngularJs

37 |

AngularJS lets you write client-side web applications as if you had a smarter browser. It lets you use good old HTML (or HAML, Jade and friends!) as your template language and lets you extend HTML’s syntax to express your application’s components clearly and succinctly. It automatically synchronizes data from your UI (view) with your JavaScript objects (model) through 2-way data binding. To help you structure your application better and make it easy to test, AngularJS teaches the browser how to do dependency injection and inversion of control. Oh yeah and it also helps with server-side communication, taming async callbacks with promises and deferreds; and makes client-side navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all: it makes development fun!

38 |

RequireJs

39 |

RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.

40 |
41 |
42 | 45 |
46 | -------------------------------------------------------------------------------- /app/templates/app/main.coffee: -------------------------------------------------------------------------------- 1 | require [ 2 | "angular" 3 | "jquery" 4 | "jquery_ujs" 5 | "restangular"<% if (includeAngularAnimate) { %> 6 | "angular-animate"<% } %> 7 | "angular-ui-router"<% if (includeUIBootstrap) { %> 8 | "ui-bootstrap-tpls"<% } %><% if (includeLodash) { %> 9 | "lodash"<% } %> 10 | "bootstrap" 11 | "home/home" 12 | ], (angular) -> 13 | "use strict" 14 | 15 | #App Module 16 | angular.element(document).ready -> 17 | 18 | #smart works go here 19 | $html = angular.element("html") 20 | angular.module("webApp", [ 21 | "ui.router" 22 | "restangular"<% if (includeUIBootstrap) { %> 23 | "ui.bootstrap"<% } %><% if (includeAngularAnimate) { %> 24 | "ngAnimate"<% } %> 25 | "homeModule" 26 | ]).config ["$urlRouterProvider", "$provide", ($urlRouterProvider, $provide) -> 27 | $urlRouterProvider.otherwise "/" 28 | 29 | # change configure to use [[ to be the interpolation ([[2 + 2]]) 30 | 31 | #$interpolateProvider.startSymbol('[['); 32 | #$interpolateProvider.endSymbol(']]'); 33 | 34 | # add safeApply function for $rootScope - called by $scope.$root.safeApply(fn) 35 | $provide.decorator "$rootScope", ["$delegate", ($delegate) -> 36 | $delegate.safeApply = (fn) -> 37 | phase = $delegate.$$phase 38 | if phase is "$apply" or phase is "$digest" 39 | fn() if fn and typeof fn is "function" 40 | else 41 | $delegate.$apply fn 42 | return 43 | 44 | return $delegate 45 | ] 46 | ] 47 | 48 | #bootstrap model 49 | angular.bootstrap $html, ["webApp"] 50 | -------------------------------------------------------------------------------- /app/templates/config/angular_template_assets.rb: -------------------------------------------------------------------------------- 1 | # Template support 2 | <% if (includeHaml) { %> 3 | # For HAML or other Tilt-compatible engine, use Tilt's adapters 4 | Rails.application.assets.register_engine('.haml', Tilt::HamlTemplate)<% } %><% if (includeSlim) { %> 5 | # For Slim, remember also to add gem to Gemfile 6 | Rails.application.assets.register_engine('.slim', Slim::Template)<% } %> 7 | -------------------------------------------------------------------------------- /app/templates/config/requirejs.yml: -------------------------------------------------------------------------------- 1 | paths: 2 | 'angular': 'angular/angular' 3 | # require angular mocks for testing 4 | 'angular-mocks': 'angular-mocks/angular-mocks' 5 | # require restangular for easily handling sending and receiving request 6 | 'restangular': 'restangular/dist/restangular'<% if (includeAngularAnimate) { %> 7 | # require angular animate for easily handling animation. I recommend to use this with tweenmax (bower install --save greensock) 8 | 'angular-animate': 'angular-animate/angular-animate'<% } %> 9 | # require angular for better handling and binding controller 10 | 'angular-ui-router': 'angular-ui-router/release/angular-ui-router'<% if (includeUIBootstrap) { %> 11 | # require ui-bootstrap with the embeded template [http://angular-ui.github.io/bootstrap/] 12 | 'ui-bootstrap-tpls': 'angular-bootstrap/ui-bootstrap-tpls'<% }%> 13 | # require jquery 14 | 'jquery': 'jquery' 15 | 'jquery_ujs': 'jquery_ujs'<% if (includeLodash) { %> 16 | # require lodash 17 | 'lodash': 'lodash/lodash'<% } %> 18 | # require bootstrap.js to make bootstrap components work 19 | 'bootstrap': 'bootstrap-sprockets' 20 | # jasmine boostrap 21 | 'jasmine': 'jasmine' 22 | 'jasmine-html': 'jasmine-html' 23 | 'jasmine-specs': 'jasmine-specs' 24 | 'json2': 'json2' 25 | 'boot': 'boot' 26 | shim: 27 | 'jquery_ujs': ['jquery'] 28 | 'angular': 29 | exports: 'angular' 30 | deps: ['jquery'] 31 | 'angular-mocks': ['angular']<% if (includeLodash) { %> 32 | 'lodash': 33 | exports: '_'<% } %> 34 | 'restangular': ['angular']<% if (includeAngularAnimate) { %> 35 | 'angular-animate': ['angular']<% } %> 36 | 'angular-ui-router': ['angular']<% if (includeUIBootstrap) { %> 37 | 'ui-bootstrap-tpls': ['angular']<% } %> 38 | 'bootstrap': ['jquery'] 39 | # jasmine test bootstrap 40 | 'jasmine': 41 | exports: 'window.jasmineRequire' 42 | 'jasmine-html': 43 | deps: ['jasmine'] 44 | exports: 'window.jasmineRequire' 45 | 'jasmine-specs': ['boot'] 46 | 'boot': 47 | deps: ['jasmine', 'jasmine-html'] 48 | exports: 'window.jasmineRequire' 49 | -------------------------------------------------------------------------------- /app/templates/jasmine_rails/jasmine.yml: -------------------------------------------------------------------------------- 1 | # path to parent directory of src_files 2 | # relative path from Rails.root 3 | # defaults to app/assets/javascripts 4 | src_dir: "app/assets/javascripts" 5 | 6 | # path to parent directory of css_files 7 | # relative path from Rails.root 8 | # defaults to app/assets/stylesheets 9 | css_dir: "app/assets/stylesheets" 10 | 11 | # list of file expressions to include as source files 12 | # relative path from src_dir 13 | src_files: 14 | #- "application.{js.coffee,js,coffee}" 15 | 16 | # list of file expressions to include as css files 17 | # relative path from css_dir 18 | css_files: 19 | 20 | # path to parent directory of spec_files 21 | # relative path from Rails.root 22 | # defaults to spec/javascripts 23 | spec_dir: spec/javascripts 24 | 25 | # list of file expressions to include as helpers into spec runner 26 | # relative path from spec_dir 27 | helpers: 28 | - "helpers/**/*.{js.coffee,js,coffee}" 29 | 30 | # list of file expressions to include as specs into spec runner 31 | # relative path from spec_dir 32 | spec_files: 33 | - "**/*_unitspec.{js.coffee,js,coffee}" 34 | 35 | # path to directory of temporary files 36 | # (spec runner and asset cache) 37 | # defaults to tmp/jasmine 38 | tmp_dir: "tmp/jasmine" 39 | -------------------------------------------------------------------------------- /app/templates/jasmine_rails/spec_helper.rb: -------------------------------------------------------------------------------- 1 | module JasmineRails 2 | module SpecHelper 3 | include ActionView::Helpers::JavaScriptHelper 4 | # Gives us access to the require_js_include_tag helper 5 | include RequirejsHelper 6 | 7 | def spec_files 8 | spec_files = [] 9 | env = Rails.application.assets 10 | env.each_logical_path do |lp| 11 | if lp =~ %r{^spec/.*_unitspec\.js$} 12 | file_name = lp.split "." 13 | file_name.pop() 14 | spec_files << (file_name.join ".") 15 | end 16 | end 17 | spec_files 18 | end 19 | 20 | def asset_to_s path 21 | Rails.application.assets[path].body.html_safe 22 | end 23 | 24 | def templates 25 | Hash[ 26 | Rails.application.assets.each_logical_path. 27 | select { |file| file.end_with?('tpl.html') }. 28 | map { |file| [file, ActionController::Base.helpers.asset_path(file)] } 29 | ] 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/templates/jasmine_rails/spec_runner.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Jasmine Specs 6 | <%= stylesheet_link_tag *jasmine_css_files %> 7 | <%= requirejs_include_tag %> 8 | 9 | 10 |
11 | <%= yield %> 12 | <%= javascript_tag do %> 13 | require(['boot', 'json2', 'helpers/angular_template_helper'], function() { 14 | require(<%= raw spec_files %>, function() { 15 | window.onload(); 16 | }); 17 | }); 18 | <% end %> 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/templates/protractor.config.js: -------------------------------------------------------------------------------- 1 | require('coffee-script'); 2 | 3 | exports.config = { 4 | seleniumPort: null, 5 | baseUrl: 'http://localhost:3000', 6 | rootElement: 'html', 7 | capabilities: { 8 | 'browserName': 'chrome' 9 | }, 10 | jasmineNodeOpts: { 11 | showColors: true 12 | }, 13 | specs: ['spec/javascripts/e2espec/**/*_e2espec.{js,coffee}'] 14 | }; 15 | -------------------------------------------------------------------------------- /app/templates/spec/apis/person_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | describe 'APIS::V1::PersonApi' do 4 | describe 'GET /api/v1/people' do 5 | it 'should get an array of people' do 6 | get '/api/v1/people' 7 | 8 | expect_json_types :array 9 | expect_json('0', { 10 | firstName: 'John', 11 | lastName: 'Smith', 12 | age: 25, 13 | address: { 14 | streetAddress: '21 2nd Street', 15 | city: 'New York', 16 | state: 'NY', 17 | postalCode: '10021' 18 | }, 19 | phoneNumber: [ 20 | { 21 | type: 'home', 22 | number: '212 555-1234' 23 | }, 24 | { 25 | type: 'fax', 26 | number: '646 555-4567' 27 | } 28 | ] 29 | }) 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/templates/spec/javascripts/e2espec/home_e2espec.coffee: -------------------------------------------------------------------------------- 1 | describe "home page title", -> 2 | ptor = protractor.getInstance() 3 | it "should not be Dummy", -> 4 | ptor.get "/#" 5 | expect(ptor.getTitle()).not.toBe "Dummy" 6 | return 7 | 8 | return 9 | -------------------------------------------------------------------------------- /app/templates/spec/javascripts/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hung-phan/generator-rails-angular-require/a176294a371f718dd5a3167b5af84f37376c6ea3/app/templates/spec/javascripts/helpers/.gitkeep -------------------------------------------------------------------------------- /app/templates/spec/javascripts/helpers/angular_template_helper.coffee.erb: -------------------------------------------------------------------------------- 1 | <% extend JasmineRails::SpecHelper %> 2 | define [ 3 | "angular" 4 | ], (angular) -> 5 | <% templates.each do |module_name, path_asset| %> 6 | angular.module("<%= module_name %>", []).run ["$templateCache", ($templateCache) -> 7 | $templateCache.put "<%= path_asset %>", """<%= asset_to_s module_name %>""" 8 | ] 9 | <% end %> 10 | return 11 | -------------------------------------------------------------------------------- /app/templates/spec/javascripts/spec/home_unitspec.coffee: -------------------------------------------------------------------------------- 1 | define [ 2 | "angular-mocks" 3 | "home/home" 4 | ], -> 5 | describe "controller title", -> 6 | # initialize 7 | $scope = undefined 8 | $location = undefined 9 | homeController = undefined 10 | 11 | beforeEach -> 12 | module("homeModule") 13 | inject((_$injector_, _$rootScope_) -> 14 | $scope = _$rootScope_.$new() 15 | $location = _$injector_.get("$location") 16 | homeController = _$injector_.get("$controller")("HomeController", 17 | '$scope': $scope 18 | '$location': $location 19 | ) 20 | return 21 | ) 22 | return 23 | 24 | it "should be equal dummy", -> 25 | expect($scope.pageTitle).toEqual "dummy" 26 | return 27 | return 28 | return 29 | -------------------------------------------------------------------------------- /app/templates/view/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= _.slugify(appname) %> 5 | 6 | 7 | <%%= stylesheet_link_tag 'application', media: 'all' %><% if (includeModernizr) { %> 8 | <%%= javascript_include_tag 'modernizr' %><% } %> 9 | <%%= requirejs_include_tag 'application' %> 10 | <%%= csrf_meta_tags %> 11 | 12 | 13 | 14 | <%%= yield %> 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/templates/view/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /controller/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | var fs = require('fs'); 5 | 6 | var ControllerGenerator = module.exports = function ControllerGenerator(args, options, config) { 7 | // By calling `NamedBase` here, we get the argument to the subgenerator call 8 | // as `this.name`. 9 | yeoman.generators.NamedBase.apply(this, arguments); 10 | 11 | console.log('You just create the sub controller with the argument ' + this.name + '. Please link it with your main controller'); 12 | this.uppercaseName = this.name.charAt(0).toUpperCase() + this.name.slice(1); 13 | this.asset_path = '<%= asset_path("' + this.name + '/' + this.name + '.tpl.html") %>'; 14 | }; 15 | 16 | util.inherits(ControllerGenerator, yeoman.generators.NamedBase); 17 | 18 | ControllerGenerator.prototype.files = function files() { 19 | var prefix = 'app/assets/javascripts/' + this.name + '/'; 20 | this.template('controller-template.coffee.erb' , prefix + this.name + '.coffee.erb'); 21 | this.template('controller-template.spec.coffee' , 'spec/javascripts/spec/' + this.name + '_unitspec.coffee'); 22 | this.template('controller-template.tpl.html' , prefix + this.name + '.tpl.html'); 23 | }; 24 | -------------------------------------------------------------------------------- /controller/templates/controller-template.coffee.erb: -------------------------------------------------------------------------------- 1 | define [ 2 | "angular" 3 | "angular-ui-router" 4 | ], (angular) -> 5 | 6 | #config path for <%= name %> module 7 | angular.module("<%= name %>Module", ["ui.router"]).config([ 8 | "$stateProvider" 9 | ($stateProvider) -> 10 | $stateProvider.state "<%= name %>", 11 | url: "/<%= name %>" 12 | templateUrl: "<%= asset_path %>" 13 | controller: "Dummy<%= uppercaseName %>Controller" 14 | 15 | ]).controller "Dummy<%= uppercaseName %>Controller", [ 16 | "$scope" 17 | "$location" 18 | ($scope, $location) -> 19 | 20 | # initialize 21 | $scope.pageTitle = "dummy" 22 | ] 23 | return 24 | -------------------------------------------------------------------------------- /controller/templates/controller-template.spec.coffee: -------------------------------------------------------------------------------- 1 | define [ 2 | "angular-mocks" 3 | "<%= name %>/<%= name %>" 4 | ], -> 5 | describe "controller title", -> 6 | # initialize 7 | $scope = undefined 8 | $location = undefined 9 | dummy<%= uppercaseName %> = undefined 10 | 11 | beforeEach -> 12 | module("<%= name %>Module") 13 | inject((_$injector_, _$rootScope_) -> 14 | $scope = _$rootScope_.$new() 15 | $location = _$injector_.get("$location") 16 | dummy<%= uppercaseName %>Controller = _$injector_.get("$controller")("Dummy<%= uppercaseName %>Controller", 17 | '$scope': $scope 18 | '$location': $location 19 | ) 20 | return 21 | ) 22 | return 23 | 24 | it "should be equal dummy", -> 25 | expect($scope.pageTitle).toEqual "dummy" 26 | return 27 | return 28 | return 29 | -------------------------------------------------------------------------------- /controller/templates/controller-template.tpl.html: -------------------------------------------------------------------------------- 1 |
2 | This is the view for <%= name %> controller 3 |
4 | -------------------------------------------------------------------------------- /directive/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | var fs = require('fs'); 5 | 6 | var DirectiveGenerator = module.exports = function DirectiveGenerator(args, options, config) { 7 | // By calling `NamedBase` here, we get the argument to the subgenerator call 8 | // as `this.name`. 9 | yeoman.generators.NamedBase.apply(this, arguments); 10 | 11 | console.log('You called the directive subgenerator with the argument ' + this.name + '.'); 12 | this.uppercaseName = this.name.charAt(0).toUpperCase() + this.name.slice(1); 13 | this.asset_path = '<%= asset_path("' + this.name + '/' + this.name + '.tpl.html") %>'; 14 | }; 15 | 16 | util.inherits(DirectiveGenerator, yeoman.generators.NamedBase); 17 | 18 | DirectiveGenerator.prototype.files = function files() { 19 | var prefix = 'app/assets/javascripts/' + this.name + '/'; 20 | this.template('directive-template.coffee.erb' , prefix + this.name + '.coffee.erb'); 21 | this.template('directive-template.spec.coffee' , 'spec/javascripts/spec/' + this.name + '_unitspec.coffee'); 22 | this.template('directive-template.tpl.html' , prefix + this.name + '.tpl.html'); 23 | }; 24 | -------------------------------------------------------------------------------- /directive/templates/directive-template.coffee.erb: -------------------------------------------------------------------------------- 1 | define ["angular"], (angular) -> 2 | "use strict" 3 | angular.module("<%= name %>Module", []).directive "<%= name %>", [-> 4 | restrict: "E" 5 | replace: true 6 | templateUrl: "<%= asset_path %>" 7 | scope: {} 8 | link: (scope, element, attrs) -> 9 | scope.directiveTitle = "dummy" 10 | return 11 | ] 12 | return 13 | 14 | -------------------------------------------------------------------------------- /directive/templates/directive-template.spec.coffee: -------------------------------------------------------------------------------- 1 | define [ 2 | "angular-mocks" 3 | "<%= name %>/<%= name %>" 4 | ], -> 5 | describe "directive with templateUrl", -> 6 | # initialize 7 | element = undefined 8 | $scope = undefined 9 | 10 | beforeEach -> 11 | module("<%= name %>Module") 12 | module("<%= name %>/<%= name %>.tpl.html") 13 | inject(($compile, _$rootScope_) -> 14 | $scope = _$rootScope_ 15 | element = angular.element("<<%=name %>>>") 16 | element = $compile(element)($scope) 17 | return 18 | ) 19 | return 20 | it "template should be loaded", -> 21 | $scope.$digest() 22 | expect(element.html()).toBe "This is directive for dummy" 23 | return 24 | 25 | return 26 | 27 | return 28 | -------------------------------------------------------------------------------- /directive/templates/directive-template.tpl.html: -------------------------------------------------------------------------------- 1 |
This is directive for {{directiveTitle}}
2 | -------------------------------------------------------------------------------- /filter/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | var fs = require('fs'); 5 | 6 | var FilterGenerator = module.exports = function FilterGenerator(args, options, config) { 7 | // By calling `NamedBase` here, we get the argument to the subgenerator call 8 | // as `this.name`. 9 | yeoman.generators.NamedBase.apply(this, arguments); 10 | 11 | console.log('You called the filter subgenerator with the argument ' + this.name + '.'); 12 | }; 13 | 14 | util.inherits(FilterGenerator, yeoman.generators.NamedBase); 15 | 16 | FilterGenerator.prototype.files = function files() { 17 | var prefix = 'app/assets/javascripts/' + this.name + '/'; 18 | this.template('filter-template.coffee' , prefix + this.name + '.coffee'); 19 | this.template('filter-template.spec.coffee' , 'spec/javascripts/spec/' + this.name + '_unitspec.coffee'); 20 | }; 21 | -------------------------------------------------------------------------------- /filter/templates/filter-template.coffee: -------------------------------------------------------------------------------- 1 | define ["angular"], (angular) -> 2 | "use strict" 3 | angular.module("<%= name %>Module", []).filter "<%= name %>Filter", -> 4 | (input) -> 5 | input.toString().replace /\B(?=(\d{3})+(?!\d))/g, "," 6 | 7 | return 8 | -------------------------------------------------------------------------------- /filter/templates/filter-template.spec.coffee: -------------------------------------------------------------------------------- 1 | define [ 2 | "angular-mocks" 3 | "<%= name %>/<%= name %>" 4 | ], -> 5 | describe "filter 100000", -> 6 | <%= name %>Filter = undefined 7 | beforeEach module("<%= name %>Module") 8 | beforeEach inject((_$filter_) -> 9 | <%= name %>Filter = _$filter_("<%= name %>Filter") 10 | return 11 | ) 12 | it "should be equal 100,000", -> 13 | expect(<%= name %>Filter(100000)).toEqual "100,000" 14 | return 15 | 16 | return 17 | 18 | return 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-rails-angular-require", 3 | "version": "0.3.2", 4 | "description": "Yeoman generator", 5 | "license": "MIT", 6 | "main": "app/index.js", 7 | "repository": "hung-phan/generator-rails-angular-require", 8 | "author": { 9 | "name": "Phan Quang Hung", 10 | "email": "colorvisavn@gmail.com", 11 | "url": "https://github.com/hung-phan" 12 | }, 13 | "engines": { 14 | "node": ">=0.10.0" 15 | }, 16 | "scripts": { 17 | "test": "mocha" 18 | }, 19 | "files": [ 20 | "app" 21 | ], 22 | "keywords": [ 23 | "yeoman-generator", "angular", "require.js", "rails" 24 | ], 25 | "dependencies": { 26 | "yeoman-generator": "~0.16.0", 27 | "chalk": "~0.4.0", 28 | "yosay": "^0.1.0", 29 | "shelljs": "^0.3.0" 30 | }, 31 | "devDependencies": { 32 | "mocha": "*" 33 | }, 34 | "peerDependencies": { 35 | "yo": ">=1.0.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /service/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | var fs = require('fs'); 5 | 6 | var ServiceGenerator = module.exports = function ServiceGenerator(args, options, config) { 7 | // By calling `NamedBase` here, we get the argument to the subgenerator call 8 | // as `this.name`. 9 | yeoman.generators.NamedBase.apply(this, arguments); 10 | 11 | console.log('You called the service subgenerator with the argument ' + this.name + '.'); 12 | this.uppercaseName = this.name.charAt(0).toUpperCase() + this.name.slice(1); 13 | }; 14 | 15 | util.inherits(ServiceGenerator, yeoman.generators.NamedBase); 16 | 17 | ServiceGenerator.prototype.files = function files() { 18 | var prefix = 'app/assets/javascripts/' + this.name + '/'; 19 | this.template('service-template.coffee' , prefix + this.name + '.coffee'); 20 | this.template('service-template.spec.coffee' , 'spec/javascripts/spec/' + this.name + '_unitspec.coffee'); 21 | }; 22 | -------------------------------------------------------------------------------- /service/templates/service-template.coffee: -------------------------------------------------------------------------------- 1 | define ["angular"], (angular) -> 2 | "use strict" 3 | angular.module("<%= name %>Module", []).factory "<%= uppercaseName %>Service", [-> 4 | "Hello world" 5 | ] 6 | return 7 | -------------------------------------------------------------------------------- /service/templates/service-template.spec.coffee: -------------------------------------------------------------------------------- 1 | define [ 2 | "angular-mocks" 3 | "<%= name %>/<%= name %>" 4 | ], -> 5 | describe "service name", -> 6 | <%= uppercaseName %>Service = undefined 7 | beforeEach module("<%= name %>Module") 8 | beforeEach inject((_<%= uppercaseName %>Service_) -> 9 | <%= uppercaseName %>Service = _<%= uppercaseName %>Service_ 10 | return 11 | ) 12 | it "should be equal dummy", -> 13 | expect(<%= uppercaseName %>Service).toEqual "Hello world" 14 | return 15 | 16 | return 17 | 18 | return 19 | -------------------------------------------------------------------------------- /test/test-creation.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it */ 2 | 'use strict'; 3 | var path = require('path'); 4 | var helpers = require('yeoman-generator').test; 5 | 6 | describe('rails-angular-require generator', function () { 7 | beforeEach(function (done) { 8 | helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { 9 | if (err) { 10 | return done(err); 11 | } 12 | 13 | this.app = helpers.createGenerator('rails-angular-require:app', [ 14 | '../../app', [ 15 | helpers.createDummyGenerator(), 16 | 'mocha:app' 17 | ] 18 | ]); 19 | done(); 20 | }.bind(this)); 21 | }); 22 | 23 | it('creates expected files', function (done) { 24 | var expected = [ 25 | // add files you expect to exist here. 26 | 'Bowerfile', 27 | 'Gemfile' 28 | ]; 29 | 30 | helpers.mockPrompt(this.app, { 31 | cssFile: ['includeFontAwesome'], 32 | jsFile: ['includeJasmine', 'includeModernizr'] 33 | }); 34 | this.app.options['skip-install'] = true; 35 | this.app.run({}, function () { 36 | helpers.assertFile(expected); 37 | done(); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/test-load.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | var assert = require('assert'); 4 | 5 | describe('rails-angular-require generator', function () { 6 | it('can be imported without blowing up', function () { 7 | var app = require('../app'); 8 | assert(app !== undefined); 9 | }); 10 | }); 11 | --------------------------------------------------------------------------------