-
Create the top-level app directory:
mkdir masterminder cd masterminder
-
Create the ember app inside your app directory. Rename it
frontend/
.ember new masterminder --skip-git --dir=frontend
-
Create the rails-api app using Postgres. Rename it
backend/
.rails-api new mastermind -T --database=postgresql mv masterminder backend
-
Initialize a git repo in your top-level app directory:
cd .. git init git add -A git commit -m "Initial commit."
-
Add
active_model_serializers
gem and testing and debugging gems and bundle. Commit your changes. Make sure to specify version 0.8.3 for active_model_serializers if you're using Rails 4.2! (which you should be).# Gemfile gem 'active_model_serializers', '0.8.3' group :test do gem 'shoulda-matchers', require: false end group :development, :test do gem 'factory_girl_rails' gem 'faker' gem 'pry-rails' gem 'rspec-rails', '~> 3.0.0' end
cd backend bundle install git add -A git commit -m "Add active_model_serializers, debugging and testing gems."
-
[PROLLY DO THIS STEP LATER] Add a rake task to start up your Rails and Ember apps.
You should be able to access your Ember app at
http://localhost:4200
once you start the server:cd ../frontend ember server
Your Rails app, meanwhile, can be accessed at
http://localhost:3000
Let's add a rake task that will start up both those servers from your top-level directory. Create a
Rakefile
in your top-level directory containing the following:require "rake" task :run do pids = [ spawn("cd backend && rails s"), spawn("cd frontend && ./node_modules/.bin/ember server --proxy http://localhost:3000"), ] trap "INT" do Process.kill "INT", *pids exit 1 end loop do sleep 1 end end
Now running
rake run
should start up both your rails and ember servers.
The first thing our wizards want to do is add a world domination scheme. Let's first test the pages that'll display those schemes.
As an evil wizard
I want to view a list of all projects
So that I can see all of the world domination schemes
Acceptance Criteria:
* I see links to all of the world domination schemes.
-
Create the acceptance test using the ember-cli generator:
ember generate acceptance-test projects
The ember-cli generator generates the following file for us:
// frontend/tests/acceptance/projects-test.js import Ember from 'ember'; import startApp from '../helpers/start-app'; var application; module('Acceptance: Projects', { setup() { application = startApp(); }, teardown() { Ember.run(application, 'destroy'); } }); test('visiting /projects', function() { visit('/projects'); andThen(() => { equal(currentPath(), 'projects'); }); });
This created some setup for our tests, as well as a test that's making sure that once we visit the
/projects
path, we're actually on that path.Since we haven't created a route for
/projects
yet, this test should fail. You can see that by navigating to http://localhost:4200/tests (make sure your server is running). You should see something like:The error tells us we need to create a route, similar if we were to visit a url in a capybara test in Rails where we hadn't started to implement the feature.
Let's add that route, in the
frontend/app/router.js
file:Router.map(function() { // add this line this.route('projects'); });
Now that test should be passing.
-
Add more tests.
In addition to testing that the route exists, we also want to test some other stuff, such as:
A. that we can navigate to the
/projects
page from the homepage.B. that the correct content appears on our
/projects
page. Specifically, let's test that the page contains links to each project.Add the following tests, plus additional setup. Your test file should look like this:
import Ember from 'ember'; import startApp from '../helpers/start-app'; // import pretender addon to mock api response import Pretender from 'pretender'; // make server variable available in your tests (if that is indeed what this line does? IDK maybe I should learn javascript someday) var application, server; module('Acceptance: Projects', { setup() { application = startApp(); // create some fake projects for pretender to serve up var projects = [ { id: 1, name: 'Lock up world oil supply' }, { id: 2, name: 'Tank the U.S. dollar' }, { id: 3, name: 'Smite the world with plague of man-eating ladybugs' } ]; // use pretender to serve up those fake projects server = new Pretender(function(){ this.get('/api/v1/projects', function(request){ return [200, {"Content-Type": "application/json"}, JSON.stringify({projects: projects})]; }); }); }, teardown() { Ember.run(application, 'destroy'); } }); // add some tests! test('Should allow navigation to the projects page from the landing page', function() { visit('/').then(() => { click('a:contains("Projects")'); }); andThen(=> () { equal(find('h3').text(), 'All World Domination Schemes'); }); }); test('visiting /projects', function() { visit('/projects'); andThen(() => { equal(currentPath(), 'projects.index'); equal(find('h3:contains("All World Domination Schemes")').length, 1); equal(find('a:contains("Lock up world oil supply")').length, 1); equal(find('a:contains("Tank the U.S. dollar")').length, 1); equal(find('a:contains("Smite the world with plague of man-eating ladybugs")').length, 1); }); });
There's one other thing we need to do before we can start making our tests pass. The setup we just added is using an addon called ember-cli-pretender to mock a response from the Rails API (which we have yet to build). To use it, we'll need to add the ember-cli-pretender addon:
cd frontend ember install ember-cli-pretender
If we start our server and visit http://localhost:4200/tests, we should see our failing tests.
Now let's make the tests pass.
- Add link to
/projects
page
// frontend/app/templates/application.hbs <h2 id="title">Mastermind</h2> {{link-to 'Projects' 'projects'}} {{outlet}}
- Add templates for projects index & show pages
// frontend/app/templates/projects.hbs <h3>All World Domination Schemes</h3> {{outlet}}
[NOTE: Eric says you don't need a
projects.hbs
template but couldn't get test to pass w/o it.]// frontend/app/templates/projects/index.hbs <ul> {{#each model as |project|}} <li>{{link-to project.name 'projects.show' project.id}}</li> {{/each}} </ul>
- Add routes to projects index and show pages in router
// frontend/app/router.js Router.map(function() { this.route('projects', function() { this.route('show', { path: ':id' }); }); });
- Add route for projects index
$ ember g route projects/index
// frontend/app/routes/projects/index.js import Ember from 'ember'; export default Ember.Route.extend({ model() { return this.store.findAll('project'); }, });
- Add project model:
$ ember g model project name:string
// frontend/app/models/project.js import DS from 'ember-data'; export default DS.Model.extend({ name: DS.attr('string') });
- Add link to