├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Gemfile ├── MIT-LICENSE ├── README.md ├── Rakefile ├── app ├── assets │ └── javascripts │ │ └── templates │ │ └── application.hbs └── controllers │ └── landing_controller.rb ├── bin └── rails ├── ember-appkit-rails.gemspec ├── gemfiles ├── Gemfile.rails-4.0.x └── Gemfile.rails-4.1.x ├── lib ├── ember-appkit-rails.rb ├── ember │ └── appkit │ │ ├── rails.rb │ │ └── rails │ │ ├── active_support.rb │ │ ├── active_support │ │ └── dependencies.rb │ │ ├── engine.rb │ │ ├── sprockets.rb │ │ ├── sprockets │ │ ├── context.rb │ │ ├── directive_processor.rb │ │ └── processed_asset.rb │ │ ├── teaspoon.rb │ │ ├── teaspoon │ │ ├── engine.rb │ │ └── suite.rb │ │ ├── template.rb │ │ ├── version.rb │ │ ├── views │ │ └── teaspoon │ │ │ └── spec │ │ │ └── _eak_rails.html.erb │ │ └── walker.rb └── generators │ ├── ember │ ├── bootstrap_generator.rb │ ├── component_generator.rb │ ├── controller_generator.rb │ ├── generator_helpers.rb │ ├── helper_generator.rb │ ├── install_generator.rb │ ├── model_generator.rb │ ├── resource_generator.rb │ ├── resource_override.rb │ ├── route_generator.rb │ ├── scaffold_controller_override.rb │ ├── scaffold_generator.rb │ ├── scaffold_override.rb │ ├── serializer_override.rb │ ├── template_generator.rb │ └── view_generator.rb │ └── templates │ ├── adapters │ └── application.es6.erb │ ├── application.js.erb │ ├── array_controller.es6 │ ├── component.es6 │ ├── component.template.hbs │ ├── controller.es6 │ ├── csrf.js │ ├── environment.js.erb │ ├── environments │ ├── development.js.erb │ ├── production.js.erb │ └── test.js.erb │ ├── helper.js │ ├── initializers │ └── teaspoon.rb │ ├── model.es6 │ ├── object_controller.es6 │ ├── route.es6 │ ├── router.es6 │ ├── scaffold │ ├── route │ │ ├── edit.es6 │ │ ├── index.es6 │ │ ├── new.es6 │ │ └── show.es6 │ ├── template.hbs │ └── template │ │ ├── edit.hbs │ │ ├── form.hbs │ │ ├── index.hbs │ │ ├── new.hbs │ │ └── show.hbs │ ├── scaffold_controller │ └── controller.rb │ ├── template.hbs │ ├── test │ ├── model.es6 │ ├── route.es6 │ ├── teaspoon_env.rb │ └── test_helper.js │ └── view.es6 ├── test ├── fixtures │ ├── rails_4-0-0_Gemfile │ ├── rails_4-0-0_application.js │ ├── rails_4-0-0_application_layout │ ├── routes_with_api_and_version_namespaces.rb │ ├── routes_with_api_namespace.rb │ ├── routes_with_api_version_namespaces_and_route.rb │ ├── vcr_cassettes │ │ ├── fetch_ember_beta.yml │ │ ├── fetch_ember_canary.yml │ │ ├── fetch_ember_data_tagged.yml │ │ ├── fetch_ember_release.yml │ │ └── fetch_ember_tagged.yml │ └── walker.rb ├── generators │ ├── bootstrap_generator_test.rb │ ├── component_generator_test.rb │ ├── controller_generator_test.rb │ ├── helper_generator_test.rb │ ├── install_generator_test.rb │ ├── model_generator_test.rb │ ├── resource_generator_test.rb │ ├── resource_override_test.rb │ ├── route_generator_test.rb │ ├── scaffold_generator_test.rb │ ├── scaffold_override_test.rb │ ├── serializer_override_test.rb │ ├── template_generator_test.rb │ └── view_generator_test.rb ├── integration │ ├── autoload_modules_test.rb │ ├── engine_test.rb │ └── navigation_test.rb ├── support │ ├── generator_test_support.rb │ └── integration_test_support.rb └── test_helper.rb └── vendor └── assets └── javascripts ├── app.es6.erb ├── ember-appkit ├── index.js ├── loader.js └── resolver.js ├── fake_xml_http_request.js ├── fakehr.js └── httpRespond.js /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | log/*.log 3 | pkg/ 4 | test/dummy 5 | Gemfile.lock 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 4 | - 2.1.0 5 | gemfile: 6 | - gemfiles/Gemfile.rails-4.0.x 7 | - gemfiles/Gemfile.rails-4.1.x 8 | before_install: 9 | - gem install bundler -v '= 1.5.1' 10 | matrix: 11 | include: 12 | - rvm: 2.1.0 13 | gemfile: gemfiles/Gemfile.rails-4.0.x 14 | env: UPDATE_RESOLVER=true 15 | notifications: 16 | slack: 17 | secure: Gk6UyzsTeb5Sn4hMjiIzUWdN6V18O0s69by2ZNJLic+vOA5igNdqFOj5CfRPeklJR5D+m43Ngx2kquOYUhyH9D4+UZpHGnXOZkJiIU9dFJoUxEhkECE8KVjMQstqCoz/OGtQHQegHupNX5mVHQZOwL4WgzP66+xevKwbVtotc1U= 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Upcoming Release 2 | 3 | * Add debug flags for Thor generator tests. 4 | * Use `minitest/pride` 5 | * Update `es6_module_transpiler-rails ~> 0.4.0` 6 | 7 | ## 0.5.0 8 | 9 | * Update to latest resolver. Removes need for monkey-patch and fixes the Ember Inspector's data panel. 10 | * Update to Ember 1.4 to resolve issue with loading and error substates. 11 | * Add a default value for `window.config` to prevent errors if the environment configuration is not present. 12 | * Ensure that the `config/serializers/` directory is mounted properly by Sprockets. 13 | * Updates `.js.es6` extensions to the preferred `.es6` file extensions. 14 | * Changes generated Rails controller error responses 15 | * Rails serializers are generated under `config/serializers`. 16 | * Update to Ember Data 1.0.0-beta.6 to resolve adapter/serializer resolution issues. 17 | * Scaffold, put `input` inside `label` instead of having an empty `for` (#a85bde2). 18 | * Scaffold, add default classes to templates. 19 | * Scaffold: use quoted action names (prepare for bound action lookup added [here](https://github.com/emberjs/ember.js/pull/3936)). 20 | * [fixed] generator error for custom app and config path 21 | * Bootstrap generates all necessary directories when using a custom app-path 22 | * Make sure attributes are camelized in scaffold templates. 23 | * Add Teaspoon integration by default https://github.com/modeset/teaspoon. 24 | * Generate test automatically when running scaffold. 25 | * Add option to get custom Ember builds. 26 | * jj-abrams-resolver now lives under the module name ember/resolver per [here](https://github.com/stefanpenner/ember-jj-abrams-resolver/pull/27). 27 | * Add support for latest serializer alpha 28 | 29 | ## 0.4.0 30 | 31 | * Changed Rails controller to use respond\_with instead of render 32 | * Add commented out history location Router details 33 | * Changed scaffold to pass context rather than doing model lookup in routes 34 | * Make environment js files erb to enable reading values from ENV 35 | * Move config/adapter.js.erb to config/adapters/application.js.es6.erb 36 | and make it resolvable by the resolver. 37 | * add `lib/` to the asset load path 38 | * Rewrote config/routes.rb walker to properly revoke and invoke 39 | depending upon generator 40 | * App config settings now exposed in config/environments/\*.js.erb 41 | * Use custom type specific prefixes in preparation for the updated Resolver. 42 | * Centralize resolver namespace configuration into a single place (`config/environments`). 43 | * Force asset prcompile to ignore `assets/javascripts/application.js` 44 | * Fix issue if jquery-rails is not included in application Gemfile 45 | * Improved matching for gem removal from Gemfile during `ember:bootstrap` 46 | 47 | ## 0.3.1 48 | 49 | * Fix bug where non javascript assets in `Rails.root`/app/assets were 50 | disallowed 51 | 52 | ## 0.3.0 53 | 54 | * Fix issue with asset path ordering. See [#96](https://github.com/dockyard/ember-appkit-rails/issues/96) for details. 55 | * Fix component generator to not add \_component suffix 56 | * Bootstrap generator remove jbuilder 57 | * Don't generate views, helpers, or javascript assets with rails 58 | resource generator 59 | * Removed ember-rails 60 | * Moved config namespace from config.ember.appkit to config.ember 61 | * Don't auto-create modules in app/ for directories that don't contain 62 | \*.rb files 63 | * Remove local variant `vendor/assets/ember`. It should just go into 64 | `vendor/assets/javascripts` 65 | * Force model generator to singularize file name 66 | * Ensure correct ember-data is loaded 67 | * Force ember-source, ember-data-source, and handlebars-source to end of 68 | assets load path 69 | * Replaced default `application.hbs` with Rails-like default page 70 | * Don't remove `app/assets/javascripts` in bootstrap but ignore the path 71 | in the asset loadpath 72 | 73 | ## 0.2.0 74 | 75 | * Ember-Data setting up - Brian Cardarella 76 | * Rails resource generator only overrides if --ember option is given - Brian Cardarella 77 | * Resource is injected into router during resource generator - Brian Cardarella 78 | * Updated es6\_module\_transpiler-rails gem - Wouter Willaert 79 | * Corrected Title in in Welcome Page - Lin Reid 80 | * Remove jquery\_ujs from application.js on bootstrap - Brian Cardarella 81 | * Bootstrap into top-level `appkit/` directory - Brian Cardarella 82 | * Replaced Rails::WelcomeController with LandingController. Now uses 83 | the application layout with an empty template. - Brian Cardarella 84 | * Added utils/csrf.js to autoset csrf token in $.ajaxPrefilter - Brian Cardarella 85 | * Added cache buster for in-gem application.hbs for Sprockets - Brian Cardarella & Lin Reid 86 | * Added Scaffold Generator - Brian Cardarella 87 | * Application generates into `app/` and `config/` - Brian Cardarella 88 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | 5 | group :development, :test do 6 | gem 'pry' 7 | gem 'm' 8 | gem 'byebug' 9 | end 10 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 DockYard 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. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## We have sunset this gem. Patches will continue to be applied but no new features will be added. If you wish to fork and maintain please feel free. 2 | 3 | # EmberAppkitRails 4 | 5 | Ember Appkit for the Asset Pipeline 6 | 7 | **This gem is still pre-1.0 and as such its public API will likely change over the course of heading towards 1.0** 8 | 9 | ##### Upgrade Notes ##### 10 | 11 | If you are upgrading from a previous version of this gem because of the high probability of a breaking API change in some of the generated files you already have you should re-run `rails g ember:bootstrap` and do a `diff` on the files that are being generated vs what you have. 12 | 13 | [![Build Status](https://secure.travis-ci.org/dockyard/ember-appkit-rails.png?branch=master)](http://travis-ci.org/dockyard/ember-appkit-rails) 14 | [![Dependency Status](https://gemnasium.com/dockyard/ember-appkit-rails.png?travis)](https://gemnasium.com/dockyard/ember-appkit-rails) 15 | [![Code Climate](https://codeclimate.com/github/dockyard/ember-appkit-rails.png)](https://codeclimate.com/github/dockyard/ember-appkit-rails) 16 | 17 | ## Prerequisites 18 | 19 | [Node.js](http://nodejs.org) is required. You can either download the 20 | package from the website or run `brew install node` (for Mac users 21 | only). 22 | 23 | ### Syntax Highlighting ### 24 | 25 | It's recommended to turn on syntax highlighting for ES6 modules. There are 26 | numerous ways to do so. Here are a few suggestions. 27 | 28 | * Vim: 29 | * Add `au BufNewFile,BufRead *.es6 set filetype=javascript` inside your `~/.vimrc` 30 | 31 | * Sublime/TextMate 32 | * Check out the [JavaScript.tmLanguage](https://github.com/Benvie/JavaScriptNext.tmLanguage) project. 33 | 34 | * Emacs: 35 | * Add `(add-to-list 'auto-mode-alist '("\\.es6\\'" . javascript-mode))` to your `.emacs`. 36 | 37 | ## Installation ## 38 | 39 | Include the gem in your `Gemfile` 40 | 41 | ```ruby 42 | gem 'ember-appkit-rails' 43 | ``` 44 | 45 | You should not need to specify any additional core Ember dependencies. 46 | `EmberAppkitRails` includes all you need to get going. 47 | 48 | Run the bootstrap generator to prepare your application: 49 | 50 | ``` 51 | rails g ember:bootstrap 52 | ``` 53 | 54 | Then run your Rails server and visit `http://localhost:3000`. If you see `Welcome to Ember!` then you are good to go! 55 | 56 | ### What do you get? ### 57 | 58 | `ember-appkit-rails` will add the `app/` and `config/` directories in 59 | your Rails application to the asset pipeline. We want you to 60 | think of your Ember application files with as much precedence as your 61 | Rails application files. 62 | 63 | `ember-appkit-rails` **completely removes `app/assets/javascripts` from 64 | the asset loadpath.** Any files put into this directory will be ignored 65 | during asset compilation. All business logic 66 | you need should be added to `app/`. If you need to add a 3rd party 67 | library these should go into `vendor/assets/javascripts/`. 68 | 69 | ### Testing ### 70 | Testing is built-in with [Teaspoon](https://github.com/modeset/teaspoon) 71 | and [QUnit](http://qunitjs.com). 72 | 73 | **By default Teaspoon runs within the development environment.** 74 | 75 | If you want to run on `test` you'll have to set it up explicitly e.g. 76 | `RAILS_ENV=test rake teaspoon`. 77 | 78 | #### Resolving #### 79 | 80 | In order for the resolver to work properly Ember application files need to go into 81 | the correct directories. For example, models **must** go into 82 | `app/models`, controllers **must** go into `app/controllers`, routes 83 | **must** go into `app/routes`, etc... The transpiler makes use of the 84 | logical path for those files when creating the AMD namespace. The Ember 85 | Appkit Resolver relies upon this namespacing for the lookups. 86 | 87 | `jquery-ujs` and `turbolinks` will be removed from your application. 88 | 89 | Any files in the `app/` directory that compile to JavaScript will be 90 | automatically required. 91 | 92 | You **must** use `es6` modules in your application files. 93 | `ember-appkit-rails` handles the transpiling for you via the 94 | `es6_module_transpiler-rails` gem as long as you add the `.es6` 95 | extension to the end of the file. The [generators](#generators) will create these 96 | files for you. 97 | 98 | #### Directory Structure #### 99 | 100 | The following is added to your `app/` directory: 101 | 102 | * `app/components` your component files 103 | * `app/mixins` names Ember mixins 104 | * `app/routes` route files go here 105 | * `app/templates` your `.hbs` files go here 106 | * `app/templates/components` any component templates go here 107 | 108 | The following is added to your `config/` directory: 109 | 110 | * `config/application.js` the main loader referenced in your Rails layout view. (replaces `app/assets/javascripts/application.js`) 111 | * `config/adapter.js.erb` configure the ember-data adapter. Pre-set for 112 | `ActiveModelAdapter` and will set the API version to 113 | `Rails.application.config.ember.api_version` 114 | * `config/router.js` your Ember Router. The actual routes will go in 115 | `app/routes` 116 | * `config/initializers` any files that compile to JavaScript in this directory will be 117 | automatically required. 118 | * `config/initializers/csrf.js` sets up the `CSRF` token for doing 119 | `POST` requests back to the Rails backend via AJAX. 120 | * `config/initializers/teaspoon.rb` teaspoon's configuration file (https://github.com/modeset/teaspoon#configuration). 121 | * `config/environment.js` the general environment settings object. You 122 | should put settings in here that will be common across all environments. 123 | * `config/environments/` hold environment specific settings. The correct 124 | environment file will be loaded. Name matches value of `Rails.env`. 125 | Settings added to these files will overwrite settings in 126 | `config/environment.js` 127 | * `config/environments/development.js` development environment settings 128 | * `config/environments/production.js` production environment settings 129 | * `config/environments/test.js` test environment settings 130 | * `config/serializers/` where Rails and Ember serializers will go 131 | 132 | The following is added to your `test/` directory: 133 | 134 | * `test/test_helper.js` require the application for testing and 135 | declare helpers. 136 | * `test/teaspoon_env.rb` configuration directives used when running 137 | teaspoon via the rake task or command line (https://github.com/modeset/teaspoon#console-runner-specific-teaspoon-env). 138 | * `test/integration/` where integration test will go. 139 | 140 | The `lib/` directory is also mounted into the asset load path. You 141 | should use `lib/` to write any custom code that does not belong in 142 | `app/` or `config/` but is not 3rd part software. 143 | 144 | Any 3rd party software should be put into `vendor/assets/javascripts` 145 | (this may change) 146 | 147 | ## Usage ## 148 | 149 | ### Generators ### 150 | 151 | Ember Appkit Rails provides the following generators: 152 | 153 | * `ember:bootstrap` 154 | 155 | Initializes Ember Appkit Rails into your project by creating the required files 156 | (`router.es6`, `ember-app.es6`, and the directory structure). Also, removes 157 | `turbolinks` from `Gemfile` and `app/views/layouts/application.html.erb`. 158 | The `app/assets/javascripts/` directory from your app is removed. 159 | 160 | The following options are supported: 161 | 162 | * `--app-path` - This is the root path to be used for your Ember application. Default value: `app/`. 163 | * `--config-path` - This is the root path for your configuration files 164 | used by your Ember Application. Default value: `config/` 165 | * `--app-name` - This will be used to name the global variable referencing your application. Default value: `App`. 166 | * `--skip-teaspoon`, `-T` - This will skip the generation of Teaspoon. 167 | 168 | * `ember:route NAME` 169 | 170 | Creates a route using the provided name in `app/routes/`. 171 | 172 | * `ember:controller NAME` 173 | 174 | Creates a controller using the provided name in `app/controllers/`. 175 | 176 | The following options are supported: 177 | 178 | * `--array` - Used to generate an `Ember.ArrayController`. 179 | * `--object` - Used to generate an `Ember.ObjectController`. 180 | 181 | * `ember:view NAME` 182 | 183 | Creates a view using the provided name in `app/views/`. 184 | 185 | The following options are supported: 186 | 187 | * `--without-template` - Used to prevent creating a template for the generated view. 188 | 189 | * `ember:component NAME` 190 | 191 | Creates a component in `app/components/` and a template in `app/templates/components/`. 192 | 193 | * `ember:template NAME` 194 | 195 | Creates a template using the provided name in `app/templates/`. 196 | 197 | * `ember:model NAME [ATTRIBUTES]` 198 | 199 | Creates a model using the provided name in `app/models/`. 200 | 201 | Accepts a list of a attributes to setup on the generated model. 202 | 203 | Test is also added automatically under `test/models/model_name_test.es6`. 204 | 205 | * `ember:resource NAME` 206 | 207 | Creates a route, controller, and template for the provided name. 208 | 209 | The following options are supported: 210 | 211 | * `--array` - Used to generate an `Ember.ArrayController`. 212 | * `--object` - Used to generate an `Ember.ObjectController`. 213 | * `--skip-route` - When present a route will not be generated. 214 | 215 | * `ember:scaffold NAME [ATTRIBUTES]` 216 | 217 | Creates the following: 218 | 219 | * Model of type name with the attributes provided 220 | * `edit`, `index`, `new`, `show` routes and templates 221 | * Injected the named resource into `router.es6` along with the 222 | correct nested routes. 223 | 224 | * `ember:helper NAME` 225 | 226 | Creates a helper using the provided name in `app/helpers/`. 227 | 228 | #### Rails Generators #### 229 | 230 | The regular Rails generators `resource` and `scaffold` can also generate 231 | the matching ember templates if you provide the `--ember` switch to the 232 | command: 233 | 234 | ``` 235 | rails g resource post title:string --ember 236 | ``` 237 | 238 | The default behavior of the following Rails generators have been 239 | modified: 240 | 241 | * `scaffold NAME [ATTRIBUTES]` 242 | 243 | * Will generate a controller with only `json` response types. 244 | * Controller and route are namespaced under `api/vX` where `X` = the 245 | values of `::Rails.application.config.ember.api_version` 246 | 247 | ### Configuration ### 248 | 249 | #### Environments #### 250 | 251 | The bootstrap will add environment specific files to 252 | `config/environemnts` that are only loaded in those environments. In 253 | these files the correct versions of Ember, Ember Data, and Handlebars 254 | are required. Any configuration settings you want passed into the 255 | creation of your Ember app should be added to the `config` object: 256 | 257 | ```js 258 | config.LOG_TRANSITIONS = true 259 | ``` 260 | 261 | The `window.config` option is mixed into your application. Likewise, any 262 | other environment specific settings should be made in these files. 263 | 264 | #### API Versioning #### 265 | 266 | Ember Data expect to work with a namespace of `api/vX` where `X` is the 267 | current version of the backend API. To update this value you can 268 | override the the value of `config.ember.api_version` in 269 | `config/application.rb`. 270 | 271 | The routing to the API endpoints in your application need to match 272 | `api/vX`. For example, you can do the following in `config/routes.rb` 273 | 274 | ```ruby 275 | namespace :api do 276 | namespace :v1 do 277 | resources :users 278 | resources :documents 279 | end 280 | end 281 | ``` 282 | 283 | Then the controller files need to be under `app/controllers/api/v1` and 284 | the classes should be namespaced properly: 285 | 286 | ```ruby 287 | class Api::V1::UsersController < ApplicationController 288 | ... 289 | end 290 | ``` 291 | 292 | Using the rails `scaffold` generator will automatically inject resource 293 | route into the correct versioned api namespace. 294 | 295 | #### Asset Path #### 296 | 297 | The default file asset path for `eak-rails` files is `app/`. The 298 | generators will write files to that directory by default instead of 299 | `app/assets/javascripts`. To change this you'll have to modify the 300 | configuration: 301 | 302 | ```ruby 303 | config.ember.paths.app = 'app/assets/javascripts' 304 | ``` 305 | 306 | Adding this to your `config/application.rb` file will generate your 307 | assets into `app/assets/javascripts` instead of `app/` 308 | 309 | #### AMD Module Namespacing #### 310 | 311 | The default AMD namespace is `app`. Modify this in your 312 | `config/application.rb` 313 | 314 | ```ruby 315 | config.ember.namespaces.app = 'ember' 316 | ``` 317 | 318 | The AMD namespace for the router is `config/` you can change this in 319 | your `config/application.rb` file as well: 320 | 321 | ```ruby 322 | config.ember.namespaces.config = 'ember_config' 323 | ``` 324 | 325 | ## Custom Ember Builds ## 326 | 327 | By default Ember Appkit Rails will serve up the proper builds of Ember, 328 | Ember Data, and Handlebars depending upon the environment from their 329 | gems. However, you can add custom builds of each library to your project 330 | to override the default builds. The files you add **must** match a 331 | particular file name to override properly: 332 | 333 | 334 | 335 | 336 | 337 | 338 |
EnvironmentEmberEmber DataHandlebars
developmentember.jsember-data.jshandlebars.js
testember.jsember-data.jshandlebars.js
productionember.prod.jsember-data.prod.jshandlebars.runtime.js
339 | 340 | For example, if you wanted to build a new copy of Ember.js you should 341 | add the files `ember.js` and `ember.prod.js` to 342 | `vendor/assets/javascripts`. The file of the same name will override the 343 | copy in the gem. 344 | 345 | If at any point you need to update Ember.js from any of the release channels, you can do that with 346 | 347 | rails generate ember:install --channel= 348 | 349 | This will fetch both Ember.js and Ember Data from [http://builds.emberjs.com/](http://builds.emberjs.com/) and copy to the right directory. You can choose between the following channels: 350 | * canary - This references the 'master' branch and is not recommended for production use. 351 | * beta - This references the 'beta' branch, and will ultimately become the next stable version. It is not recommended for production use. 352 | * release - This references the 'stable' branch, and is recommended for production use. 353 | 354 | When you don't specify a channel, the release channel is used. 355 | 356 | It is also possible to download a specific tagged release. To do this, use the following syntax: 357 | 358 | 359 | rails generate ember:install --tag=v1.2.0-beta.2 --ember 360 | 361 | or for ember-data 362 | 363 | rails generate ember:install --tag=v1.0.0-beta.2 --ember-data 364 | 365 | 366 | ## Authors ## 367 | 368 | * [Brian Cardarella](http://twitter.com/bcardarella) 369 | * [Alex Navasardyan](http://twitter.com/twokul) 370 | * [Robert Jackson](http://twitter.com/rwjblue) 371 | 372 | A lot of the "real work" was done by [Stefan Penner](http://twitter.com/stefanpenner) with the original [Ember Appkit](https://github.com/stefanpenner/ember-app-kit) project. 373 | 374 | [We are very thankful for the many contributors](https://github.com/dockyard/ember-appkit-rails/graphs/contributors) 375 | 376 | ## Versioning ## 377 | 378 | This gem follows [Semantic Versioning](http://semver.org) 379 | 380 | ## Want to help? ## 381 | 382 | Please do! We are always looking to improve this gem. 383 | 384 | ## Legal ## 385 | 386 | [DockYard](http://dockyard.com) Inc. © 2014 387 | 388 | [@dockyard](http://twitter.com/dockyard) 389 | 390 | [Licensed under the MIT license](http://www.opensource.org/licenses/mit-license.php) 391 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | require 'rdoc/task' 3 | require 'net/http' 4 | require 'uri' 5 | 6 | begin 7 | require 'bundler/setup' 8 | rescue LoadError 9 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks' 10 | end 11 | 12 | RDoc::Task.new(:rdoc) do |rdoc| 13 | rdoc.rdoc_dir = 'rdoc' 14 | rdoc.title = 'EmberAppKit' 15 | rdoc.options << '--line-numbers' 16 | rdoc.rdoc_files.include('README.rdoc') 17 | rdoc.rdoc_files.include('lib/**/*.rb') 18 | end 19 | 20 | desc "Update ember-resolver." 21 | task :update_resolver do 22 | uri = URI("https://raw.github.com/stefanpenner/ember-jj-abrams-resolver/master/dist/ember-resolver.js") 23 | 24 | output = StringIO.new 25 | output.puts "// Fetched from: " + uri.to_s 26 | output.puts "// Fetched on: " + Time.now.utc.strftime('%FT%T') 27 | output.puts Net::HTTP.get(uri).force_encoding("UTF-8") 28 | output.rewind 29 | 30 | File.write('vendor/assets/javascripts/ember-appkit/resolver.js', output.read) 31 | end 32 | 33 | desc "Updates the resolver when UPDATE_RESOLVER is set." 34 | task :update_resolver_if_requested do 35 | Rake::Task['update_resolver'].invoke if ENV['UPDATE_RESOLVER'] == 'true' 36 | end 37 | 38 | desc "Setup dummy application." 39 | task :setup_dummy_app do 40 | initial_path = Dir.pwd 41 | 42 | require 'rails' 43 | require 'rails/generators' 44 | require 'rails/generators/rails/app/app_generator' 45 | 46 | FileUtils.rm_rf 'test/dummy' 47 | 48 | silence_stream(STDOUT) do 49 | begin 50 | Rails::Generators::AppGenerator.start ['test/dummy', '--skip-active-record', '--skip-bundle'] 51 | ensure 52 | Dir.chdir initial_path 53 | end 54 | end 55 | 56 | application_config_path = 'test/dummy/config/application.rb' 57 | application_config = File.read(application_config_path) 58 | 59 | File.write(application_config_path, application_config.sub('module Dummy', "require 'jquery-rails'\nrequire 'ember-appkit-rails'\nmodule Dummy")) 60 | 61 | APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__) 62 | load 'rails/tasks/engine.rake' 63 | end 64 | 65 | Bundler::GemHelper.install_tasks 66 | 67 | require 'rake/testtask' 68 | 69 | Rake::TestTask.new(:integration_test => :setup_dummy_app) do |t| 70 | t.libs << 'lib' 71 | t.libs << 'test' 72 | t.pattern = 'test/integration/**/*_test.rb' 73 | t.verbose = false 74 | end 75 | 76 | Rake::TestTask.new(:generators_test => :setup_dummy_app) do |t| 77 | t.libs << 'lib' 78 | t.libs << 'test' 79 | t.pattern = 'test/generators/**/*_test.rb' 80 | t.verbose = false 81 | end 82 | 83 | task :test => [:update_resolver_if_requested, :generators_test, :integration_test] 84 | 85 | task default: :test 86 | -------------------------------------------------------------------------------- /app/assets/javascripts/templates/application.hbs: -------------------------------------------------------------------------------- 1 | 142 | 143 |
144 | 160 |
161 |
162 | 164 | 165 | 166 | 169 | 170 | 173 | 175 | 177 | 178 | 181 | 182 | 183 | 186 | 187 | 188 | 190 | 191 | 192 | 217 | 218 | 220 | 221 | 245 | 246 | 247 | 271 | 272 | 273 | 276 | 277 | 278 | 281 | 282 | 283 | 284 | 285 | 286 | 289 | 290 | 301 | 302 | 303 | 304 | 306 | 307 | 308 | 309 | 333 | 334 | 335 | 359 | 360 | 362 | 363 | 369 | 370 | 371 | 372 | 375 | 376 | 377 | 379 | 380 | 381 | 384 | 390 | 391 | 392 | 394 | 395 | 396 | 399 | 400 | 409 | 410 | 411 | 412 | 414 | 415 | 416 | 419 | 420 | 421 | 423 | 424 | 425 | 429 | 430 | 431 | 437 | 438 | 459 | 460 | 461 | 462 | 465 | 467 | 468 | 469 | 472 | 474 | 475 | 476 | 477 | 478 | 485 | 486 | 487 | 489 | 490 | 491 | 493 | 494 | 495 | 497 | 498 | 499 | 501 | 502 | 503 | 505 | 506 | 507 | 510 | 511 | 512 | 514 | 515 | 516 | 519 | 520 | 521 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 533 | 534 | 535 | 537 | 538 | 539 | 540 | 541 | 542 | 543 |

Welcome to Ember on Rails!

544 |

That was easy, wasn’t it?

545 |
546 |
547 |

Getting started

548 |

Try some simple Ember magic: {{input value=name name="sampleInput" placeholder="Your name"}}

549 | {{#if name}} 550 | Hello {{name}}, 551 | 552 |
    553 |
  1. 554 |

    Add your own application template to replace this page.

    555 |

    You are seeing this page because you haven’t set an application template yet.

    556 |

    Add a new app/templates/application.hbs file.

    557 |
  2. 558 | 559 |
  3. 560 |

    Use rails generate ember:scaffold to get your application started.

    561 |
  4. 562 | 563 |
  5. 564 |

    Your Rails controllers should be nested under app/controllers/api/v1.

    565 |
  6. 566 |
567 | {{/if}} 568 |
569 |
570 | 571 |
572 | -------------------------------------------------------------------------------- /app/controllers/landing_controller.rb: -------------------------------------------------------------------------------- 1 | class LandingController < ApplicationController 2 | def index 3 | render inline: '', layout: 'application' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application. 3 | 4 | ENGINE_ROOT = File.expand_path('../..', __FILE__) 5 | ENGINE_PATH = File.expand_path('../../lib/ember/appkit/rails/engine', __FILE__) 6 | 7 | require 'rails/all' 8 | require 'rails/engine/commands' 9 | -------------------------------------------------------------------------------- /ember-appkit-rails.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | # Maintain your gem's version: 4 | require 'ember/appkit/rails/version' 5 | 6 | # Describe your gem and declare its dependencies: 7 | Gem::Specification.new do |s| 8 | s.name = 'ember-appkit-rails' 9 | s.version = Ember::Appkit::Rails::VERSION 10 | s.authors = ['Brian Cardarella'] 11 | s.email = ['bcardarella@gmail.com'] 12 | s.homepage = 'https://github.com/dockyard/ember-appkit-rails' 13 | s.summary = 'Ember App Kit for Rails' 14 | s.description = 'Ember App Kit for Rails' 15 | 16 | s.files = Dir["{app,config,db,lib,vendor}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] 17 | s.test_files = Dir["test/**/*"] 18 | 19 | s.add_dependency 'rails', '~> 4.0' 20 | s.add_dependency 'parser' 21 | s.add_dependency 'es6_module_transpiler-rails', '~> 0.4.0' 22 | s.add_dependency 'ember-source', '~> 1.4.beta' 23 | s.add_dependency 'ember-data-source', '~> 1.0.0.beta.6' 24 | s.add_dependency 'handlebars-source' 25 | s.add_dependency 'jquery-rails' 26 | s.add_dependency 'barber', '>= 0.4.1' 27 | s.add_dependency 'active_model_serializers' 28 | s.add_dependency 'teaspoon', '~> 0.7.9' 29 | 30 | s.add_development_dependency 'capybara' 31 | s.add_development_dependency 'poltergeist' 32 | s.add_development_dependency "vcr" 33 | s.add_development_dependency "webmock", "< 1.14.0" 34 | end 35 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.0.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec path: '../' 4 | 5 | gem 'rails', '~>4.0.0' 6 | 7 | group :development, :test do 8 | gem 'pry' 9 | gem 'm' 10 | gem 'byebug' 11 | end 12 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.1.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec path: '../' 4 | 5 | gem 'rails', '~>4.1.0.beta.1' 6 | 7 | group :development, :test do 8 | gem 'pry' 9 | gem 'm' 10 | gem 'byebug' 11 | end 12 | -------------------------------------------------------------------------------- /lib/ember-appkit-rails.rb: -------------------------------------------------------------------------------- 1 | require 'ember/appkit/rails' 2 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails.rb: -------------------------------------------------------------------------------- 1 | require 'jquery-rails' 2 | require 'ember/source' 3 | require 'es6_module_transpiler/rails' 4 | require 'active_model_serializers' 5 | require 'sprockets/railtie' 6 | require 'ember/source' 7 | require 'ember/data/source' 8 | require 'handlebars/source' 9 | 10 | module Ember 11 | module Appkit 12 | module Rails; end 13 | end 14 | end 15 | 16 | require 'ember/appkit/rails/engine' 17 | require 'ember/appkit/rails/sprockets' 18 | require 'ember/appkit/rails/template' 19 | require 'ember/appkit/rails/active_support' 20 | 21 | if [:development, :test].include?(Rails.env.to_sym) 22 | require 'ember/appkit/rails/teaspoon' 23 | end 24 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/active_support.rb: -------------------------------------------------------------------------------- 1 | require 'ember/appkit/rails/active_support/dependencies' 2 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/active_support/dependencies.rb: -------------------------------------------------------------------------------- 1 | module ActiveSupport::Dependencies 2 | def autoloadable_module?(path_suffix) 3 | autoload_paths.each do |load_path| 4 | path = File.join(load_path, path_suffix) 5 | return load_path if File.directory?(path) && Dir.glob(File.join(path, '**/*.rb')).present? 6 | end 7 | 8 | return false 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/engine.rb: -------------------------------------------------------------------------------- 1 | class Ember::Appkit::Rails::Engine < ::Rails::Engine 2 | config.ember = ActiveSupport::OrderedOptions.new 3 | config.ember.paths = ActiveSupport::OrderedOptions.new 4 | config.ember.namespaces = ActiveSupport::OrderedOptions.new 5 | config.ember.prefix_patterns = ActiveSupport::OrderedOptions.new 6 | 7 | config.ember.paths.app = 'app' 8 | config.ember.paths.config = 'config' 9 | config.ember.namespaces.app = 'app' 10 | config.ember.namespaces.config = 'config' 11 | config.ember.api_version = 1 12 | 13 | generators do |app| 14 | app.config.generators.helper false 15 | app.config.generators.assets false 16 | app.config.generators.template_engine false 17 | 18 | ::Rails::Generators.configure!(app.config.generators) 19 | ::Rails::Generators.hidden_namespaces.uniq! 20 | require 'generators/ember/resource_override' 21 | require 'generators/ember/scaffold_override' 22 | require 'generators/ember/scaffold_controller_override' 23 | require 'generators/ember/serializer_override' 24 | end 25 | 26 | initializer :appkit_transpiler do 27 | config.ember.prefix_patterns.app ||= Regexp.new(File.join(::Rails.root, config.ember.namespaces.app)) 28 | config.ember.prefix_patterns.config ||= Regexp.new(File.join(::Rails.root, config.ember.namespaces.config)) 29 | 30 | ES6ModuleTranspiler.add_prefix_pattern config.ember.prefix_patterns.app, config.ember.namespaces.app 31 | ES6ModuleTranspiler.add_prefix_pattern config.ember.prefix_patterns.config, config.ember.namespaces.config 32 | ES6ModuleTranspiler.transform = lambda { |name| name.split('/').map { |n| n.underscore.dasherize }.join('/') } 33 | end 34 | 35 | initializer :appkit_handlebars do 36 | config.handlebars = ActiveSupport::OrderedOptions.new 37 | 38 | config.handlebars.precompile = true 39 | config.handlebars.output_type = :global 40 | config.handlebars.templates_root = "templates" 41 | config.handlebars.templates_path_separator = '/' 42 | 43 | config.before_initialize do |app| 44 | Sprockets::Engines # force autoloading 45 | Sprockets.register_engine '.handlebars', Ember::Appkit::Rails::Template 46 | Sprockets.register_engine '.hbs', Ember::Appkit::Rails::Template 47 | Sprockets.register_engine '.hjs', Ember::Appkit::Rails::Template 48 | end 49 | 50 | config.handlebars ||= ActiveSupport::OrderedOptions.new 51 | config.handlebars.output_type = :amd 52 | config.handlebars.amd_namespace = config.ember.namespaces.app 53 | end 54 | 55 | initializer :appkit_router do |app| 56 | app.routes.append do 57 | get '/' => "landing#index" 58 | end 59 | end 60 | 61 | initializer :appkit_serializer, before: :set_autoload_paths do |app| 62 | app.config.paths.add File.join(Rails.root, 'config/serializers'), eager_load: true 63 | end 64 | 65 | initializer :appkit_sprockets do 66 | assets = Sprockets::Railtie.config.assets 67 | 68 | precompile_index = config.assets.precompile.index { |i| i =~ File.join(Rails.root, 'app/assets/javascripts/application.js') } 69 | config.assets.precompile[precompile_index] = /(? :all do |app| 81 | app.config.assets.paths.append(File.dirname(::Ember::Source.bundled_path_for("ember.js"))) 82 | app.config.assets.paths.append(File.dirname(::Ember::Data::Source.bundled_path_for("ember-data.js"))) 83 | app.config.assets.paths.append(File.expand_path('../', ::Handlebars::Source.bundled_path)) 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/sprockets.rb: -------------------------------------------------------------------------------- 1 | module Ember::Appkit::Rails::Sprockets; end 2 | 3 | require 'ember/appkit/rails/sprockets/context' 4 | require 'ember/appkit/rails/sprockets/processed_asset' 5 | require 'ember/appkit/rails/sprockets/directive_processor' 6 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/sprockets/context.rb: -------------------------------------------------------------------------------- 1 | require 'sprockets/context' 2 | 3 | module Ember::Appkit::Rails::Sprockets::Context 4 | def asset_requirable?(path) 5 | return false if path.to_s.match(File.join(::Rails.root, 'app/assets/javascripts')) || path.to_s.match(File.join(::Rails.root, 'lib/assets/javascripts')) 6 | super 7 | end 8 | end 9 | 10 | Sprockets::Context.send(:prepend, Ember::Appkit::Rails::Sprockets::Context) 11 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/sprockets/directive_processor.rb: -------------------------------------------------------------------------------- 1 | require 'sprockets/directive_processor' 2 | 3 | module Ember::Appkit::Rails::Sprockets::DirectiveProcessor 4 | def process_require_environment_from_directive(path) 5 | context.require_asset(File.join(path, ::Rails.env)) 6 | end 7 | end 8 | 9 | Sprockets::DirectiveProcessor.send(:include, Ember::Appkit::Rails::Sprockets::DirectiveProcessor) 10 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/sprockets/processed_asset.rb: -------------------------------------------------------------------------------- 1 | require 'sprockets/processed_asset' 2 | 3 | module Ember::Appkit::Rails::Sprockets::ProcessedAsset 4 | def initialize(environment, logical_path, pathname) 5 | super 6 | 7 | _make_ember_application_template_stale(pathname) 8 | end 9 | 10 | def init_with(environment, coder) 11 | super 12 | 13 | _make_ember_application_template_stale(coder['pathname']) 14 | end 15 | 16 | private 17 | 18 | def _make_ember_application_template_stale(pathname) 19 | if pathname.to_s =~ /(ember-appkit-rails.+\/app\/assets\/javascripts\/templates\/application.hbs)|(.*\.erb)/ 20 | def self.fresh?(environment) 21 | false 22 | end 23 | end 24 | end 25 | end 26 | 27 | Sprockets::ProcessedAsset.send(:prepend, Ember::Appkit::Rails::Sprockets::ProcessedAsset) 28 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/teaspoon.rb: -------------------------------------------------------------------------------- 1 | module Ember::Appkit::Rails::Teaspoon; end 2 | 3 | require 'teaspoon' 4 | require 'ember/appkit/rails/teaspoon/engine' 5 | require 'ember/appkit/rails/teaspoon/suite' 6 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/teaspoon/engine.rb: -------------------------------------------------------------------------------- 1 | class Ember::Appkit::Rails::Teaspoon::Engine < ::Rails::Engine 2 | paths["app/views"] << Ember::Appkit::Rails::Engine.root.join('lib', 'ember', 'appkit', 'rails', 'views') 3 | end 4 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/teaspoon/suite.rb: -------------------------------------------------------------------------------- 1 | module Ember::Appkit::Rails::Teaspoon::Suite 2 | def asset_from_file(filename) 3 | super.gsub(/(\.js\.es6|.es6)$/, '.js') 4 | end 5 | end 6 | 7 | Teaspoon::Suite.send(:prepend, Ember::Appkit::Rails::Teaspoon::Suite) if defined?(Teaspoon::Suite) 8 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/template.rb: -------------------------------------------------------------------------------- 1 | require 'sprockets' 2 | require 'sprockets/engines' 3 | require 'barber' 4 | 5 | class Ember::Appkit::Rails::Template < Tilt::Template 6 | def self.default_mime_type 7 | 'application/javascript' 8 | end 9 | 10 | def prepare; end 11 | 12 | def evaluate(scope, locals, &block) 13 | raw = handlebars?(scope) 14 | 15 | if raw 16 | template = data 17 | else 18 | template = mustache_to_handlebars(scope, data) 19 | end 20 | 21 | if configuration.precompile 22 | if raw 23 | template = precompile_handlebars(template) 24 | else 25 | template = precompile_ember_handlebars(template) 26 | end 27 | else 28 | if raw 29 | template = compile_handlebars(data) 30 | else 31 | template = compile_ember_handlebars(template) 32 | end 33 | end 34 | 35 | if configuration.output_type == :amd 36 | target = amd_template_target(scope) 37 | 38 | "define('#{target}', ['exports'], function(__exports__){ __exports__.default = #{template} });" 39 | else 40 | target = global_template_target(scope) 41 | 42 | "#{target} = #{template}\n" 43 | end 44 | end 45 | 46 | private 47 | 48 | def handlebars?(scope) 49 | scope.pathname.to_s =~ /\.raw\.(handlebars|hjs|hbs)/ 50 | end 51 | 52 | def amd_template_target(scope) 53 | "#{configuration.amd_namespace}/#{scope.logical_path.split(".").first}" 54 | end 55 | 56 | def global_template_target(scope) 57 | "Ember.TEMPLATES[#{template_path(scope.logical_path).inspect}]" 58 | end 59 | 60 | def compile_handlebars(string) 61 | "Handlebars.compile(#{indent(string).inspect});" 62 | end 63 | 64 | def precompile_handlebars(string) 65 | Barber::FilePrecompiler.call(string) 66 | end 67 | 68 | def compile_ember_handlebars(string) 69 | "Ember.Handlebars.compile(#{indent(string).inspect});" 70 | end 71 | 72 | def precompile_ember_handlebars(string) 73 | Barber::Ember::FilePrecompiler.call(string) 74 | end 75 | 76 | def mustache_to_handlebars(scope, template) 77 | if scope.pathname.to_s =~ /\.mustache\.(handlebars|hjs|hbs)/ 78 | template.gsub(/\{\{(\w[^\}\}]+)\}\}/){ |x| "{{unbound #{$1}}}" } 79 | else 80 | template 81 | end 82 | end 83 | 84 | def template_path(path) 85 | root = configuration.templates_root 86 | 87 | if root.kind_of? Array 88 | root.each do |root| 89 | path.sub!(/#{Regexp.quote(root)}\//, '') 90 | end 91 | else 92 | unless root.empty? 93 | path.sub!(/#{Regexp.quote(root)}\/?/, '') 94 | end 95 | end 96 | 97 | path = path.split('/') 98 | 99 | path.join(configuration.templates_path_separator) 100 | end 101 | 102 | def configuration 103 | ::Rails.configuration.handlebars 104 | end 105 | 106 | def indent(string) 107 | string.gsub(/$(.)/m, "\\1 ").strip 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/version.rb: -------------------------------------------------------------------------------- 1 | module Ember 2 | module Appkit 3 | module Rails 4 | VERSION = '0.5.0' 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/views/teaspoon/spec/_eak_rails.html.erb: -------------------------------------------------------------------------------- 1 | <%= javascript_include_tag_for_teaspoon *@suite.spec_javascripts, @javascript_options %> 2 | 3 | 11 | -------------------------------------------------------------------------------- /lib/ember/appkit/rails/walker.rb: -------------------------------------------------------------------------------- 1 | require 'parser/current' 2 | 3 | class Walker < AST::Processor 4 | attr_accessor :found_nodes, :namespace_type 5 | 6 | def initialize(resource, path, api_version) 7 | @resource = resource 8 | @file = File.open(path, 'r+') 9 | @content = @file.read 10 | @ast = Parser::CurrentRuby.parse(@content) 11 | @api_version = api_version 12 | @found_nodes = [] 13 | end 14 | 15 | def handler_missing(node) 16 | walk(node) 17 | end 18 | 19 | def on_block(node) 20 | if is_namespace?(node) 21 | if is_namespace_type?(node, :api) 22 | found_nodes << node 23 | self.namespace_type = :api 24 | walk_namespace(node) 25 | elsif is_namespace_type?(node, "v#{@api_version}".to_sym) 26 | found_nodes << node 27 | self.namespace_type = :version 28 | walk_namespace(node) 29 | end 30 | else 31 | walk(node) 32 | end 33 | end 34 | 35 | def on_send(node) 36 | if is_resource?(node, @resource.to_sym) 37 | @found_resource = true 38 | found_nodes << node 39 | end 40 | end 41 | 42 | def write_api_namespace 43 | " namespace :api do\n#{yield}\n end" 44 | end 45 | 46 | def write_version_namespace 47 | " namespace :v#{@api_version} do\n#{yield}\n end" 48 | end 49 | 50 | def write_resource 51 | " resources :#{@resource}, except: [:new, :edit]" 52 | end 53 | 54 | def invoke! 55 | process(@ast) 56 | if found_nodes.empty? 57 | found_nodes << @ast 58 | end 59 | node = found_nodes.last 60 | begin_pos = node.loc.begin.end_pos 61 | 62 | output = '' 63 | 64 | if namespace_type 65 | if namespace_type == :version 66 | output = write_resource 67 | else 68 | output = write_version_namespace do 69 | write_resource 70 | end 71 | end 72 | else 73 | output = write_api_namespace do 74 | write_version_namespace do 75 | write_resource 76 | end 77 | end 78 | end 79 | 80 | @file.rewind 81 | @file.write(@content.insert(begin_pos + 1, output + "\n")) 82 | @file.close 83 | end 84 | 85 | def revoke! 86 | @revoke = true 87 | process(@ast) 88 | return if found_nodes.empty? || @found_resource.nil? 89 | if found_nodes.last.loc.expression 90 | begin_pos = found_nodes.last.loc.expression.begin_pos 91 | end_pos = found_nodes.last.loc.expression.end_pos 92 | else 93 | begin_pos = found_nodes.last.loc.begin.begin_pos 94 | end_pos = found_nodes.last.loc.end.end_pos 95 | end 96 | begin_pos = begin_pos - @content[0..begin_pos].reverse.index("\n") 97 | @file.rewind 98 | @file.write @content.sub(@content[begin_pos...end_pos], '') 99 | @file.close 100 | end 101 | 102 | private 103 | 104 | def is_resource?(node, type) 105 | node.children[1] == :resource && node.children[2].children.first == type.to_sym 106 | end 107 | 108 | def is_namespace?(node) 109 | node.children.first.children[1] == :namespace 110 | end 111 | 112 | def is_namespace_type?(node, type) 113 | node.children.first.children[2].children.first == type.to_sym 114 | end 115 | 116 | def walk_namespace(node) 117 | process(node.children[2]) 118 | if @revoke && node.children[2] && node.children[2].children == found_nodes.last.to_a 119 | found_nodes << node 120 | end 121 | end 122 | 123 | def walk(node) 124 | node.children.each do |child| 125 | process(child) if child.respond_to?(:to_ast) 126 | end 127 | end 128 | end 129 | -------------------------------------------------------------------------------- /lib/generators/ember/bootstrap_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class BootstrapGenerator < ::Rails::Generators::Base 6 | APP_FOLDERS = %W{models controllers views routes components templates templates/components mixins} 7 | CONFIG_FOLDERS = %W{serializers} 8 | 9 | include Ember::Generators::GeneratorHelpers 10 | 11 | source_root File.expand_path("../../templates", __FILE__) 12 | 13 | desc "Creates a default Ember.js folder layout in app/ and config/" 14 | 15 | class_option :app_path, :type => :string, :aliases => "-a", :default => false, :desc => "Custom ember app path" 16 | class_option :config_path, :type => :string, :aliases => "-c", :default => false, :desc => "Custom ember config path" 17 | class_option :app_name, :type => :string, :aliases => "-n", :default => false, :desc => "Custom ember app name" 18 | class_option :skip_teaspoon, :type => :boolean, :aliases => "-T", :default => false, :desc => "Opt-out of Teaspoon setup" 19 | 20 | def create_app_dir_layout 21 | create_layout(APP_FOLDERS) 22 | end 23 | 24 | def create_config_dir_layout 25 | create_layout(CONFIG_FOLDERS, config_path) 26 | end 27 | 28 | def create_router_file 29 | template "router.es6", "#{config_path}/router.es6" 30 | end 31 | 32 | def create_application_file 33 | template "application.js.erb", "#{config_path}/application.js" 34 | end 35 | 36 | def create_ember_adapter_file 37 | copy_file "adapters/application.es6.erb", "#{config_path}/adapters/application.es6.erb" 38 | end 39 | 40 | def create_ember_environment_files 41 | copy_file "environment.js.erb", "#{config_path}/environment.js.erb" 42 | copy_file "environments/development.js.erb", "#{config_path}/environments/development.js.erb" 43 | copy_file "environments/production.js.erb", "#{config_path}/environments/production.js.erb" 44 | copy_file "environments/test.js.erb", "#{config_path}/environments/test.js.erb" 45 | end 46 | 47 | def create_utils_csrf_file 48 | template "csrf.js", "#{config_path}/initializers/csrf.js" 49 | end 50 | 51 | def remove_turbolinks 52 | remove_turbolinks_from_gemfile 53 | remove_turbolinks_from_layout 54 | end 55 | 56 | def remove_jbuilder 57 | remove_jbuilder_from_gemfile 58 | end 59 | 60 | def add_greedy_rails_route 61 | insert_into_file 'config/routes.rb', before: /^end$/ do 62 | "\n" + 63 | " # Uncomment when using 'history' as the location in Ember's router\n" + 64 | " # get '*foo', :to => 'landing#index'\n" 65 | end 66 | end 67 | 68 | def add_custom_paths 69 | if app_path != configuration.paths.app 70 | insert_into_file 'config/application.rb', before: /\s\send\nend/ do 71 | " config.ember.paths.app = '#{app_path}'\n" 72 | end 73 | end 74 | 75 | if config_path != configuration.paths.config 76 | insert_into_file 'config/application.rb', before: /\s\send\nend/ do 77 | " config.ember.paths.config = '#{config_path}'\n" 78 | end 79 | end 80 | end 81 | 82 | def teaspoon_requested? 83 | add_teaspoon_files unless options[:skip_teaspoon] 84 | end 85 | 86 | private 87 | 88 | def add_teaspoon_files 89 | copy_file "initializers/teaspoon.rb", "config/initializers/teaspoon.rb" 90 | copy_file "test/teaspoon_env.rb", "test/teaspoon_env.rb" 91 | copy_file "test/test_helper.js", "test/test_helper.js" 92 | empty_directory "test/integration" 93 | end 94 | 95 | def create_layout(directories, path = app_path) 96 | directories.each do |dir| 97 | empty_directory "#{path}/#{dir}" 98 | create_file "#{path}/#{dir}/.gitkeep" unless options[:skip_git] 99 | end 100 | end 101 | 102 | def remove_turbolinks_from_layout 103 | path = Pathname.new(destination_root).join('app','views','layouts','application.html.erb') 104 | return unless path.exist? 105 | 106 | gsub_file path, /(?:, "data-turbolinks-track" => true)/, '' 107 | end 108 | 109 | def remove_gem_from_gemfile(gem) 110 | path = Pathname.new(destination_root).join('Gemfile') 111 | return unless path.exist? 112 | 113 | gsub_file path, /(?:#.+$\n)?gem ['|"]#{gem}.*['|"].*\n\n?/, '' 114 | end 115 | 116 | def remove_turbolinks_from_gemfile 117 | remove_gem_from_gemfile(:turbolinks) 118 | end 119 | 120 | def remove_jbuilder_from_gemfile 121 | remove_gem_from_gemfile(:jbuilder) 122 | end 123 | end 124 | end 125 | end 126 | -------------------------------------------------------------------------------- /lib/generators/ember/component_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class ComponentGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | 10 | desc "Creates a new Ember.js component and component template\nCustom Ember Components require at least two descriptive names separated by a dash. Use CamelCase or dash-case to name your component.\n\nExample,\n\trails generate ember:component PostChart [options]\n\trails generate ember:component post-chart [options]" 11 | 12 | def create_component_files 13 | dashed_file_name = file_name.gsub(/_/, '-') 14 | component_path = File.join(app_path, 'components', class_path, "#{dashed_file_name}.es6") 15 | template "component.es6", component_path 16 | 17 | template_path = File.join(app_path, 'templates/components', class_path, "#{dashed_file_name}.hbs") 18 | template "component.template.hbs", template_path 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/generators/ember/controller_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class ControllerGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | 10 | desc "Creates a new Ember.js controller." 11 | 12 | class_option :array, :type => :boolean, :default => false, :desc => "Create an Ember.ArrayController to represent multiple objects." 13 | class_option :object, :type => :boolean, :default => false, :desc => "Create an Ember.ObjectController to represent a single object." 14 | 15 | def create_controller_files 16 | file_path = File.join(app_path, 'controllers', class_path, "#{file_name}.es6") 17 | 18 | if options.array? 19 | template "array_controller.es6", file_path 20 | elsif options.object? 21 | template "object_controller.es6", file_path 22 | else 23 | template "controller.es6", file_path 24 | end 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/generators/ember/generator_helpers.rb: -------------------------------------------------------------------------------- 1 | require 'rails/generators' 2 | 3 | module Ember 4 | module Generators 5 | module GeneratorHelpers 6 | 7 | def app_path 8 | if options[:app_path] 9 | options[:app_path] 10 | else 11 | configuration.paths.app 12 | end 13 | end 14 | 15 | def config_path 16 | if options[:config_path] 17 | options[:config_path] 18 | else 19 | configuration.paths.config 20 | end 21 | end 22 | 23 | def rails_engine? 24 | defined?(ENGINE_PATH) 25 | end 26 | 27 | def engine_name 28 | ENGINE_PATH.split('/')[-2] 29 | end 30 | 31 | def application_name 32 | if options[:app_name] 33 | options[:app_name] 34 | elsif configuration.app_name 35 | configuration.app_name 36 | elsif rails_engine? 37 | engine_name 38 | else 39 | 'App' 40 | end 41 | end 42 | 43 | def class_name 44 | (class_path + [file_name]).map!{ |m| m.camelize }.join() 45 | end 46 | 47 | def require_name 48 | (class_path + [file_name]).map!{ |m| m.dasherize }.join('/') 49 | end 50 | 51 | def handlebars_template_path 52 | File.join(class_path, file_name).gsub(/^\//, '') 53 | end 54 | 55 | def javascript_assets_path 56 | File.join(::Rails.root, 'app/assets/javascripts') 57 | end 58 | 59 | def configuration 60 | ::Rails.configuration.ember 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/generators/ember/helper_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class HelperGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | argument :name, :type => :string, :desc => 'Create an Ember.Handlebars.helper' 10 | 11 | def create_helper_files 12 | file_path = File.join(app_path, 'helpers', class_path, "#{file_name}.js") 13 | template 'helper.js', file_path 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/generators/ember/install_generator.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | require 'uri' 3 | require 'fileutils' 4 | 5 | 6 | # Based on https://github.com/emberjs/ember-rails/blob/master/lib/generators/ember/install_generator.rb 7 | module Ember 8 | module Generators 9 | class InstallGenerator < ::Rails::Generators::Base 10 | 11 | class InvalidChannel < ::Thor::Error; end 12 | class ConflictingOptions < ::Thor::Error; end 13 | class Deprecated < ::Thor::Error; end 14 | class InsufficientOptions < ::Thor::Error; end 15 | 16 | ::InvalidChannel = InvalidChannel 17 | ::ConflictingOptions = ConflictingOptions 18 | ::Deprecated = Deprecated 19 | ::InsufficientOptions = InsufficientOptions 20 | 21 | desc "Install Ember.js into your vendor folder" 22 | class_option :channel, 23 | :type => :string, 24 | :required => false, 25 | :desc => "Ember release channel Choose between 'release', 'beta' or 'canary'" 26 | class_option :ember_only, 27 | :type => :boolean, 28 | :required => false, 29 | :desc => "Only download Ember.", 30 | :aliases => '--ember' 31 | class_option :ember_data_only, 32 | :type => :boolean, 33 | :required => false, 34 | :desc => "Only download ember-data", 35 | :aliases => '--ember-data' 36 | class_option :tag, 37 | :type => :string, 38 | :required => false, 39 | :desc => "Download tagged release use syntax v1.0.0-beta.3/ember-data & v1.0.0-rc.8/ember" 40 | 41 | def initialize(args = [], options = {}, config = {}) 42 | super(args, options, config) 43 | check_options 44 | process_options 45 | end 46 | 47 | 48 | def ember 49 | return if options.ember_data_only? 50 | 51 | get_ember_for(:development) 52 | get_ember_for(:production) 53 | rescue Thor::Error 54 | say('WARNING: no ember files on this channel or tag' , :yellow) 55 | end 56 | 57 | def ember_data 58 | return if options.ember_only? 59 | 60 | get_ember_for(:development, ember_data_channel, 'ember-data') 61 | get_ember_for(:production, ember_data_channel, 'ember-data') 62 | rescue Thor::Error 63 | say('WARNING: no ember-data files on this channel or tag' , :yellow) 64 | end 65 | 66 | private 67 | 68 | def get_ember_for(environment, chan = channel, name = 'ember') 69 | file_name = environment == :production ? "#{name}.prod.js" : "#{name}.js" 70 | create_file "vendor/assets/javascripts/#{file_name}" do 71 | fetch "#{base_url}/#{chan}/#{file_name_for(name, environment)}", "vendor/assets/javascripts/#{file_name}" 72 | end 73 | end 74 | 75 | def ember_data_channel 76 | if channel == :release 77 | say_status("warning:", 'Ember Data is not available on the :release channel. Falling back to beta channel.' , :yellow) 78 | :beta 79 | else 80 | channel 81 | end 82 | end 83 | 84 | def file_name_for(component,environment) 85 | case environment 86 | when :production 87 | "#{component}.min.js" 88 | when :development 89 | "#{component}.js" 90 | end 91 | end 92 | 93 | def check_options 94 | if options.channel? && !%w(release beta canary).include?(options[:channel]) 95 | say 'ERROR: channel can either be release, beta or canary', :red 96 | raise InvalidChannel 97 | end 98 | if options.channel? && options.tag? 99 | say 'ERROR: conflicting options. --tag and --channel. --tag is incompatible with other options', :red 100 | raise ConflictingOptions 101 | end 102 | if options.tag? && !(options.ember_only? || options.ember_data_only?) 103 | say 'ERROR: insufficient options. --tag needs to be combined with eithe --ember or --ember-data', :red 104 | raise InsufficientOptions 105 | end 106 | end 107 | 108 | def process_options 109 | if options.tag? 110 | @channel = "tags/#{options.tag}" 111 | end 112 | end 113 | 114 | def base_url 115 | 'http://builds.emberjs.com' 116 | end 117 | 118 | def channel 119 | if options.channel 120 | @channel ||= options[:channel] 121 | else 122 | @channel ||= :release 123 | end 124 | end 125 | 126 | def fetch(from, to) 127 | message = "#{from} -> #{to}" 128 | say_status("downloading:", message , :green) 129 | 130 | uri = URI(from) 131 | output = StringIO.new 132 | output.puts "// Fetched from channel: #{channel}, with url " + uri.to_s 133 | output.puts "// Fetched on: " + Time.now.utc.iso8601.to_s 134 | response = Net::HTTP.get_response(uri) 135 | case response.code 136 | when '404' 137 | say "ERROR: Error reading the content from the channel with url #{from}. File not found" , :red 138 | raise Thor::Error 139 | when '200' 140 | output.puts response.body.force_encoding("UTF-8") 141 | else 142 | say "ERROR: Unexpected error with status #{response.code} reading the content from the channel with url #{from}." , :red 143 | raise Thor::Error 144 | end 145 | output.rewind 146 | output.read 147 | end 148 | end 149 | end 150 | end 151 | -------------------------------------------------------------------------------- /lib/generators/ember/model_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class ModelGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | desc "Creates a new ember.js model" 10 | argument :attributes, :type => :array, :default => [], :banner => "field[:type] field[:type] ..." 11 | 12 | def create_model_files 13 | file_path = File.join(app_path, 'models', class_path, "#{file_name.singularize}.es6") 14 | template "model.es6", file_path 15 | end 16 | 17 | def create_test_files 18 | file_path = File.join('test', 'models', class_path, "#{file_name.singularize}_test.es6") 19 | template "test/model.es6", file_path 20 | end 21 | 22 | private 23 | 24 | EMBER_TYPE_LOOKUP = { 25 | nil => 'string', 26 | :binary => 'string', 27 | :string => 'string', 28 | :text => 'string', 29 | :boolean => 'boolean', 30 | :date => 'date', 31 | :datetime =>'date', 32 | :time => 'date', 33 | :timestamp => 'date', 34 | :decimal => 'number', 35 | :float => 'number', 36 | :integer => 'number', 37 | :primary_key => 'number' 38 | } 39 | 40 | def parse_attributes! 41 | self.attributes = (attributes || []).map do |attr| 42 | name, type = attr.split(':') 43 | key = type.try(:to_sym) 44 | ember_type = EMBER_TYPE_LOOKUP[key] || type 45 | 46 | { :name => name, :type => ember_type } 47 | end 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/generators/ember/resource_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class ResourceGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | 10 | desc "Creates a new Ember.js router, controller, view and template" 11 | 12 | class_option :skip_route, :type => :boolean, :default => false, :desc => "Don't create route" 13 | class_option :array, :type => :boolean, :default => false, :desc => "Create an Ember.ArrayController to represent multiple objects" 14 | class_option :object, :type => :boolean, :default => false, :desc => "Create an Ember.ObjectController to represent a single object" 15 | 16 | def create_resource_files 17 | unless options[:skip_route] 18 | invoke('ember:route', [ name.pluralize ], options) 19 | inject_into_router_file(name) 20 | end 21 | invoke('ember:controller', [ name.pluralize ], options) 22 | invoke('ember:template', [ name.pluralize ], options) 23 | end 24 | 25 | private 26 | 27 | def inject_into_router_file(name) 28 | router_file = "#{config_path}/router.es6" 29 | inject_into_file(router_file, :after => /^.*Router.map\(function\(\) \{*$/) do 30 | "\n this.resource('#{name.pluralize}');" 31 | end 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/generators/ember/resource_override.rb: -------------------------------------------------------------------------------- 1 | require "rails/generators" 2 | require "rails/generators/rails/resource/resource_generator" 3 | require "generators/ember/controller_generator" 4 | require "generators/ember/view_generator" 5 | 6 | module Rails 7 | module Generators 8 | ResourceGenerator.class_eval do 9 | class_option :ember, aliases: '-e', desc: 'force ember resource to generate', optional: true, type: 'boolean', default: false, banner: '--ember' 10 | 11 | def add_ember 12 | if options.ember 13 | say_status :invoke, "ember:resource", :white 14 | with_padding do 15 | invoke "ember:resource", [singular_name, attributes.map { |a| "#{a.name}:#{a.type}" }].flatten 16 | end 17 | end 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/generators/ember/route_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class RouteGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | 10 | desc "Creates a new Ember.js route" 11 | 12 | def create_route_files 13 | file_path = File.join(app_path, 'routes', class_path, "#{file_name}.es6") 14 | template "route.es6", file_path 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/generators/ember/scaffold_controller_override.rb: -------------------------------------------------------------------------------- 1 | require 'rails/generators' 2 | require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator' 3 | 4 | module Rails 5 | module Generators 6 | class ScaffoldControllerGenerator 7 | source_root File.expand_path('../../templates/scaffold_controller', __FILE__) 8 | 9 | def create_controller_files 10 | template "controller.rb", File.join("app/controllers/api/v#{::Rails.application.config.ember.api_version}", class_path, "#{controller_file_name}_controller.rb") 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/generators/ember/scaffold_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/model_generator' 2 | 3 | module Ember 4 | module Generators 5 | class ScaffoldGenerator < ModelGenerator 6 | source_root File.expand_path("../../templates", __FILE__) 7 | desc "Scaffolds a new Ember CRUD" 8 | 9 | class_option :skip_route, :type => :boolean, :default => false, :desc => "Don't create route" 10 | class_option :array, :type => :boolean, :default => false, :desc => "Create an Ember.ArrayController to represent multiple objects" 11 | class_option :object, :type => :boolean, :default => false, :desc => "Create an Ember.ObjectController to represent a single object" 12 | 13 | def create_route_files 14 | create_resource_files_for(:route, 'es6') 15 | inject_into_router_file(file_name) 16 | end 17 | 18 | def create_template_files 19 | create_resource_files_for(:template, 'hbs') 20 | template "scaffold/template.hbs", File.join(app_path, 'templates', "#{file_name.pluralize}.hbs") 21 | template "scaffold/template/form.hbs", File.join(app_path, 'templates', file_name.pluralize, 'form.hbs') 22 | end 23 | 24 | def create_tests 25 | ["route"].each do |type| 26 | create_test_files_for(type) 27 | end 28 | end 29 | 30 | private 31 | 32 | def create_resource_files_for(type, extension) 33 | dir = type.to_s.pluralize 34 | resource = file_name.pluralize 35 | 36 | [:edit, :index, :new, :show].each do |action| 37 | template "scaffold/#{type}/#{action}.#{extension}", File.join(app_path, dir, "#{resource}/#{action}.#{extension}") 38 | end 39 | end 40 | 41 | def create_test_files_for(type) 42 | resource = file_name.pluralize 43 | 44 | [:edit, :index, :new, :show].each do |action| 45 | object = "#{resource}_#{action}_#{type}".camelize 46 | template "test/#{type}.es6", File.join('test', type.pluralize, "#{resource}/#{action}_test.es6"), object: object, action: action 47 | end 48 | end 49 | 50 | def inject_into_router_file(name) 51 | router_file = "#{config_path}/router.es6" 52 | js = <<-JS 53 | 54 | this.resource('#{name.pluralize}', function() { 55 | this.route('new'); 56 | this.route('show', {path: ':#{file_name.singularize}_id'}); 57 | this.route('edit', {path: ':#{file_name.singularize}_id/edit'}); 58 | }); 59 | JS 60 | inject_into_file(router_file, :after => /^.*Router.map\(function\(\) \{*$/) do 61 | js.rstrip 62 | end 63 | end 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/generators/ember/scaffold_override.rb: -------------------------------------------------------------------------------- 1 | require 'rails/generators' 2 | require 'rails/generators/rails/scaffold/scaffold_generator' 3 | require 'ember/appkit/rails/walker' 4 | 5 | module Rails 6 | module Generators 7 | class ScaffoldGenerator 8 | class_option :ember, aliases: '-e', desc: 'force ember resource to generate', optional: true, type: 'boolean', default: false, banner: '--ember' 9 | remove_hook_for :resource_route 10 | 11 | def add_ember 12 | if options.ember 13 | say_status :invoke, "ember:resource", :white 14 | with_padding do 15 | invoke "ember:scaffold", [singular_name, attributes.map { |a| "#{a.name}:#{a.type}" }].flatten 16 | end 17 | end 18 | end 19 | 20 | def write_resource 21 | action Walker.new(file_path.pluralize, File.join(destination_root, 'config/routes.rb'), ::Rails.application.config.ember.api_version) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/generators/ember/serializer_override.rb: -------------------------------------------------------------------------------- 1 | require "rails/generators" 2 | 3 | begin 4 | require "generators/serializer/serializer_generator" 5 | rescue LoadError 6 | # TODO: Make this primary when active_model_serializers 0.9.0 is final 7 | require "active_model/serializer/generators/serializer/serializer_generator" 8 | end 9 | 10 | module Rails 11 | module Generators 12 | SerializerGenerator.class_eval do 13 | def create_serializer_file 14 | template 'serializer.rb', File.join('config/serializers', class_path, "#{file_name}_serializer.rb") 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/generators/ember/template_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class TemplateGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | 10 | desc "Creates a new Ember.js template." 11 | 12 | def create_template_files 13 | file_path = File.join(app_path, 'templates', class_path, "#{file_name}.hbs") 14 | template 'template.hbs', file_path 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/generators/ember/view_generator.rb: -------------------------------------------------------------------------------- 1 | require 'generators/ember/generator_helpers' 2 | 3 | module Ember 4 | module Generators 5 | class ViewGenerator < ::Rails::Generators::NamedBase 6 | include Ember::Generators::GeneratorHelpers 7 | 8 | source_root File.expand_path("../../templates", __FILE__) 9 | 10 | desc "Creates a new Ember.js view and associated template." 11 | class_option :without_template, :type => :boolean, :default => false, :desc => "Create template for this view" 12 | 13 | def create_view_files 14 | file_path = File.join(app_path, 'views', class_path, "#{file_name}.es6") 15 | template "view.es6", file_path 16 | invoke('ember:template', [ name ], options) unless options[:without_template] 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/generators/templates/adapters/application.es6.erb: -------------------------------------------------------------------------------- 1 | export default DS.ActiveModelAdapter.extend({ 2 | namespace: 'api/v<%= Rails.application.config.ember.api_version %>' 3 | }); 4 | -------------------------------------------------------------------------------- /lib/generators/templates/application.js.erb: -------------------------------------------------------------------------------- 1 | //= require jquery 2 | //= require environment 3 | //= require ember-appkit 4 | //= require_self 5 | //= require_tree ./adapters 6 | //= require_tree ./serializers 7 | //= require router 8 | //= require_tree ../<%= app_path %> 9 | //= require_tree ./initializers 10 | 11 | window.<%= application_name.camelize %> = require('app').default.create(); 12 | -------------------------------------------------------------------------------- /lib/generators/templates/array_controller.es6: -------------------------------------------------------------------------------- 1 | export default Ember.ArrayController.extend({ 2 | }); 3 | -------------------------------------------------------------------------------- /lib/generators/templates/component.es6: -------------------------------------------------------------------------------- 1 | export default Ember.Component.extend({ 2 | }); 3 | -------------------------------------------------------------------------------- /lib/generators/templates/component.template.hbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavyJonesLocker/ember-appkit-rails/9243d2413bb25649f41b956e086f3094fc823561/lib/generators/templates/component.template.hbs -------------------------------------------------------------------------------- /lib/generators/templates/controller.es6: -------------------------------------------------------------------------------- 1 | export default Ember.Controller.extend({ 2 | }); 3 | -------------------------------------------------------------------------------- /lib/generators/templates/csrf.js: -------------------------------------------------------------------------------- 1 | $.ajaxPrefilter(function(options, originalOptions, jqXHR) { 2 | var token; 3 | if (!options.crossDomain) { 4 | token = $('meta[name="csrf-token"]').attr('content'); 5 | if (token) { 6 | return jqXHR.setRequestHeader('X-CSRF-Token', token); 7 | } 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /lib/generators/templates/environment.js.erb: -------------------------------------------------------------------------------- 1 | //= require_self 2 | //= require_environment_from ./environments 3 | /* 4 | This is useful when using canary versions of Ember to enable 5 | feature flags before Ember itself is loaded. 6 | 7 | Example: ENV = { FEATURES: { 'query-params-new': true } }; 8 | 9 | See the feature flags guide for details: 10 | 11 | http://emberjs.com/guides/configuring-ember/feature-flags/ 12 | */ 13 | 14 | window.config = {}; 15 | 16 | <% config = Rails.application.config.ember %> 17 | 18 | config.modulePrefix = '<%= config.namespaces.app %>'; 19 | config.routerPrefix = '<%= config.namespaces.config %>'; 20 | config.adapterPrefix = '<%= config.namespaces.config %>'; 21 | config.serializerPrefix = '<%= config.namespaces.config %>'; 22 | -------------------------------------------------------------------------------- /lib/generators/templates/environments/development.js.erb: -------------------------------------------------------------------------------- 1 | //= require handlebars 2 | //= require ember 3 | //= require ember-data 4 | 5 | config.LOG_ACTIVE_GENERATION = true; 6 | config.LOG_MODULE_RESOLVER = true; 7 | config.LOG_TRANSITIONS = true; 8 | config.LOG_TRANSITIONS_INTERNAL = true; 9 | config.LOG_VIEW_LOOKUPS = true; 10 | -------------------------------------------------------------------------------- /lib/generators/templates/environments/production.js.erb: -------------------------------------------------------------------------------- 1 | //= require handlebars.runtime 2 | //= require ember.prod 3 | //= require ember-data.prod 4 | 5 | // For some configuration settings such as API keys, 6 | // you should read them from the environment rather 7 | // than checking them into version control. See also 8 | // the Figaro gem. 9 | // Keep in mind that API keys in js are visible to 10 | // someone poking in the browser, so never expose 11 | // a truly private API key in javascript. 12 | // my_api_key = <%= ENV['MY_API_KEY'] %> 13 | 14 | Ember.LOG_VERSION = false; 15 | -------------------------------------------------------------------------------- /lib/generators/templates/environments/test.js.erb: -------------------------------------------------------------------------------- 1 | //= require handlebars 2 | //= require ember 3 | //= require ember-data 4 | 5 | Ember.LOG_VERSION = false; 6 | -------------------------------------------------------------------------------- /lib/generators/templates/helper.js: -------------------------------------------------------------------------------- 1 | Ember.Handlebars.helper('<%= name %>', function(value) { 2 | }); 3 | -------------------------------------------------------------------------------- /lib/generators/templates/initializers/teaspoon.rb: -------------------------------------------------------------------------------- 1 | Teaspoon.setup do |config| 2 | # This determines where the Teaspoon routes will be mounted. Changing this to "/jasmine" would allow you to browse to 3 | # http://localhost:3000/jasmine to run your tests. 4 | config.mount_at = "/teaspoon" 5 | 6 | # This defaults to Rails.root if left nil. If you're testing an engine using a dummy application it can be useful to 7 | # set this to your engines root.. E.g. `Teaspoon::Engine.root` 8 | config.root = nil 9 | 10 | # These paths are appended to the Rails assets paths (relative to config.root), and by default is an array that you 11 | # can replace or add to. 12 | config.asset_paths = ["test", "test/stylesheets"] 13 | 14 | # Fixtures are rendered through a standard controller. This means you can use things like HAML or RABL/JBuilder, etc. 15 | # to generate fixtures within this path. 16 | config.fixture_path = "test/fixtures" 17 | 18 | # You can modify the default suite configuration and create new suites here. Suites can be isolated from one another. 19 | # When defining a suite you can provide a name and a block. If the name is left blank, :default is assumed. You can 20 | # omit various directives and the defaults will be used. 21 | # 22 | # To run a specific suite 23 | # - in the browser: http://localhost/teaspoon/[suite_name] 24 | # - from the command line: rake teaspoon suite=[suite_name] 25 | config.suite do |suite| 26 | suite.boot_partial = 'eak_rails' 27 | 28 | # You can specify a file matcher and all matching files will be loaded when the suite is run. It's important that these files are serve-able from sprockets. 29 | # 30 | # Note: Can also be set to nil. 31 | suite.matcher = "test/**/*_test.{js,js.coffee,es6,coffee}" 32 | 33 | # Each suite can load a different helper, which can in turn require additional files. This file is loaded before 34 | # your tests are loaded, and can be used as a manifest. 35 | suite.helper = "test_helper" 36 | 37 | # These are the core Teaspoon javascripts. It's strongly encouraged to include only the base files here. You can 38 | # require other support libraries in your test helper, which allows you to change them without having to restart the 39 | # server. 40 | # 41 | # Available frameworks: teaspoon-jasmine, teaspoon-mocha, teaspoon-qunit 42 | # 43 | # Note: To use the CoffeeScript source files use `"teaspoon/qunit"` etc. 44 | suite.javascripts = ["teaspoon-qunit"] 45 | 46 | # If you want to change how Teaspoon looks, or include your own stylesheets you can do that here. The default is the 47 | # stylesheet for the HTML reporter. 48 | suite.stylesheets = ["teaspoon"] 49 | 50 | # When running coverage reports, you probably want to exclude libraries that you're not 3 | <%= attribute[:name].camelize(:lower) %>: <%= 4 | if %w(references belongs_to).member?(attribute[:type]) 5 | "DS.belongsTo('%s.%s')" % [application_name.camelize, attribute[:name].camelize] 6 | else 7 | "DS.attr('%s')" % attribute[:type] 8 | end 9 | %><% if (idx < attributes.length-1) %>,<% end %> 10 | <% end -%> 11 | }); 12 | -------------------------------------------------------------------------------- /lib/generators/templates/object_controller.es6: -------------------------------------------------------------------------------- 1 | export default Ember.ObjectController.extend({ 2 | }); 3 | -------------------------------------------------------------------------------- /lib/generators/templates/route.es6: -------------------------------------------------------------------------------- 1 | export default Ember.Route.extend({ 2 | }); 3 | -------------------------------------------------------------------------------- /lib/generators/templates/router.es6: -------------------------------------------------------------------------------- 1 | var Router = Ember.Router.extend({ 2 | // Uncomment to change Ember's router to use the 3 | // HTML5 History API 4 | // Please note that not all browsers support this! 5 | // You will also need to uncomment the greedy route matcher 6 | // in config/routes.rb 7 | 8 | // location: 'history' 9 | }); 10 | 11 | Router.map(function() { 12 | }); 13 | 14 | export default Router; 15 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/route/edit.es6: -------------------------------------------------------------------------------- 1 | export default Ember.Route.extend({ 2 | model: function(params) { 3 | return this.store.find('<%= require_name.singularize -%>', params.<%= file_name.singularize -%>_id); 4 | }, 5 | deactivate: function() { 6 | var model = this.get('controller.model'); 7 | model.rollback(); 8 | }, 9 | actions: { 10 | save: function(model) { 11 | var _this = this; 12 | model.save().then(function() { 13 | _this.transitionTo('<%= file_name.pluralize -%>.show', model); 14 | }); 15 | }, 16 | cancel: function(model) { 17 | this.transitionTo('<%= file_name.pluralize -%>.show', model); 18 | } 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/route/index.es6: -------------------------------------------------------------------------------- 1 | export default Ember.Route.extend({ 2 | model: function() { 3 | return this.store.find('<%= require_name.singularize -%>'); 4 | } 5 | }); 6 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/route/new.es6: -------------------------------------------------------------------------------- 1 | export default Ember.Route.extend({ 2 | model: function() { 3 | return this.store.createRecord('<%= require_name.singularize -%>'); 4 | }, 5 | deactivate: function() { 6 | var model = this.get('controller.model'); 7 | if (model.get('isNew')) { 8 | model.deleteRecord(); 9 | } 10 | }, 11 | actions: { 12 | save: function(model) { 13 | var _this = this; 14 | model.save().then(function() { 15 | _this.transitionTo('<%= file_name.pluralize -%>.show', model); 16 | }); 17 | }, 18 | cancel: function() { 19 | this.transitionTo('<%= file_name.pluralize -%>.index'); 20 | } 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/route/show.es6: -------------------------------------------------------------------------------- 1 | export default Ember.Route.extend({ 2 | model: function(params) { 3 | return this.store.find('<%= require_name.singularize -%>', params.<%= file_name.singularize -%>_id); 4 | }, 5 | actions: { 6 | destroyRecord: function(model) { 7 | var _this = this; 8 | model.destroyRecord().then(function() { 9 | _this.transitionTo('<%= file_name.pluralize -%>.index'); 10 | }); 11 | } 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/template.hbs: -------------------------------------------------------------------------------- 1 |

<%= file_name.pluralize.titleize -%>

2 | 3 | {{outlet}} 4 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/template/edit.hbs: -------------------------------------------------------------------------------- 1 |

Edit

2 | 3 | {{partial '<%= file_name.pluralize -%>/form'}} 4 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/template/form.hbs: -------------------------------------------------------------------------------- 1 | <% attributes.each do |attribute| -%> 2 |
3 | 4 |
5 | <% end -%> 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/template/index.hbs: -------------------------------------------------------------------------------- 1 |

Index

2 | 3 |

{{link-to 'New <%= file_name.singularize -%>' '<%= file_name.pluralize -%>.new'}}

4 | 5 | 6 | 7 | 8 | <% attributes.each do |attribute| -%> 9 | 10 | <% end -%> 11 | 12 | {{#each}} 13 | 14 | 15 | <% attributes.each do |attribute| -%> 16 | 17 | <% end -%> 18 | 19 | {{/each}} 20 |
id<%= attribute[:name].titleize -%>
{{link-to id '<%= file_name.pluralize -%>.show' this}}{{<%= attribute[:name].camelize(:lower) -%>}}
21 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/template/new.hbs: -------------------------------------------------------------------------------- 1 |

New

2 | 3 | {{partial '<%= file_name.pluralize -%>/form'}} 4 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold/template/show.hbs: -------------------------------------------------------------------------------- 1 |

{{id}}

2 | 3 |

{{link-to 'Edit' '<%= file_name.pluralize -%>.edit' this}}

4 | 5 | 10 | -------------------------------------------------------------------------------- /lib/generators/templates/scaffold_controller/controller.rb: -------------------------------------------------------------------------------- 1 | <% api_version = Rails.application.config.ember.api_version -%> 2 | class Api::V<%= api_version %>::<%= controller_class_name %>Controller < ApplicationController 3 | before_action :set_<%= singular_table_name %>, only: [:show, :update, :destroy] 4 | respond_to :json 5 | 6 | # GET <%= route_url %> 7 | def index 8 | respond_with <%= orm_class.all(class_name) %> 9 | end 10 | 11 | # GET <%= route_url %>/1 12 | def show 13 | respond_with <%= "@#{singular_table_name}" %> 14 | end 15 | 16 | # POST <%= route_url %> 17 | def create 18 | @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %> 19 | 20 | if @<%= orm_instance.save %> 21 | respond_with <%= "@#{singular_table_name}" %>, status: :created, location: [:api, :v<%= api_version %>, <%= "@#{singular_table_name}" %>] 22 | else 23 | render json: { errors: <%= "@#{orm_instance.errors}" %> }, status: :unprocessable_entity 24 | end 25 | end 26 | 27 | # PATCH/PUT <%= route_url %>/1 28 | def update 29 | if @<%= orm_instance.update("#{singular_table_name}_params") %> 30 | respond_with <%= "@#{singular_table_name}" %>, status: :ok, location: [:api, :v<%= api_version %>, <%= "@#{singular_table_name}" %>] 31 | else 32 | render json: { errors: <%= "@#{orm_instance.errors}" %> }, status: :unprocessable_entity 33 | end 34 | end 35 | 36 | # DELETE <%= route_url %>/1 37 | def destroy 38 | @<%= orm_instance.destroy %> 39 | head :no_content 40 | end 41 | 42 | private 43 | 44 | # Use callbacks to share common setup or constraints between actions. 45 | def set_<%= singular_table_name %> 46 | @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> 47 | end 48 | 49 | # Never trust parameters from the scary internet, only allow the white list through. 50 | def <%= "#{singular_table_name}_params" %> 51 | <%- if attributes_names.empty? -%> 52 | params[<%= ":#{singular_table_name}" %>] 53 | <%- else -%> 54 | params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>) 55 | <%- end -%> 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/generators/templates/template.hbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavyJonesLocker/ember-appkit-rails/9243d2413bb25649f41b956e086f3094fc823561/lib/generators/templates/template.hbs -------------------------------------------------------------------------------- /lib/generators/templates/test/model.es6: -------------------------------------------------------------------------------- 1 | import <%= file_name.camelize -%> from '<%= app_path -%>/models/<%= require_name.dasherize -%>'; 2 | 3 | module('Unit - <%= file_name.camelize -%>'); 4 | 5 | test('exists', function(){ 6 | ok( <%= file_name.camelize -%>, 'Expected <%= file_name.camelize -%> to exist.'); 7 | }); 8 | -------------------------------------------------------------------------------- /lib/generators/templates/test/route.es6: -------------------------------------------------------------------------------- 1 | import <%= config[:object] -%> from '<%= app_path -%>/routes/<%= require_name.dasherize.pluralize -%>/<%= config[:action] -%>'; 2 | 3 | var route, store; 4 | 5 | module('Unit - <%= config[:object] -%>', { 6 | setup: function(){ 7 | store = {}; 8 | 9 | route = <%= config[:object] -%>.create({ 10 | store: store 11 | }); 12 | }, 13 | teardown: function(){ 14 | Ember.run(route, 'destroy'); 15 | } 16 | }); 17 | 18 | test('it exist', function(){ 19 | expect(2); 20 | 21 | ok(route); 22 | ok(route instanceof Ember.Route); 23 | }); 24 | -------------------------------------------------------------------------------- /lib/generators/templates/test/teaspoon_env.rb: -------------------------------------------------------------------------------- 1 | # This file allows you to override various Teaspoon configuration directives when running from the command line. It is not 2 | # required from within the Rails environment, so overriding directives that have been defined within the initializer 3 | # is not possible. 4 | # 5 | # Set RAILS_ROOT and load the environment. 6 | ENV["RAILS_ROOT"] = File.expand_path("../../", __FILE__) 7 | require File.expand_path("../../config/environment", __FILE__) 8 | 9 | # Provide default configuration. 10 | # 11 | # You can override various configuration directives defined here by using arguments with the teaspoon command. 12 | # 13 | # teaspoon --driver=selenium --suppress-log 14 | # rake teaspoon DRIVER=selenium SUPPRESS_LOG=false 15 | Teaspoon.setup do |config| 16 | # Driver / Server 17 | #config.driver = "phantomjs" # available: phantomjs, selenium 18 | #config.server = nil # defaults to Rack::Server 19 | 20 | # Behaviors 21 | #config.server_timeout = 20 # timeout for starting the server 22 | #config.server_port = nil # defaults to any open port unless specified 23 | #config.fail_fast = true # abort after the first failing suite 24 | 25 | # Output 26 | #config.formatters = "dot" # available: dot, tap, tap_y, swayze_or_oprah 27 | #config.suppress_log = false # suppress logs coming from console[log/error/debug] 28 | #config.color = true 29 | 30 | # Coverage (requires istanbul -- https://github.com/gotwarlost/istanbul) 31 | #config.coverage = true 32 | #config.coverage_reports = "text,html,cobertura" 33 | #config.coverage_output_dir = "coverage" 34 | #config.statements_coverage_threshold = 50 35 | #config.functions_coverage_threshold = 50 36 | #config.branches_coverage_threshold = 50 37 | #config.lines_coverage_threshold = 50 38 | end 39 | -------------------------------------------------------------------------------- /lib/generators/templates/test/test_helper.js: -------------------------------------------------------------------------------- 1 | // Teaspoon includes some support files, but you can use anything from your own support path too. 2 | // require support/sinon 3 | // require support/your-support-file 4 | // 5 | // Deferring execution 6 | // If you're using CommonJS, RequireJS or some other asynchronous library you can defer execution. Call Teaspoon.execute() 7 | // after everything has been loaded. Simple example of a timeout: 8 | // 9 | // Teaspoon.defer = true 10 | // setTimeout(Teaspoon.execute, 1000) 11 | // 12 | // Manifest 13 | // If you'd rather require your test files manually (to control order for instance) you can disable the suite matcher in 14 | // the configuration and use this file as a manifest. 15 | // 16 | // For more information: http://github.com/modeset/teaspoon 17 | // 18 | // You can require javascript files here. A good place to start is by 19 | // requiring your application.js. 20 | //= require application 21 | //= require fake_xml_http_request 22 | //= require fakehr 23 | //= require httpRespond 24 | 25 | Ember.testing = true; 26 | 27 | function exists(selector) { 28 | return !!find(selector).length; 29 | } 30 | 31 | function getAssertionMessage(actual, expected, message) { 32 | return message || QUnit.jsDump.parse(expected) + " expected but was " + QUnit.jsDump.parse(actual); 33 | } 34 | 35 | function equal(actual, expected, message) { 36 | message = getAssertionMessage(actual, expected, message); 37 | QUnit.equal.call(this, actual, expected, message); 38 | } 39 | 40 | function strictEqual(actual, expected, message) { 41 | message = getAssertionMessage(actual, expected, message); 42 | QUnit.strictEqual.call(this, actual, expected, message); 43 | } 44 | 45 | window.exists = exists; 46 | window.equal = equal; 47 | window.strictEqual = strictEqual; 48 | 49 | Ember.Test.registerHelper('shouldHaveElementWithCount', 50 | function(app, selector, n, context) { 51 | var el = findWithAssert(selector, context); 52 | var count = el.length; 53 | equal(n, count, "found " + count + " times"); 54 | } 55 | ); 56 | -------------------------------------------------------------------------------- /lib/generators/templates/view.es6: -------------------------------------------------------------------------------- 1 | export default Ember.View.extend({ 2 | }); 3 | -------------------------------------------------------------------------------- /test/fixtures/rails_4-0-0_Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 4 | gem 'rails', '4.0.1' 5 | 6 | # Use sqlite3 as the database for Active Record 7 | gem 'sqlite3' 8 | 9 | # Use SCSS for stylesheets 10 | gem 'sass-rails', '~> 4.0.0' 11 | 12 | # Use Uglifier as compressor for JavaScript assets 13 | gem 'uglifier', '>= 1.3.0' 14 | 15 | # Use CoffeeScript for .js.coffee assets and views 16 | gem 'coffee-rails', '~> 4.0.0' 17 | 18 | # See https://github.com/sstephenson/execjs#readme for more supported runtimes 19 | # gem 'therubyracer', platforms: :ruby 20 | 21 | # Use jquery as the JavaScript library 22 | gem 'jquery-rails' 23 | 24 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 25 | gem 'turbolinks' 26 | 27 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 28 | gem 'jbuilder', '~> 1.2' 29 | 30 | group :doc do 31 | # bundle exec rake doc:rails generates the API under doc/api. 32 | gem 'sdoc', require: false 33 | end 34 | 35 | # Use ActiveModel has_secure_password 36 | # gem 'bcrypt-ruby', '~> 3.1.2' 37 | 38 | # Use unicorn as the app server 39 | # gem 'unicorn' 40 | 41 | # Use Capistrano for deployment 42 | # gem 'capistrano', group: :development 43 | 44 | # Use debugger 45 | # gem 'debugger', group: [:development, :test] 46 | -------------------------------------------------------------------------------- /test/fixtures/rails_4-0-0_application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require turbolinks 16 | //= require_tree . 17 | -------------------------------------------------------------------------------- /test/fixtures/rails_4-0-0_application_layout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SampleRails400 5 | <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> 6 | <%= javascript_include_tag "application", "data-turbolinks-track" => true %> 7 | <%= csrf_meta_tags %> 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/fixtures/routes_with_api_and_version_namespaces.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.routes.draw do 2 | namespace :api do 3 | namespace :v1 do 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /test/fixtures/routes_with_api_namespace.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.routes.draw do 2 | namespace :api do 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/fixtures/routes_with_api_version_namespaces_and_route.rb: -------------------------------------------------------------------------------- 1 | Dummy::Application.routes.draw do 2 | namespace :api do 3 | namespace :v1 do 4 | resource :dogs, except: [:new, :edit] 5 | end 6 | 7 | end 8 | 9 | namespace :dogs do 10 | 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/fixtures/walker.rb: -------------------------------------------------------------------------------- 1 | require 'parser/current' 2 | require 'byebug' 3 | 4 | file = File.read('routes_with_api_version_namespaces_and_route.rb') 5 | 6 | ast = Parser::CurrentRuby.parse(file) 7 | 8 | class RouteProcessor < AST::Processor 9 | attr_accessor :delete_nodes 10 | 11 | def initialize(*) 12 | @delete_nodes = [] 13 | super 14 | end 15 | 16 | def handler_missing(node) 17 | walk(node) 18 | end 19 | 20 | def on_block(node) 21 | if is_namespace?(node) 22 | if is_namespace_type?(node, :api) 23 | walk_namespace(node) 24 | elsif is_namespace_type?(node, :v1) 25 | walk_namespace(node) 26 | end 27 | else 28 | walk(node) 29 | end 30 | end 31 | 32 | def on_send(node) 33 | if is_resource?(node, :dogs) 34 | delete_nodes << node 35 | end 36 | end 37 | 38 | private 39 | 40 | def is_resource?(node, type) 41 | node.children[1] == :resource && node.children[2].children.first == type.to_sym 42 | end 43 | 44 | def is_namespace?(node) 45 | node.children.first.children[1] == :namespace 46 | end 47 | 48 | def is_namespace_type?(node, type) 49 | node.children.first.children[2].children.first == type.to_sym 50 | end 51 | 52 | def walk_namespace(node) 53 | process(node.children[2]) 54 | if node.children[2].children == delete_nodes.last.to_a 55 | delete_nodes << node 56 | end 57 | end 58 | 59 | def walk(node) 60 | node.children.each do |child| 61 | process(child) if child.respond_to?(:to_ast) 62 | end 63 | end 64 | end 65 | 66 | processor = RouteProcessor.new 67 | processor.process(ast) 68 | if processor.delete_nodes.last.loc.expression 69 | begin_pos = processor.delete_nodes.last.loc.expression.begin_pos 70 | end_pos = processor.delete_nodes.last.loc.expression.end_pos 71 | else 72 | begin_pos = processor.delete_nodes.last.loc.begin.begin_pos 73 | end_pos = processor.delete_nodes.last.loc.end.end_pos 74 | end 75 | begin_pos = begin_pos - file[0..begin_pos].reverse.index("\n") 76 | puts file.sub(file[begin_pos...end_pos], '') 77 | -------------------------------------------------------------------------------- /test/generators/bootstrap_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/bootstrap_generator' 3 | 4 | class BootstrapGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::BootstrapGenerator 8 | destination File.join(Rails.root, "tmp", "generator_test_output") 9 | 10 | setup :prepare_destination, :copy_application, :copy_routes 11 | 12 | test "Assert folder layout and .gitkeep files are properly created" do 13 | run_generator [] 14 | assert_new_dirs 15 | end 16 | 17 | test "create bootstrap" do 18 | run_generator [] 19 | 20 | assert_files 21 | end 22 | 23 | test "create bootstrap with and custom app path" do 24 | custom_path = app_path("custom") 25 | run_generator ["-a", custom_path] 26 | 27 | assert_files custom_path, config_path 28 | assert_file 'config/application.rb', /config\.ember\.paths\.app = '#{custom_path}'/ 29 | end 30 | 31 | test "create bootstrap with and custom config path" do 32 | custom_path = config_path("custom") 33 | run_generator ["-c", custom_path] 34 | 35 | assert_files app_path, custom_path 36 | assert_file 'config/application.rb', /config\.ember\.paths\.config = '#{custom_path}'/ 37 | end 38 | 39 | test "create bootstrap with custom app name" do 40 | run_generator ["-n", "MyApp"] 41 | 42 | assert_file "#{config_path}/application.js", /MyApp = / 43 | 44 | assert_files 45 | end 46 | 47 | test 'Creates bootstrap without Teaspoon' do 48 | run_generator ['-T'] 49 | assert_no_file 'config/initializers/teaspoon.rb' 50 | assert_no_file 'test/teaspoon_env.rb' 51 | assert_no_file 'test/test_helper.js' 52 | end 53 | 54 | test "Uses config.ember.app_name" do 55 | with_config app_name: 'Blazorz' do 56 | run_generator 57 | 58 | assert_files 59 | assert_file "#{config_path}/application.js", /Blazorz = / 60 | end 61 | end 62 | 63 | test "Uses config.ember.appkit.paths.app" do 64 | custom_app_path = app_path("custom_app") 65 | custom_config_path = app_path("custom_config") 66 | 67 | with_config paths: {app: custom_app_path, config: custom_config_path} do 68 | run_generator 69 | 70 | assert_files custom_app_path, custom_config_path 71 | end 72 | end 73 | 74 | test "Removes turbolinks" do 75 | run_generator 76 | 77 | confirm_turbolinks_removed "Gemfile" 78 | confirm_turbolinks_removed "app/views/layouts/application.html.erb" 79 | end 80 | 81 | test "Removed jbuilder" do 82 | run_generator 83 | 84 | assert_file 'Gemfile' do |content| 85 | assert_no_match(/jbuilder/, content) 86 | end 87 | end 88 | 89 | test "Does not error if Gemfile is missing" do 90 | FileUtils.rm destination_root + '/Gemfile' 91 | run_generator 92 | end 93 | 94 | test "Adds commented out greedy matcher to Rails routes file" do 95 | run_generator 96 | 97 | assert_file 'config/routes.rb' do |content| 98 | assert_match(/^ # get '\*foo', :to => 'landing#index'$/, content) 99 | end 100 | end 101 | 102 | private 103 | 104 | def assert_files(app_path = app_path, config_path = config_path) 105 | %W{models controllers views routes components templates templates/components mixins}.each do |dir| 106 | assert_directory "#{app_path}/#{dir}" 107 | end 108 | assert_directory "#{config_path}/serializers" 109 | 110 | assert_file "#{config_path}/environment.js.erb" 111 | assert_file "#{config_path}/environments/development.js.erb" 112 | assert_file "#{config_path}/environments/production.js.erb" 113 | assert_file "#{config_path}/environments/test.js.erb" 114 | assert_file "#{config_path}/application.js" 115 | assert_file "#{config_path}/router.es6" 116 | assert_file "#{config_path}/adapters/application.es6.erb" 117 | assert_file "#{config_path}/initializers/csrf.js" 118 | assert_file "config/initializers/teaspoon.rb" 119 | assert_file "test/teaspoon_env.rb" 120 | assert_file "test/test_helper.js" 121 | end 122 | 123 | def confirm_turbolinks_removed(file) 124 | assert_file file do |content| 125 | assert_no_match(/turbolinks/, content) 126 | end 127 | end 128 | 129 | def confirm_turbolinks_not_removed(file) 130 | assert_file file do |content| 131 | assert_match(/turbolinks/, content) 132 | end 133 | end 134 | end 135 | -------------------------------------------------------------------------------- /test/generators/component_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/component_generator' 3 | 4 | class ComponentGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::ComponentGenerator 8 | destination File.join(Rails.root, "tmp", "generator_test_output") 9 | 10 | setup :prepare_destination 11 | 12 | test "default_component" do 13 | run_generator ["PostChart"] 14 | assert_file "#{app_path}/components/post-chart.es6" 15 | assert_file "#{app_path}/templates/components/post-chart.hbs" 16 | end 17 | 18 | test "Assert files are properly created (CamelCase)" do 19 | run_generator %w(PostChart) 20 | assert_file "#{app_path}/components/post-chart.es6" 21 | assert_file "#{app_path}/templates/components/post-chart.hbs" 22 | end 23 | 24 | test "Assert object names are properly created with CamelCase name" do 25 | run_generator %w(PostChart) 26 | assert_file "#{app_path}/components/post-chart.es6" 27 | assert_file "#{app_path}/templates/components/post-chart.hbs" 28 | end 29 | 30 | test "Assert files are properly created (lower-case)" do 31 | run_generator %w(post-chart) 32 | assert_file "#{app_path}/components/post-chart.es6" 33 | assert_file "#{app_path}/templates/components/post-chart.hbs" 34 | end 35 | 36 | test "Assert object names are properly created with lower-case name" do 37 | run_generator %w(post-chart) 38 | assert_file "#{app_path}/components/post-chart.es6" 39 | assert_file "#{app_path}/templates/components/post-chart.hbs" 40 | end 41 | 42 | test "Uses config.ember.appkit.paths.app" do 43 | custom_path = app_path("custom") 44 | 45 | with_config paths: {app: custom_path} do 46 | run_generator ["PostChart"] 47 | assert_file "#{custom_path}/components/post-chart.es6" 48 | assert_file "#{custom_path}/templates/components/post-chart.hbs" 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /test/generators/controller_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/controller_generator' 3 | 4 | class ControllerGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::ControllerGenerator 8 | destination File.join(Rails.root, "tmp", "generator_test_output") 9 | 10 | setup :prepare_destination 11 | 12 | test "array_controller" do 13 | run_generator ["post", "--array"] 14 | assert_file "#{app_path}/controllers/post.es6" 15 | end 16 | 17 | test "object_controller" do 18 | run_generator ["post", "--object"] 19 | assert_file "#{app_path}/controllers/post.es6" 20 | end 21 | 22 | test "default_controller" do 23 | run_generator ["post"] 24 | assert_file "#{app_path}/controllers/post.es6" 25 | end 26 | 27 | test "Assert files are properly created" do 28 | run_generator %w(ember) 29 | assert_file "#{app_path}/controllers/ember.es6" 30 | end 31 | 32 | test "Uses config.ember.appkit.paths.app" do 33 | custom_path = app_path("custom") 34 | 35 | with_config paths: {app: custom_path} do 36 | run_generator ["post", "--object"] 37 | assert_file "#{custom_path}/controllers/post.es6" 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /test/generators/helper_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/helper_generator' 3 | 4 | class HelperGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::HelperGenerator 8 | destination File.join(Rails.root, 'tmp') 9 | 10 | setup :prepare_destination 11 | 12 | test 'Generates helper correctly' do 13 | run_generator ['catdog'] 14 | assert_file "#{app_path}/helpers/catdog.js", /catdog/ 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/generators/install_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/install_generator' 3 | require 'vcr' 4 | 5 | class InstallGeneratorTest < Rails::Generators::TestCase 6 | tests Ember::Generators::InstallGenerator 7 | destination File.join(Rails.root, "tmp", "generator_test_output") 8 | 9 | setup :prepare_destination, :set_test_environment 10 | 11 | def copy_directory(dir) 12 | source = Rails.root.join(dir) 13 | dest = Rails.root.join("tmp", "generator_test_output", File.dirname(dir)) 14 | 15 | FileUtils.mkdir_p dest 16 | FileUtils.cp_r source, dest 17 | end 18 | 19 | def set_test_environment 20 | ENV['THOR_DEBUG'] = '1' 21 | VCR.configure do |c| 22 | c.cassette_library_dir = 'test/fixtures/vcr_cassettes' 23 | c.hook_into :webmock # or :fakeweb 24 | c.default_cassette_options = { :record => :new_episodes } 25 | end 26 | end 27 | 28 | def create_directory(dir) 29 | dest = Rails.root.join("tmp", "generator_test_output", dir) 30 | FileUtils.mkdir_p dest 31 | end 32 | 33 | test "without any options it load the release channel" do 34 | VCR.use_cassette('fetch_ember_release') do 35 | run_generator 36 | assert_all_ember_files 37 | # assert_all_ember_data_files TODO: Remove after ember data is released 38 | end 39 | end 40 | 41 | test "with options channel=release it should load the release ember-data & ember files" do 42 | VCR.use_cassette('fetch_ember_release') do 43 | run_generator ['--channel=release'] 44 | assert_all_ember_files 45 | # assert_all_ember_data_files TODO: Remove after ember data is released 46 | end 47 | end 48 | 49 | test "with options channel=beta it should load the beta ember-data & ember files" do 50 | VCR.use_cassette('fetch_ember_beta') do 51 | run_generator ['--channel=beta'] 52 | assert_all_ember_files 53 | assert_all_ember_data_files 54 | end 55 | end 56 | 57 | test "with options channel=canary it should load the beta ember-data & ember files" do 58 | VCR.use_cassette('fetch_ember_canary') do 59 | run_generator ['--channel=canary'] 60 | assert_all_ember_files 61 | assert_all_ember_data_files 62 | end 63 | end 64 | 65 | test "with unknown channel option it should raise exception InvalidChannel" do 66 | assert_raise ::InvalidChannel do 67 | run_generator ['--channel=unkown'], debug: true 68 | end 69 | assert_no_ember_files 70 | assert_no_ember_data_files 71 | end 72 | 73 | test "with option ember_only it should only load ember" do 74 | VCR.use_cassette('fetch_ember_release') do 75 | run_generator ['--ember_only'] 76 | end 77 | assert_all_ember_files 78 | assert_no_ember_data_files 79 | end 80 | 81 | test "option --ember aliases --ember_only" do 82 | VCR.use_cassette('fetch_ember_release') do 83 | run_generator ['--ember'] 84 | end 85 | assert_all_ember_files 86 | assert_no_ember_data_files 87 | end 88 | 89 | test "with option ember-data_only it should only load ember" do 90 | VCR.use_cassette('fetch_ember_beta') do 91 | run_generator ['--ember_data_only', '--channel=beta'] 92 | end 93 | assert_no_ember_files 94 | assert_all_ember_data_files 95 | end 96 | 97 | test "option --ember-data aliasses --ember_data_only" do 98 | VCR.use_cassette('fetch_ember_beta') do 99 | run_generator ['--ember-data', '--channel=beta'] 100 | end 101 | assert_no_ember_files 102 | assert_all_ember_data_files 103 | end 104 | 105 | test "with options --tag=v1.0.0-beta.1 --ember-data" do 106 | VCR.use_cassette('fetch_ember_data_tagged') do 107 | run_generator ['--tag=v1.0.0-beta.1', '--ember-data'] 108 | end 109 | assert_no_ember_files 110 | assert_all_ember_data_files 111 | end 112 | 113 | test "with option --tag=v1.2.0-beta.2 --ember" do 114 | VCR.use_cassette('fetch_ember_tagged') do 115 | run_generator ['--tag=v1.2.0-beta.2', '--ember'] 116 | end 117 | assert_all_ember_files 118 | assert_no_ember_data_files 119 | end 120 | 121 | test "with options --channel set and options --tag it should raise exception ConflictingOptions" do 122 | assert_raise ::ConflictingOptions do 123 | run_generator ['--channel=canary', '--tag=v1.2.0-beta.2/ember'], debug: true 124 | end 125 | assert_no_ember_files 126 | assert_no_ember_data_files 127 | end 128 | 129 | test "with options --tag without --ember or --ember-data it should raise exception InsufficientOptions" do 130 | assert_raise ::InsufficientOptions do 131 | run_generator ['--tag=v1.2.0-beta.2'], debug: true 132 | end 133 | assert_no_ember_files 134 | assert_no_ember_data_files 135 | end 136 | 137 | private 138 | 139 | def assert_all_ember_files 140 | assert_file "vendor/assets/javascripts/ember.js" 141 | assert_file "vendor/assets/javascripts/ember.prod.js" 142 | end 143 | 144 | def assert_all_ember_data_files 145 | assert_file "vendor/assets/javascripts/ember-data.js" 146 | assert_file "vendor/assets/javascripts/ember-data.prod.js" 147 | end 148 | 149 | def assert_no_ember_files 150 | assert_no_file "vendor/assets/javascripts/ember.js" 151 | assert_no_file "vendor/assets/javascripts/ember.prod.js" 152 | end 153 | 154 | def assert_no_ember_data_files 155 | assert_no_file "vendor/assets/javascripts/ember-data.js" 156 | assert_no_file "vendor/assets/javascripts/ember-data.prod.js" 157 | end 158 | end 159 | -------------------------------------------------------------------------------- /test/generators/model_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/model_generator' 3 | 4 | class ModelGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::ModelGenerator 8 | destination File.join(Rails.root, "tmp", "generator_test_output") 9 | 10 | setup :prepare_destination 11 | 12 | test "create model" do 13 | run_generator ["post", "title:string"] 14 | assert_file "#{app_path}/models/post.es6" 15 | end 16 | 17 | test "create namespaced model" do 18 | run_generator ["post/dog", "title:string"] 19 | assert_file "#{app_path}/models/post/dog.es6" 20 | end 21 | 22 | test "leave parentheses when create model w/o attributes" do 23 | run_generator ["post"] 24 | assert_file "#{app_path}/models/post.es6", /export default DS.Model.extend/ 25 | end 26 | 27 | test "forces pluarl names to singular" do 28 | run_generator ["posts"] 29 | assert_file "#{app_path}/models/post.es6" 30 | assert_no_file "#{app_path}/models/posts.es6" 31 | end 32 | 33 | test "Assert files are properly created" do 34 | run_generator %w(ember) 35 | 36 | assert_file "#{app_path}/models/ember.es6" 37 | end 38 | 39 | test "Uses config.ember.appkit.paths.app" do 40 | custom_path = app_path("custom") 41 | 42 | with_config paths: {app: custom_path} do 43 | run_generator ["ember"] 44 | assert_file "#{custom_path}/models/ember.es6" 45 | end 46 | end 47 | 48 | test "create test" do 49 | run_generator ["post", "title:string"] 50 | assert_file "test/models/post_test.es6" 51 | end 52 | 53 | test "imports model for test" do 54 | run_generator ["post", "title:string"] 55 | 56 | assert_file 'test/models/post_test.es6', /^import Post from 'app\/models\/post';$/ 57 | end 58 | 59 | test "create namespaced test" do 60 | run_generator ["post/dog", "title:string"] 61 | assert_file "test/models/post/dog_test.es6" 62 | end 63 | 64 | test "imports namespaced model for test" do 65 | run_generator ["post/dog", "title:string"] 66 | 67 | assert_file 'test/models/post/dog_test.es6', /^import Dog from 'app\/models\/post\/dog';$/ 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /test/generators/resource_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/resource_generator' 3 | 4 | class ResourceGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::ResourceGenerator 8 | destination File.join(Rails.root, "tmp") 9 | setup :prepare_destination, :copy_router 10 | 11 | test "create template" do 12 | run_generator ["post"] 13 | assert_file "#{app_path}/templates/posts.hbs" 14 | end 15 | 16 | test "create controller" do 17 | run_generator ["post"] 18 | assert_file "#{app_path}/controllers/posts.es6" 19 | end 20 | 21 | test "create route" do 22 | run_generator ["post"] 23 | assert_file "#{app_path}/routes/posts.es6" 24 | assert_file "#{config_path}/router.es6" do |content| 25 | assert_match(%r{this.resource\('posts'\);}, content) 26 | end 27 | end 28 | 29 | test "skip route" do 30 | run_generator ["post", "--skip-route"] 31 | assert_no_file "#{app_path}/routes/posts.es6" 32 | end 33 | 34 | test "Uses config.ember.appkit.paths.app" do 35 | custom_path = app_path("custom") 36 | copy_router(custom_path) 37 | 38 | with_config paths: {app: custom_path} do 39 | run_generator ["post"] 40 | assert_file "#{custom_path}/controllers/posts.es6" 41 | assert_file "#{custom_path}/routes/posts.es6" 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/generators/resource_override_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ResourceOverrideTest < Rails::Generators::TestCase 4 | include GeneratorTestSupport 5 | 6 | tests Rails::Generators::ResourceGenerator 7 | destination File.join(Rails.root, "tmp") 8 | setup :prepare_destination, :copy_router, :copy_routes 9 | 10 | test "create template without ember" do 11 | run_generator ["post"] 12 | assert_no_file "#{app_path}/templates/posts.hbs" 13 | end 14 | 15 | test "create template with ember" do 16 | run_generator ["post", '--ember'] 17 | assert_file "#{app_path}/templates/posts.hbs" 18 | end 19 | 20 | test "does not create non-essential files for ember apps" do 21 | run_generator ["post", "title:string"] 22 | assert_no_file "#{app_path}/assets/javascripts/posts.js" 23 | assert_no_file "#{app_path}/helpers/posts_helper.rb" 24 | assert_no_directory "#{app_path}/views/posts" 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /test/generators/route_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/route_generator' 3 | 4 | class RouteGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::RouteGenerator 8 | destination File.join(Rails.root, "tmp", "generator_test_output") 9 | 10 | setup :prepare_destination 11 | 12 | test "Assert files are properly created" do 13 | run_generator %w(index) 14 | 15 | assert_file "#{app_path}/routes/index.es6" 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/generators/scaffold_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/scaffold_generator' 3 | 4 | class ScaffoldGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::ScaffoldGenerator 8 | destination File.join(Rails.root, "tmp", "generator_test_output") 9 | setup :prepare_destination, :copy_router 10 | 11 | test "create template" do 12 | run_generator ["post", "published_at:date"] 13 | 14 | assert_files 15 | assert_test_files 16 | assert_inject_into_router 17 | end 18 | 19 | test "with namespaced name" do 20 | run_generator ["post/dog"] 21 | 22 | assert_namespaced_model_find 23 | end 24 | 25 | 26 | private 27 | 28 | def assert_files 29 | assert_file "#{app_path}/models/post.es6" 30 | assert_file "test/models/post_test.es6" 31 | 32 | assert_file "#{app_path}/routes/posts/edit.es6" 33 | assert_file "#{app_path}/routes/posts/index.es6" 34 | assert_file "#{app_path}/routes/posts/new.es6" 35 | assert_file "#{app_path}/routes/posts/show.es6" 36 | 37 | assert_file "#{app_path}/templates/posts.hbs" 38 | assert_file "#{app_path}/templates/posts/edit.hbs" 39 | assert_file "#{app_path}/templates/posts/form.hbs" do |content| 40 | assert_match(/value=publishedAt/, content) 41 | end 42 | assert_file "#{app_path}/templates/posts/index.hbs" do |content| 43 | assert_match(/{{publishedAt}}/, content) 44 | end 45 | assert_file "#{app_path}/templates/posts/new.hbs" 46 | assert_file "#{app_path}/templates/posts/show.hbs" do |content| 47 | assert_match(/{{publishedAt}}/, content) 48 | end 49 | end 50 | 51 | def assert_inject_into_router 52 | js = <<-JS 53 | this.resource('posts', function() { 54 | this.route('new'); 55 | this.route('show', {path: ':post_id'}); 56 | this.route('edit', {path: ':post_id/edit'}); 57 | }); 58 | JS 59 | assert_file "#{config_path}/router.es6" do |content| 60 | assert_match(/#{Regexp.escape(js.rstrip)}/m, content) 61 | end 62 | end 63 | 64 | def assert_namespaced_model_find 65 | assert_file "#{app_path}/routes/dogs/edit.es6" do |content| 66 | assert_match(/return this\.store\.find\('post\/dog', params.dog_id\);/, content) 67 | end 68 | assert_file "#{app_path}/routes/dogs/index.es6" do |content| 69 | assert_match(/return this\.store\.find\('post\/dog'\);/, content) 70 | end 71 | assert_file "#{app_path}/routes/dogs/new.es6" do |content| 72 | assert_match(/return this\.store\.createRecord\('post\/dog'\);/, content) 73 | end 74 | assert_file "#{app_path}/routes/dogs/show.es6" do |content| 75 | assert_match(/return this\.store\.find\('post\/dog', params.dog_id\);/, content) 76 | end 77 | end 78 | 79 | def assert_test_files 80 | assert_file "test/routes/posts/edit_test.es6" do |content| 81 | assert_match(/^import PostsEditRoute from 'app\/routes\/posts\/edit';/, content) 82 | assert_match(/'Unit - PostsEditRoute'/, content) 83 | end 84 | assert_file "test/routes/posts/index_test.es6" do |content| 85 | assert_match(/^import PostsIndexRoute from 'app\/routes\/posts\/index';/, content) 86 | assert_match(/'Unit - PostsIndexRoute'/, content) 87 | end 88 | assert_file "test/routes/posts/new_test.es6" do |content| 89 | assert_match(/^import PostsNewRoute from 'app\/routes\/posts\/new';/, content) 90 | assert_match(/'Unit - PostsNewRoute'/, content) 91 | end 92 | assert_file "test/routes/posts/show_test.es6" do |content| 93 | assert_match(/^import PostsShowRoute from 'app\/routes\/posts\/show';/, content) 94 | assert_match(/'Unit - PostsShowRoute'/, content) 95 | end 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /test/generators/scaffold_override_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ScaffoldOverrideTest < Rails::Generators::TestCase 4 | include GeneratorTestSupport 5 | 6 | tests Rails::Generators::ScaffoldGenerator 7 | destination File.join(Rails.root, "tmp") 8 | setup :prepare_destination, :copy_routes, :copy_router, :reset_api_version 9 | 10 | test "create template without ember" do 11 | run_generator ["post"] 12 | assert_no_file "#{app_path}/templates/posts.hbs" 13 | end 14 | 15 | test "create template with ember" do 16 | run_generator ["post", 'title:string', '--ember'] 17 | assert_file "#{app_path}/templates/posts.hbs" 18 | end 19 | 20 | test "does not create non-essential files for ember apps" do 21 | run_generator ["post", "title:string"] 22 | assert_no_file "#{app_path}/assets/javascripts/posts.js" 23 | assert_no_file "#{app_path}/helpers/posts_helper.rb" 24 | assert_no_directory "#{app_path}/views/posts" 25 | end 26 | 27 | test "creates properly namespaced api route" do 28 | run_generator ["post"] 29 | assert_file 'config/routes.rb' do |content| 30 | assert_match(/ namespace :api do\n namespace :v1 do\n resources :posts, except: \[:new, :edit\]\n end\n end/, content) 31 | end 32 | end 33 | 34 | test "creates api version namespaced controller" do 35 | run_generator ["post"] 36 | assert_file 'app/controllers/api/v1/posts_controller.rb' 37 | end 38 | 39 | test "creates properly namespaced api routes when api namespace already exists" do 40 | copy_routes_with_api_namespace 41 | run_generator ["post"] 42 | assert_file 'config/routes.rb' do |content| 43 | assert_match(/ namespace :api do\n namespace :v1 do\n resources :posts, except: \[:new, :edit\]\n end\n end/, content) 44 | assert_equal 1, content.scan(/api/).size 45 | end 46 | end 47 | 48 | test "creates properly namespaced api routes when api and version namespaces already exists" do 49 | copy_routes_with_api_and_version_namespaces 50 | run_generator ["post"] 51 | assert_file 'config/routes.rb' do |content| 52 | assert_match(/ namespace :api do\n namespace :v1 do\n resources :posts, except: \[:new, :edit\]\n end\n end/, content) 53 | assert_equal 1, content.scan(/api/).size 54 | assert_equal 1, content.scan(/v1/).size 55 | end 56 | end 57 | 58 | test "creates properly namespaced api routes when api and other version namespaces already exists" do 59 | copy_routes_with_api_and_version_namespaces 60 | ::Rails.application.config.ember.api_version = 2 61 | run_generator ["post"] 62 | assert_file 'config/routes.rb' do |content| 63 | assert_match(/ namespace :api do\n namespace :v2 do\n resources :posts, except: \[:new, :edit\]\n end\n namespace :v1 do\n end\n end/, content) 64 | assert_equal 1, content.scan(/api/).size 65 | assert_equal 1, content.scan(/v1/).size 66 | assert_equal 1, content.scan(/v2/).size 67 | end 68 | end 69 | 70 | test 'destroy does not remove any non-matching resources or namespaces' do 71 | copy_routes_with_api_version_namespaces_and_route 72 | config_content = File.read(File.expand_path('config/routes.rb', destination_root)) 73 | run_generator ['post'], behavior: :revoke 74 | 75 | assert_file 'config/routes.rb' do |content| 76 | assert_equal config_content, content 77 | end 78 | end 79 | 80 | test 'destroy removes matching resources and namespaces' do 81 | copy_routes_with_api_version_namespaces_and_route 82 | File.read(File.expand_path('config/routes.rb', destination_root)) 83 | run_generator ['dogs'], behavior: :revoke 84 | 85 | assert_file 'config/routes.rb' do |content| 86 | refute_match(/ namespace :api do\n namespace :v1 do\n resource :dogs, except: \[:new, :edit\]\n end\n end/, content) 87 | end 88 | end 89 | 90 | private 91 | 92 | def reset_api_version 93 | ::Rails.application.config.ember.api_version = 1 94 | end 95 | 96 | def copy_routes_with_api_namespace 97 | copy_routes_file("../../fixtures/routes_with_api_namespace.rb") 98 | end 99 | 100 | def copy_routes_with_api_and_version_namespaces 101 | copy_routes_file("../../fixtures/routes_with_api_and_version_namespaces.rb") 102 | end 103 | 104 | def copy_routes_with_api_version_namespaces_and_route 105 | copy_routes_file("../../fixtures/routes_with_api_version_namespaces_and_route.rb") 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /test/generators/serializer_override_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SerializerOverrideTest < Rails::Generators::TestCase 4 | include GeneratorTestSupport 5 | 6 | tests Rails::Generators::SerializerGenerator 7 | destination File.join(Rails.root, "tmp") 8 | setup :prepare_destination 9 | 10 | test "create serializer under config/serializers" do 11 | run_generator ["post"] 12 | assert_file "#{config_path}/serializers/post_serializer.rb" 13 | end 14 | 15 | test "does not create serializer under app/serializers" do 16 | run_generator ["post"] 17 | assert_no_file "#{app_path}/serializers/post_serializer.rb" 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/generators/template_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/template_generator' 3 | 4 | class TemplateGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::TemplateGenerator 8 | destination File.join(Rails.root, "tmp") 9 | 10 | setup :prepare_destination 11 | 12 | test "generates template" do 13 | run_generator ["post"] 14 | assert_file "#{app_path}/templates/post.hbs" 15 | end 16 | 17 | test "Uses config.ember.appkit.paths.app" do 18 | custom_path = app_path("custom") 19 | 20 | with_config paths: {app: custom_path} do 21 | run_generator ["post"] 22 | assert_file "#{custom_path}/templates/post.hbs" 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /test/generators/view_generator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'generators/ember/view_generator' 3 | 4 | class ViewGeneratorTest < Rails::Generators::TestCase 5 | include GeneratorTestSupport 6 | 7 | tests Ember::Generators::ViewGenerator 8 | destination File.join(Rails.root, "tmp", "generator_test_output") 9 | 10 | setup :prepare_destination 11 | 12 | test "create view with template by default" do 13 | run_generator ["post"] 14 | assert_file "#{app_path}/views/post.es6" 15 | assert_file "#{app_path}/templates/post.hbs" 16 | end 17 | 18 | test "create view without a template" do 19 | run_generator ["post", "--without-template"] 20 | assert_file "#{app_path}/views/post.es6" 21 | assert_no_file "#{app_path}/templates/post.hbs" 22 | end 23 | 24 | test "create view and template (using ember-rails flags)" do 25 | run_generator ["post", "--with-template"] 26 | assert_file "#{app_path}/views/post.es6" 27 | assert_file "#{app_path}/templates/post.hbs" 28 | end 29 | 30 | test "create namespaced view" do 31 | run_generator ["post/index"] 32 | assert_file "#{app_path}/views/post/index.es6" 33 | end 34 | 35 | test "Assert files are properly created" do 36 | run_generator %w(ember) 37 | assert_file "#{app_path}/views/ember.es6" 38 | end 39 | 40 | test "Uses config.ember.appkit.paths.app" do 41 | custom_path = app_path("custom") 42 | 43 | with_config paths: {app: custom_path} do 44 | run_generator [ "ember"] 45 | assert_file "#{custom_path}/views/ember.es6" 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /test/integration/autoload_modules_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AutoloadModulesTest < ActionDispatch::IntegrationTest 4 | include IntegrationTestSupport 5 | 6 | test 'does not auto create modules for directories that do not have ruby files' do 7 | FileUtils.mkdir(File.join(Rails.root, 'app/models/not_a_module')) 8 | 9 | assert_raise NameError do 10 | NotAModule 11 | end 12 | end 13 | 14 | test 'does create modules for directories that have ruby files' do 15 | FileUtils.mkdir(File.join(Rails.root, 'app/models/is_a_module')) 16 | FileUtils.touch(File.join(Rails.root, 'app/models/is_a_module/dog.rb')) 17 | 18 | assert_nothing_raised NameError do 19 | IsAModule 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/integration/engine_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class EngineTest < ActionDispatch::IntegrationTest 4 | test 'app/assets/javascripts is not in asset load path' do 5 | refute Rails.application.config.assets.paths.include?(File.join(Rails.root, 'app/assets/javascripts')) 6 | end 7 | 8 | test 'config/serializers is added to autoload_path' do 9 | assert Rails.application.config.paths.eager_load.include?(File.join(Rails.root, 'config/serializers')) 10 | end 11 | 12 | test 'app is in the asset load path' do 13 | assert Rails.application.config.assets.paths.include?(File.join(Rails.root, 'app')) 14 | end 15 | 16 | test 'config is in the asset load path' do 17 | assert Rails.application.config.assets.paths.include?(File.join(Rails.root, 'config')) 18 | end 19 | 20 | test 'lib is in the asset load path' do 21 | assert Rails.application.config.assets.paths.include?(File.join(Rails.root, 'lib')) 22 | end 23 | 24 | test 'lib/assets/javascripts is not in the asset load path' do 25 | refute Rails.application.config.assets.paths.include?(File.join(Rails.root, 'lib/assets/javascripts')) 26 | end 27 | 28 | test 'ember source assets come after vendor/assets/javascripts' do 29 | vendor_index = Rails.application.config.assets.paths.index(File.join(Rails.root, 'vendor/assets/javascripts')) 30 | ember_source_index = Rails.application.config.assets.paths.index { |path| path =~ /ember-source/ } 31 | ember_data_source_index = Rails.application.config.assets.paths.index { |path| path =~ /ember-data-source/ } 32 | handlebars_source_index = Rails.application.config.assets.paths.index { |path| path =~ /handlebars-source/ } 33 | 34 | assert vendor_index < ember_source_index 35 | assert vendor_index < ember_data_source_index 36 | assert vendor_index < handlebars_source_index 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /test/integration/navigation_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class NavigationTest < ActionDispatch::IntegrationTest 4 | include IntegrationTestSupport 5 | 6 | test 'can render default landing page' do 7 | visit '/' 8 | assert page.has_text? "Welcome to Ember on Rails!" 9 | end 10 | 11 | test 'can using simple "ember magic"' do 12 | visit '/' 13 | fill_in 'sampleInput', with: 'EMBER ROCKS!' 14 | assert page.has_text? "EMBER ROCKS!" 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/support/generator_test_support.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | 3 | module GeneratorTestSupport 4 | # def run_generator(args=self.default_arguments, config={}) 5 | # args += ['--skip-bundle'] unless args.include? '--dev' 6 | # self.generator_class.start(args, config.reverse_merge(destination_root: destination_root)) 7 | # end 8 | 9 | def prepare_destination 10 | super 11 | 12 | tmp_destination = Pathname.new(destination_root) 13 | javascript_destination = tmp_destination.join('app','assets','javascripts') 14 | 15 | FileUtils.mkdir_p javascript_destination 16 | FileUtils.cp "test/fixtures/rails_4-0-0_application.js", javascript_destination.join('application.js') 17 | 18 | FileUtils.mkdir_p tmp_destination.join(app_path) 19 | FileUtils.mkdir_p tmp_destination.join(config_path) 20 | 21 | FileUtils.mkdir_p javascript_destination.join('custom') 22 | FileUtils.cp "test/fixtures/rails_4-0-0_application.js", javascript_destination.join('custom', 'application.js') 23 | 24 | FileUtils.cp 'test/fixtures/rails_4-0-0_Gemfile', tmp_destination.join('Gemfile') 25 | 26 | FileUtils.mkdir_p tmp_destination.join('app','views', 'layouts') 27 | FileUtils.cp 'test/fixtures/rails_4-0-0_application_layout', tmp_destination.join('app','views','layouts', 'application.html.erb') 28 | end 29 | 30 | def with_config(options = {}) 31 | original_values = ::Rails.configuration.ember.clone 32 | original_values.paths = original_values.paths.clone 33 | original_values.paths.app = original_values.paths.app.clone 34 | original_values.paths.config = original_values.paths.config.clone 35 | 36 | options.each do |key, value| 37 | if Hash === value 38 | value.each do |k, v| 39 | ::Rails.configuration.ember[key][k] = v 40 | end 41 | else 42 | ::Rails.configuration.ember[key] = value 43 | end 44 | end 45 | 46 | yield 47 | ensure 48 | ::Rails.configuration.ember.clear 49 | ::Rails.configuration.ember = original_values 50 | end 51 | 52 | def assert_new_dirs(options = {}) 53 | path = options[:in_path] || app_path 54 | 55 | %W{components templates templates/components routes}.each do |dir| 56 | assert_directory "#{path}/#{dir}" 57 | assert_file "#{path}/#{dir}/.gitkeep" 58 | end 59 | end 60 | 61 | def application_name 62 | "App" 63 | end 64 | 65 | def app_path(path = 'app') 66 | path 67 | end 68 | 69 | def config_path(path = 'config') 70 | path 71 | end 72 | 73 | def copy_router(path = config_path) 74 | source = File.expand_path("../../../lib/generators/templates/router.es6", __FILE__) 75 | destination = File.join(destination_root, path) 76 | FileUtils.mkdir_p(destination) 77 | FileUtils.cp source, File.join(destination, 'router.es6') 78 | end 79 | 80 | def copy_application(path = config_path) 81 | source = File.expand_path("../../dummy/config/application.rb", __FILE__) 82 | destination = File.join(destination_root, path) 83 | FileUtils.mkdir_p(destination) 84 | copy_file source, File.join(destination, 'application.rb') 85 | end 86 | 87 | def copy_routes 88 | copy_routes_file("../../dummy/config/routes.rb") 89 | end 90 | 91 | def copy_routes_file(routes_destination) 92 | routes = File.expand_path(routes_destination, __FILE__) 93 | destination = File.join(destination_root, 'config') 94 | FileUtils.mkdir_p(destination) 95 | FileUtils.cp routes, File.join(destination, 'routes.rb') 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /test/support/integration_test_support.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | require 'generators/ember/bootstrap_generator' 3 | 4 | module IntegrationTestSupport 5 | def setup 6 | Dir.chdir 'test/dummy' do 7 | silence_stream(STDOUT) do 8 | Ember::Generators::BootstrapGenerator.start 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # Configure Rails Environment 2 | ENV["RAILS_ENV"] = "test" 3 | 4 | require 'byebug' 5 | require File.expand_path("../dummy/config/environment.rb", __FILE__) 6 | require "rails/test_help" 7 | require 'capybara/rails' 8 | require 'capybara/poltergeist' 9 | require 'minitest/pride' 10 | 11 | Capybara.current_driver = :poltergeist 12 | 13 | Rails.backtrace_cleaner.remove_silencers! 14 | Rails.application.load_generators 15 | 16 | # Load support files 17 | Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } 18 | 19 | class ActionDispatch::IntegrationTest 20 | include Capybara::DSL 21 | end 22 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/app.es6.erb: -------------------------------------------------------------------------------- 1 | <% config = Rails.application.config.ember %> 2 | import Resolver from 'ember/resolver'; 3 | 4 | if (typeof Turbolinks !== 'undefined') { 5 | throw new Error("Turbolinks has been detected. Ember Appkit Rails will not function properly alongside Turbolinks."); 6 | } 7 | 8 | if (window.config === undefined) { window.config = {}; } 9 | 10 | var App = Ember.Application.extend({ 11 | Resolver: Resolver 12 | }, window.config); 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/ember-appkit/index.js: -------------------------------------------------------------------------------- 1 | //= require ./loader 2 | //= require ./resolver 3 | //= require app 4 | //= require templates/application 5 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/ember-appkit/loader.js: -------------------------------------------------------------------------------- 1 | var define, requireModule, require, requirejs; 2 | 3 | (function() { 4 | var registry = {}, seen = {}; 5 | 6 | define = function(name, deps, callback) { 7 | registry[name] = { deps: deps, callback: callback }; 8 | }; 9 | 10 | requirejs = require = requireModule = function(name) { 11 | requirejs._eak_seen = registry; 12 | 13 | if (seen[name]) { return seen[name]; } 14 | seen[name] = {}; 15 | 16 | if (!registry[name]) { 17 | throw new Error("Could not find module " + name); 18 | } 19 | 20 | var mod = registry[name], 21 | deps = mod.deps, 22 | callback = mod.callback, 23 | reified = [], 24 | exports; 25 | 26 | for (var i=0, l=deps.length; i 1) { 240 | return split[0] + ':' + Ember.String.dasherize(split[1].replace(/\./g, '/')); 241 | } else { 242 | return fullName; 243 | } 244 | } 245 | }); 246 | 247 | Resolver['default'] = Resolver; 248 | return Resolver; 249 | }); 250 | 251 | define("resolver", 252 | ["ember/resolver"], 253 | function (Resolver) { 254 | Ember.deprecate('Importing/requiring Ember Resolver as "resolver" is deprecated, please use "ember/resolver" instead'); 255 | return Resolver; 256 | }); 257 | 258 | })(); 259 | 260 | 261 | 262 | (function() { 263 | /*globals define registry requirejs */ 264 | 265 | define("ember/container-debug-adapter", 266 | [], 267 | function() { 268 | "use strict"; 269 | 270 | // Support Ember < 1.5-beta.4 271 | // TODO: Remove this after 1.5.0 is released 272 | if (typeof Ember.ContainerDebugAdapter === 'undefined') { 273 | return null; 274 | } 275 | /* 276 | * This module defines a subclass of Ember.ContainerDebugAdapter that adds two 277 | * important features: 278 | * 279 | * 1) is able provide injections to classes that implement `extend` 280 | * (as is typical with Ember). 281 | */ 282 | 283 | var ContainerDebugAdapter = Ember.ContainerDebugAdapter.extend({ 284 | /** 285 | The container of the application being debugged. 286 | This property will be injected 287 | on creation. 288 | 289 | @property container 290 | @default null 291 | */ 292 | // container: null, LIVES IN PARENT 293 | 294 | /** 295 | The resolver instance of the application 296 | being debugged. This property will be injected 297 | on creation. 298 | 299 | @property resolver 300 | @default null 301 | */ 302 | // resolver: null, LIVES IN PARENT 303 | /** 304 | Returns true if it is possible to catalog a list of available 305 | classes in the resolver for a given type. 306 | 307 | @method canCatalogEntriesByType 308 | @param {string} type The type. e.g. "model", "controller", "route" 309 | @return {boolean} whether a list is available for this type. 310 | */ 311 | canCatalogEntriesByType: function(type) { 312 | return true; 313 | }, 314 | 315 | /** 316 | Returns the available classes a given type. 317 | 318 | @method catalogEntriesByType 319 | @param {string} type The type. e.g. "model", "controller", "route" 320 | @return {Array} An array of classes. 321 | */ 322 | catalogEntriesByType: function(type) { 323 | var entries = requirejs.entries, 324 | module, 325 | types = Ember.A(); 326 | 327 | var makeToString = function(){ 328 | return this.shortname; 329 | }; 330 | 331 | for(var key in entries) { 332 | if(entries.hasOwnProperty(key) && key.indexOf(type) !== -1) 333 | { 334 | // // TODO return the name instead of the module itself 335 | // module = require(key, null, null, true); 336 | 337 | // if (module && module['default']) { module = module['default']; } 338 | // module.shortname = key.split(type +'s/').pop(); 339 | // module.toString = makeToString; 340 | 341 | // types.push(module); 342 | types.push(key.split(type +'s/').pop()); 343 | } 344 | } 345 | 346 | return types; 347 | } 348 | }); 349 | 350 | ContainerDebugAdapter['default'] = ContainerDebugAdapter; 351 | return ContainerDebugAdapter; 352 | }); 353 | 354 | })(); 355 | 356 | 357 | 358 | (function() { 359 | (function() { 360 | "use strict"; 361 | 362 | Ember.Application.initializer({ 363 | name: 'container-debug-adapter', 364 | 365 | initialize: function(container) { 366 | var ContainerDebugAdapter = require('ember/container-debug-adapter'); 367 | var Resolver = require('ember/resolver'); 368 | 369 | container.register('container-debug-adapter:main', ContainerDebugAdapter); 370 | } 371 | }); 372 | }()); 373 | 374 | })(); 375 | 376 | 377 | 378 | (function() { 379 | 380 | })(); 381 | 382 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/fake_xml_http_request.js: -------------------------------------------------------------------------------- 1 | (function(window, undefined){ 2 | /** 3 | * Minimal Event interface implementation 4 | * 5 | * Original implementation by Sven Fuchs: https://gist.github.com/995028 6 | * Modifications and tests by Christian Johansen. 7 | * 8 | * @author Sven Fuchs (svenfuchs@artweb-design.de) 9 | * @author Christian Johansen (christian@cjohansen.no) 10 | * @license BSD 11 | * 12 | * Copyright (c) 2011 Sven Fuchs, Christian Johansen 13 | */ 14 | 15 | var _Event = function Event(type, bubbles, cancelable, target) { 16 | this.type = type; 17 | this.bubbles = bubbles; 18 | this.cancelable = cancelable; 19 | this.target = target; 20 | }; 21 | 22 | _Event.prototype = { 23 | stopPropagation: function () {}, 24 | preventDefault: function () { 25 | this.defaultPrevented = true; 26 | } 27 | }; 28 | 29 | /* 30 | Used to set the statusText property of an xhr object 31 | */ 32 | var httpStatusCodes = { 33 | 100: "Continue", 34 | 101: "Switching Protocols", 35 | 200: "OK", 36 | 201: "Created", 37 | 202: "Accepted", 38 | 203: "Non-Authoritative Information", 39 | 204: "No Content", 40 | 205: "Reset Content", 41 | 206: "Partial Content", 42 | 300: "Multiple Choice", 43 | 301: "Moved Permanently", 44 | 302: "Found", 45 | 303: "See Other", 46 | 304: "Not Modified", 47 | 305: "Use Proxy", 48 | 307: "Temporary Redirect", 49 | 400: "Bad Request", 50 | 401: "Unauthorized", 51 | 402: "Payment Required", 52 | 403: "Forbidden", 53 | 404: "Not Found", 54 | 405: "Method Not Allowed", 55 | 406: "Not Acceptable", 56 | 407: "Proxy Authentication Required", 57 | 408: "Request Timeout", 58 | 409: "Conflict", 59 | 410: "Gone", 60 | 411: "Length Required", 61 | 412: "Precondition Failed", 62 | 413: "Request Entity Too Large", 63 | 414: "Request-URI Too Long", 64 | 415: "Unsupported Media Type", 65 | 416: "Requested Range Not Satisfiable", 66 | 417: "Expectation Failed", 67 | 422: "Unprocessable Entity", 68 | 500: "Internal Server Error", 69 | 501: "Not Implemented", 70 | 502: "Bad Gateway", 71 | 503: "Service Unavailable", 72 | 504: "Gateway Timeout", 73 | 505: "HTTP Version Not Supported" 74 | }; 75 | 76 | 77 | /* 78 | Cross-browser XML parsing. Used to turn 79 | XML responses into Document objects 80 | Borrowed from JSpec 81 | */ 82 | function parseXML(text) { 83 | var xmlDoc; 84 | 85 | if (typeof DOMParser != "undefined") { 86 | var parser = new DOMParser(); 87 | xmlDoc = parser.parseFromString(text, "text/xml"); 88 | } else { 89 | xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); 90 | xmlDoc.async = "false"; 91 | xmlDoc.loadXML(text); 92 | } 93 | 94 | return xmlDoc; 95 | }; 96 | 97 | /* 98 | Without mocking, the native XMLHttpRequest object will throw 99 | an error when attempting to set these headers. We match this behavior. 100 | */ 101 | var unsafeHeaders = { 102 | "Accept-Charset": true, 103 | "Accept-Encoding": true, 104 | "Connection": true, 105 | "Content-Length": true, 106 | "Cookie": true, 107 | "Cookie2": true, 108 | "Content-Transfer-Encoding": true, 109 | "Date": true, 110 | "Expect": true, 111 | "Host": true, 112 | "Keep-Alive": true, 113 | "Referer": true, 114 | "TE": true, 115 | "Trailer": true, 116 | "Transfer-Encoding": true, 117 | "Upgrade": true, 118 | "User-Agent": true, 119 | "Via": true 120 | }; 121 | 122 | /* 123 | Adds an "event" onto the fake xhr object 124 | that just calls the same-named method. This is 125 | in case a library adds callbacks for these events. 126 | */ 127 | function _addEventListener(eventName, xhr){ 128 | xhr.addEventListener(eventName, function (event) { 129 | var listener = xhr["on" + eventName]; 130 | 131 | if (listener && typeof listener == "function") { 132 | listener(event); 133 | } 134 | }); 135 | } 136 | 137 | /* 138 | Constructor for a fake window.XMLHttpRequest 139 | */ 140 | function FakeXMLHttpRequest() { 141 | this.readyState = FakeXMLHttpRequest.UNSENT; 142 | this.requestHeaders = {}; 143 | this.requestBody = null; 144 | this.status = 0; 145 | this.statusText = ""; 146 | 147 | this._eventListeners = {}; 148 | var events = ["loadstart", "load", "abort", "loadend"]; 149 | for (var i = events.length - 1; i >= 0; i--) { 150 | _addEventListener(events[i], this); 151 | } 152 | } 153 | 154 | 155 | // These status codes are available on the native XMLHttpRequest 156 | // object, so we match that here in case a library is relying on them. 157 | FakeXMLHttpRequest.UNSENT = 0; 158 | FakeXMLHttpRequest.OPENED = 1; 159 | FakeXMLHttpRequest.HEADERS_RECEIVED = 2; 160 | FakeXMLHttpRequest.LOADING = 3; 161 | FakeXMLHttpRequest.DONE = 4; 162 | 163 | FakeXMLHttpRequest.prototype = { 164 | UNSENT: 0, 165 | OPENED: 1, 166 | HEADERS_RECEIVED: 2, 167 | LOADING: 3, 168 | DONE: 4, 169 | async: true, 170 | 171 | /* 172 | Duplicates the behavior of native XMLHttpRequest's open function 173 | */ 174 | open: function open(method, url, async, username, password) { 175 | this.method = method; 176 | this.url = url; 177 | this.async = typeof async == "boolean" ? async : true; 178 | this.username = username; 179 | this.password = password; 180 | this.responseText = null; 181 | this.responseXML = null; 182 | this.requestHeaders = {}; 183 | this.sendFlag = false; 184 | this._readyStateChange(FakeXMLHttpRequest.OPENED); 185 | }, 186 | 187 | /* 188 | Duplicates the behavior of native XMLHttpRequest's addEventListener function 189 | */ 190 | addEventListener: function addEventListener(event, listener) { 191 | this._eventListeners[event] = this._eventListeners[event] || []; 192 | this._eventListeners[event].push(listener); 193 | }, 194 | 195 | /* 196 | Duplicates the behavior of native XMLHttpRequest's removeEventListener function 197 | */ 198 | removeEventListener: function removeEventListener(event, listener) { 199 | var listeners = this._eventListeners[event] || []; 200 | 201 | for (var i = 0, l = listeners.length; i < l; ++i) { 202 | if (listeners[i] == listener) { 203 | return listeners.splice(i, 1); 204 | } 205 | } 206 | }, 207 | 208 | /* 209 | Duplicates the behavior of native XMLHttpRequest's dispatchEvent function 210 | */ 211 | dispatchEvent: function dispatchEvent(event) { 212 | var type = event.type; 213 | var listeners = this._eventListeners[type] || []; 214 | 215 | for (var i = 0; i < listeners.length; i++) { 216 | if (typeof listeners[i] == "function") { 217 | listeners[i].call(this, event); 218 | } else { 219 | listeners[i].handleEvent(event); 220 | } 221 | } 222 | 223 | return !!event.defaultPrevented; 224 | }, 225 | 226 | /* 227 | Duplicates the behavior of native XMLHttpRequest's setRequestHeader function 228 | */ 229 | setRequestHeader: function setRequestHeader(header, value) { 230 | verifyState(this); 231 | 232 | if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) { 233 | throw new Error("Refused to set unsafe header \"" + header + "\""); 234 | } 235 | 236 | if (this.requestHeaders[header]) { 237 | this.requestHeaders[header] += "," + value; 238 | } else { 239 | this.requestHeaders[header] = value; 240 | } 241 | }, 242 | 243 | /* 244 | Duplicates the behavior of native XMLHttpRequest's send function 245 | */ 246 | send: function send(data) { 247 | verifyState(this); 248 | 249 | if (!/^(get|head)$/i.test(this.method)) { 250 | if (this.requestHeaders["Content-Type"]) { 251 | var value = this.requestHeaders["Content-Type"].split(";"); 252 | this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8"; 253 | } else { 254 | this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8"; 255 | } 256 | 257 | this.requestBody = data; 258 | } 259 | 260 | this.errorFlag = false; 261 | this.sendFlag = this.async; 262 | this._readyStateChange(FakeXMLHttpRequest.OPENED); 263 | 264 | if (typeof this.onSend == "function") { 265 | this.onSend(this); 266 | } 267 | 268 | this.dispatchEvent(new _Event("loadstart", false, false, this)); 269 | }, 270 | 271 | /* 272 | Duplicates the behavior of native XMLHttpRequest's abort function 273 | */ 274 | abort: function abort() { 275 | this.aborted = true; 276 | this.responseText = null; 277 | this.errorFlag = true; 278 | this.requestHeaders = {}; 279 | 280 | if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) { 281 | this._readyStateChange(FakeXMLHttpRequest.DONE); 282 | this.sendFlag = false; 283 | } 284 | 285 | this.readyState = FakeXMLHttpRequest.UNSENT; 286 | 287 | this.dispatchEvent(new _Event("abort", false, false, this)); 288 | if (typeof this.onerror === "function") { 289 | this.onerror(); 290 | } 291 | }, 292 | 293 | /* 294 | Duplicates the behavior of native XMLHttpRequest's getResponseHeader function 295 | */ 296 | getResponseHeader: function getResponseHeader(header) { 297 | if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { 298 | return null; 299 | } 300 | 301 | if (/^Set-Cookie2?$/i.test(header)) { 302 | return null; 303 | } 304 | 305 | header = header.toLowerCase(); 306 | 307 | for (var h in this.responseHeaders) { 308 | if (h.toLowerCase() == header) { 309 | return this.responseHeaders[h]; 310 | } 311 | } 312 | 313 | return null; 314 | }, 315 | 316 | /* 317 | Duplicates the behavior of native XMLHttpRequest's getAllResponseHeaders function 318 | */ 319 | getAllResponseHeaders: function getAllResponseHeaders() { 320 | if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) { 321 | return ""; 322 | } 323 | 324 | var headers = ""; 325 | 326 | for (var header in this.responseHeaders) { 327 | if (this.responseHeaders.hasOwnProperty(header) && !/^Set-Cookie2?$/i.test(header)) { 328 | headers += header + ": " + this.responseHeaders[header] + "\r\n"; 329 | } 330 | } 331 | 332 | return headers; 333 | }, 334 | 335 | /* 336 | Places a FakeXMLHttpRequest object into the passed 337 | state. 338 | */ 339 | _readyStateChange: function _readyStateChange(state) { 340 | this.readyState = state; 341 | 342 | if (typeof this.onreadystatechange == "function") { 343 | this.onreadystatechange(); 344 | } 345 | 346 | this.dispatchEvent(new _Event("readystatechange")); 347 | 348 | if (this.readyState == FakeXMLHttpRequest.DONE) { 349 | this.dispatchEvent(new _Event("load", false, false, this)); 350 | this.dispatchEvent(new _Event("loadend", false, false, this)); 351 | } 352 | }, 353 | 354 | 355 | /* 356 | Sets the FakeXMLHttpRequest object's response headers and 357 | places the object into readyState 2 358 | */ 359 | _setResponseHeaders: function _setResponseHeaders(headers) { 360 | this.responseHeaders = {}; 361 | 362 | for (var header in headers) { 363 | if (headers.hasOwnProperty(header)) { 364 | this.responseHeaders[header] = headers[header]; 365 | } 366 | } 367 | 368 | if (this.async) { 369 | this._readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED); 370 | } else { 371 | this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED; 372 | } 373 | }, 374 | 375 | 376 | 377 | /* 378 | Sets the FakeXMLHttpRequest object's response body and 379 | if body text is XML, sets responseXML to parsed document 380 | object 381 | */ 382 | _setResponseBody: function _setResponseBody(body) { 383 | verifyRequestSent(this); 384 | verifyHeadersReceived(this); 385 | verifyResponseBodyType(body); 386 | 387 | var chunkSize = this.chunkSize || 10; 388 | var index = 0; 389 | this.responseText = ""; 390 | 391 | do { 392 | if (this.async) { 393 | this._readyStateChange(FakeXMLHttpRequest.LOADING); 394 | } 395 | 396 | this.responseText += body.substring(index, index + chunkSize); 397 | index += chunkSize; 398 | } while (index < body.length); 399 | 400 | var type = this.getResponseHeader("Content-Type"); 401 | 402 | if (this.responseText && (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) { 403 | try { 404 | this.responseXML = parseXML(this.responseText); 405 | } catch (e) { 406 | // Unable to parse XML - no biggie 407 | } 408 | } 409 | 410 | if (this.async) { 411 | this._readyStateChange(FakeXMLHttpRequest.DONE); 412 | } else { 413 | this.readyState = FakeXMLHttpRequest.DONE; 414 | } 415 | }, 416 | 417 | /* 418 | Forces a response on to the FakeXMLHttpRequest object. 419 | 420 | This is the public API for faking responses. This function 421 | takes a number status, headers object, and string body: 422 | 423 | ``` 424 | xhr.respond(404, {Content-Type: 'text/plain'}, "Sorry. This object was not found.") 425 | 426 | ``` 427 | */ 428 | respond: function respond(status, headers, body) { 429 | this._setResponseHeaders(headers || {}); 430 | this.status = typeof status == "number" ? status : 200; 431 | this.statusText = httpStatusCodes[this.status]; 432 | this._setResponseBody(body || ""); 433 | if (typeof this.onload === "function"){ 434 | this.onload(); 435 | } 436 | } 437 | } 438 | 439 | function verifyState(xhr) { 440 | if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { 441 | throw new Error("INVALID_STATE_ERR"); 442 | } 443 | 444 | if (xhr.sendFlag) { 445 | throw new Error("INVALID_STATE_ERR"); 446 | } 447 | } 448 | 449 | 450 | function verifyRequestSent(xhr) { 451 | if (xhr.readyState == FakeXMLHttpRequest.DONE) { 452 | throw new Error("Request done"); 453 | } 454 | } 455 | 456 | function verifyHeadersReceived(xhr) { 457 | if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) { 458 | throw new Error("No headers received"); 459 | } 460 | } 461 | 462 | function verifyResponseBodyType(body) { 463 | if (typeof body != "string") { 464 | var error = new Error("Attempted to respond to fake XMLHttpRequest with " + 465 | body + ", which is not a string."); 466 | error.name = "InvalidBodyException"; 467 | throw error; 468 | } 469 | } 470 | 471 | 472 | window.FakeXMLHttpRequest = FakeXMLHttpRequest; 473 | })(window); 474 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/fakehr.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | // Extends FakeXMLHttpRequest to register each new 3 | // request with fakehr 4 | function FakeRequest(){ 5 | FakeXMLHttpRequest.call(this); 6 | fakehr.addRequest(this); 7 | } 8 | FakeRequest.prototype = FakeXMLHttpRequest.prototype; 9 | 10 | // reference the native XMLHttpRequest object so 11 | // it can be restored lated 12 | var nativeRequest = window.XMLHttpRequest; 13 | 14 | var fakehr = { 15 | addRequest: function(r){ 16 | this.requests.push(r); 17 | }, 18 | start: function(){ 19 | this.requests = this.requests ||[]; 20 | window.XMLHttpRequest = FakeRequest; 21 | }, 22 | stop: function(){ 23 | window.XMLHttpRequest = nativeRequest; 24 | }, 25 | clear: function(){ 26 | var requests = this.requests; 27 | // removes the objects from the original array 28 | // just in case someone is referencing it. 29 | // the removed requests will never get a response. 30 | while (requests.length > 0) { 31 | requests.pop(); 32 | } 33 | }, 34 | reset: function(){ 35 | this.stop(); 36 | this.clear(); 37 | }, 38 | match: function(method, url, readyState){ 39 | if (readyState === undefined) { readyState = 1;} 40 | 41 | var requests = this.requests; 42 | for (var i = requests.length - 1; i >= 0; i--) { 43 | var request = requests[i]; 44 | if(request.method.toLowerCase() === method.toLowerCase() && request.url === url && request.readyState === readyState) { 45 | return request; 46 | } 47 | }; 48 | } 49 | } 50 | 51 | window.fakehr = fakehr; 52 | })(); 53 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/httpRespond.js: -------------------------------------------------------------------------------- 1 | Ember.Test.registerHelper('httpRespond', function(app, verb, url, body, status) { 2 | if(typeof body !== 'string'){ body = JSON.stringify(body); } 3 | 4 | var found = fakehr.match(verb.toUpperCase(), url) 5 | 6 | if (found){ 7 | Ember.run(function() { 8 | found.respond(status || 200, {'content-type': 'application/json'}, body); 9 | }); 10 | } else { 11 | throw("No request intercepted for " + verb.toUpperCase() + " " + url + ". Intercepted requests were: " + fakehr.requests.map(function(r){ return r.method + " " + r.url}).join(", ")); 12 | } 13 | return wait(app); 14 | }); 15 | 16 | /* 17 | This is mildly crazy. Ember.Test increments requets on ajax start 18 | so promises won't resolve until all xhrs complete, but were mocking 19 | them all, so we just remove the ajaxStart and ajaxStop callbacks 20 | until we can merge into master and put some of this behind flags. 21 | */ 22 | Ember.Test.onInjectHelpers(function() { 23 | Ember.$(document).unbind("ajaxStart ajaxStop"); 24 | }); --------------------------------------------------------------------------------