Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List Spike - not for merging #27

Open
wants to merge 98 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
5ce821a
WIP: List API
eliotsykes Aug 23, 2015
d9c2d2a
Authorizer adds X-Api-Key to API request headers
eliotsykes Aug 24, 2015
5d7a686
Document next steps for list page
eliotsykes Aug 24, 2015
eb2a60e
Style lists page draft
eliotsykes Aug 25, 2015
43c7cae
List styling WIP
eliotsykes Sep 5, 2015
c9459da
Tweak colors
eliotsykes Sep 5, 2015
aa6ac91
Reminder to migrate Polish notes
eliotsykes Sep 5, 2015
57fec10
Style lists, remove tables
eliotsykes Sep 5, 2015
b981ff7
Remove footer from Your Lists
eliotsykes Sep 5, 2015
7613ace
New Lists link at top of list
eliotsykes Sep 5, 2015
732bc48
Remove stale WIP from WIP.md
eliotsykes Sep 5, 2015
3189d14
Simplify remaining CRUD tasks for Your lists
eliotsykes Sep 5, 2015
f57af67
Style link to new list
eliotsykes Sep 5, 2015
0f41ec8
Use Ember's link-to
eliotsykes Sep 5, 2015
cd2d48a
Add list.new route
eliotsykes Sep 6, 2015
077c379
Move nav to appear only on home page
eliotsykes Sep 6, 2015
d605515
Move nav to appear only on home page
eliotsykes Sep 6, 2015
1179904
Introduce header style and nav link
eliotsykes Sep 6, 2015
128e3e0
New list-form component
eliotsykes Sep 7, 2015
b641979
Tweak header colors
eliotsykes Sep 7, 2015
29814cb
Notes on duplicate list creation with null id issue
eliotsykes Sep 7, 2015
5e5d8e6
Make ListsController#create API Ember-Data compliant
eliotsykes Sep 7, 2015
0f5a363
Use isDirty
eliotsykes Sep 8, 2015
9defa7a
Notes on what to do next
eliotsykes Sep 9, 2015
fc296ea
JsonHelper.parse(str) method added
eliotsykes Sep 9, 2015
4ec38fe
Installed binstubs for pry-rescue
eliotsykes Sep 9, 2015
5eae622
Install pry-rescue
eliotsykes Sep 9, 2015
c475bef
Implement and test ListSerializer
eliotsykes Sep 9, 2015
24c2bd2
Fix test for Api::ListsController#create
eliotsykes Sep 9, 2015
cbae317
Juggling code in list-form component
eliotsykes Sep 9, 2015
46359cb
Disable save button when saving
eliotsykes Sep 10, 2015
fa24ad3
Add ellipsis to 'Saving...' button text
eliotsykes Sep 10, 2015
b88bb42
Beginning New List Feature Spec
eliotsykes Sep 10, 2015
9aa599b
Shared footer styles
eliotsykes Sep 10, 2015
ad7cdb8
Put all login helper methods in login_helper
eliotsykes Sep 10, 2015
c106a02
Sign out link in lists footer
eliotsykes Sep 10, 2015
ce287a8
Introduce visit_login_page_and_login helper method
eliotsykes Sep 10, 2015
e6c2cb5
De-emphasize Sign Out link
eliotsykes Sep 10, 2015
57a054a
Older Ember uses isDirty not hasDirtyAttributes
eliotsykes Sep 10, 2014
b5b86cf
Add clear_notification option to login helper
eliotsykes Sep 10, 2015
7d89b33
Offline-first/last notes
eliotsykes Sep 10, 2015
5ed9c1f
Add migration to make list title non-null
eliotsykes Sep 12, 2015
a4a19fa
Reminder to run rake db:migrate
eliotsykes Sep 12, 2015
ec562e5
Add validation for required list title
eliotsykes Sep 12, 2015
18a85f1
Remove required from input field
eliotsykes Sep 12, 2015
a96b03d
Progress with list features
eliotsykes Sep 12, 2015
6fb9f26
Handle invalid list creation via API
eliotsykes Sep 12, 2015
b6c70fe
Show validation error if user tries to save blank list title
eliotsykes Sep 12, 2015
f8469ba
Add missing semi-colon
eliotsykes Sep 12, 2015
6e18e32
Test cancelled lists with titles aren't shown in index
eliotsykes Sep 12, 2015
201d40b
Remove stale feature specs
eliotsykes Sep 12, 2015
ad90fc3
Add list page matchers module
eliotsykes Sep 12, 2015
b55f5e9
Begin work on edit & delete list feature specs
eliotsykes Sep 13, 2015
dcdd860
Edit mode link in 'Your Lists' page
eliotsykes Sep 13, 2015
7097523
List edit mode specs
eliotsykes Sep 13, 2015
a81fc59
Rename feature spec to list_index from view_lists
eliotsykes Sep 13, 2015
a5f6731
Generate controller with 'bin/ember generate controller list/index --…
eliotsykes Sep 13, 2015
a5611a6
Introduce editsLocked queryParam
eliotsykes Sep 13, 2015
191936c
Note on ember generate controller
eliotsykes Sep 13, 2015
1ff975f
Edit List Route
eliotsykes Sep 13, 2015
fc904cd
WIP: Handle list edits
eliotsykes Sep 13, 2015
628acb6
Work towards edit and new route handling their own
eliotsykes Sep 14, 2015
02b8e4e
Move edit unlock test to more appropriate feature spec
eliotsykes Sep 18, 2015
2b07797
Remove unused comments
eliotsykes Sep 18, 2015
61d4836
Fix lint errors
eliotsykes Sep 18, 2015
2dd0433
Fix lint errors
eliotsykes Sep 18, 2015
b58c3fa
WIP: Moving action work into routes
eliotsykes Sep 18, 2015
4c86350
Use transitionTo directly
eliotsykes Sep 18, 2015
44a1846
Refactor out duplication
eliotsykes Sep 18, 2015
4731ee5
Better test coverage
eliotsykes Sep 18, 2015
a6278cc
Update list request spec (failing)
eliotsykes Sep 18, 2015
e1c72eb
Update todos
eliotsykes Sep 18, 2015
50c6afc
Logout page for testing use greens instead of reds
eliotsykes Sep 19, 2015
3c9475f
Restrict lists API routes
eliotsykes Sep 19, 2015
a0b6b09
Replace where.first with find_by in authenticate
eliotsykes Sep 19, 2015
bbd431e
Favor current_user over @user
eliotsykes Sep 19, 2015
0bf84d1
Consolidate error handling into render_errors
eliotsykes Sep 19, 2015
40beb1f
Test for blank list title when no list given
eliotsykes Sep 19, 2015
5cbd68d
Temporary stiches for update list spec for non-API controller
eliotsykes Sep 19, 2015
2ad7da0
Delete list working
eliotsykes Sep 19, 2015
308d69e
Delete list spec passing
eliotsykes Sep 19, 2015
49fe4b0
Show Deleting... on button if list is being deleted
eliotsykes Sep 19, 2015
b4e5f4b
Common transitionToListIndex() function
eliotsykes Sep 19, 2015
ab5052a
Remove unneeded local variables
eliotsykes Sep 19, 2015
160008e
Convenience notify(msg) function
eliotsykes Sep 19, 2015
b54101a
Reminders of next steps
eliotsykes Sep 19, 2015
d4e0840
WIP GET /api/v1/lists/:id to show list via JSON
eliotsykes Oct 2, 2015
3538b68
Assert API lists/show unauthorized response when auth token missing
eliotsykes Oct 2, 2015
187f900
Test show list API responds with 404 Not Found for list belonging to …
eliotsykes Oct 2, 2015
0fb4229
GET /api/v1/lists/:id responds with 404 Not Found for non-existent list
eliotsykes Oct 2, 2015
373a6b0
Refresh module for feature specs
eliotsykes Oct 2, 2015
41b9d8c
Use refresh module
eliotsykes Oct 2, 2015
262b370
Test that edit list page is refreshable
eliotsykes Oct 2, 2015
adbbd32
Update TODOs
eliotsykes Oct 2, 2015
d3c5c1f
Style delete button in red
eliotsykes Oct 2, 2015
52129b7
Style Edit List links
eliotsykes Oct 2, 2015
ef87397
Update TODOs
eliotsykes Oct 2, 2015
aa8781c
Get edit/delete list buttons displaying reliably
eliotsykes Oct 4, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
171 changes: 171 additions & 0 deletions GUIDE.md
Expand Up @@ -4147,3 +4147,174 @@ How are all the 2 feature specs we've written doing? Run them both, they should
```bash
bin/rspec spec/features/user_*
```


## List UI

Spike in progress.

Spike should enable:

- view lists
- create list
- delete list
- edit list

See `~/dev/app-store-rails/asr-todo/client` for approach in that app. In-line editing, see `~/dev/app-store-rails/asr-todo/client/app/templates/components/todo-widget.hbs`

Run:
```bash
bin/ember generate model list title:string --pod
```

outputs:
```
installing
create app/pods/list/model.js
installing
create tests/unit/pods/list/model-test.js
```

TODO: Add spec for list page first before generating model

Generate application authorizer. The authorizer is responsible for including the API token in every request to the backend.

```bash
bin/ember generate authorizer application
```
outputs and creates file:
```
installing
create app/authorizers/application.js
```

Configure the authorizer to use in `ENV['simple-auth']` in `client/config/environment.js`:

```diff
--- a/client/config/environment.js
+++ b/client/config/environment.js
@@ -23,7 +23,8 @@ module.exports = function(environment) {

ENV['simple-auth'] = {
authenticationRoute: 'session.new',
- routeAfterAuthentication: 'list'
+ routeAfterAuthentication: 'list',
+ authorizer: 'authorizer:application'
};

if (environment === 'development') {
```

Save `client/app/authorizers/application.js` with contents:

```diff
--- /dev/null
+++ b/client/app/authorizers/application.js
@@ -0,0 +1,12 @@
+import Base from 'simple-auth/authorizers/base';
+
+export default Base.extend({
+ authorize(jqXHR, requestOptions) {
+ let isAuthenticated = this.get('session.isAuthenticated');
+ let token = this.get('session.secure.token');
+
+ if (isAuthenticated && !Ember.isEmpty(token)) {
+ jqXHR.setRequestHeader('X-Api-Key', token);
+ }
+ }
+});
```

Modify `client/app/pods/list/index/route.js`:

```js
import Ember from 'ember';

export default Ember.Route.extend({
model() {
return this.store.findAll('list');
}
});
```

Modify `client/app/pods/list/index/template.hbs`:

```
TODO
```

TODO: Instructions on updating stylesheets to latest and add new ones.

Run Ember's generate command to generate a route for creating new lists:

```bash
# Inside your-rails-app/ directory:
bin/ember generate route list/new --pod
```

This will generate the following output and files inside the list pod:

```
installing
create app/pods/list/new/route.js
create app/pods/list/new/template.hbs
installing
create tests/unit/pods/list/new/route-test.js
```

The generate will modify `client/app/router.js` for you, by nesting the `list.new` route within the existing `list` route:

```diff
--- a/client/app/router.js
+++ b/client/app/router.js
@@ -12,7 +12,9 @@ Router.map(function() {
this.route('user.new', { path: '/register' });
this.route('confirmation-pending');
this.route('session.new', { path: '/login' });
- this.route('list', function() {});
+ this.route('list', function() {
+ this.route('new');
+ });
});

export default Router;
```

The name of this component will be `list-form`. Generate it with this command:

```bash
bin/ember generate component list-form --pod
```

Generates:

```
installing
create app/pods/components/list-form/component.js
create app/pods/components/list-form/template.hbs
installing
create tests/unit/pods/components/list-form/component-test.js
```


`ListsController#create` needed tweaks:

- `status: :created`
- Root node of `list` in generated JSON (requirement of Ember Data)


Explain `Model#isSaving` and other related `isMethods` and what dirty attributes are.

TODO: Include instructions to run `rake db:migrate` since changing null constraint of lists title column.

```bash
# Generate controller needed for queryParams.editsLocked:
bin/ember generate controller list/index --pod
```

```bash
# Generate route with path option for editing list:
bin/ember generate route list/edit --path=:list_id/edit --pod
```

TODO: Merge POLISH.md notes from branch to master
4 changes: 3 additions & 1 deletion Gemfile
Expand Up @@ -13,7 +13,6 @@ group :development do
end

group :test do
gem 'rspec-rails', '~> 3.1.0'
gem 'database_cleaner'
gem 'factory_girl_rails'
gem 'capybara'
Expand All @@ -23,7 +22,10 @@ group :test do
end

group :development, :test do
gem 'rspec-rails', '~> 3.1.0'
gem 'rspec'
gem 'pry-rails'
gem 'pry-rescue'
gem 'spring-commands-rspec'
end

Expand Down
10 changes: 10 additions & 0 deletions Gemfile.lock
Expand Up @@ -102,6 +102,7 @@ GEM
activesupport (>= 4.1.0)
hike (1.2.3)
i18n (0.7.0)
interception (0.5)
jbuilder (2.2.12)
activesupport (>= 3.0.0, < 5)
multi_json (~> 1.2)
Expand Down Expand Up @@ -132,6 +133,9 @@ GEM
slop (~> 3.4)
pry-rails (0.3.4)
pry (>= 0.9.10)
pry-rescue (1.4.2)
interception (>= 0.5)
pry
pundit (0.3.0)
activesupport (>= 3.0.0)
rack (1.6.0)
Expand Down Expand Up @@ -173,6 +177,10 @@ GEM
railties (>= 4.2.0, < 5)
restclient (0.10.1)
paint (~> 0.8)
rspec (3.1.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-core (3.1.7)
rspec-support (~> 3.1.0)
rspec-expectations (3.1.2)
Expand Down Expand Up @@ -266,10 +274,12 @@ DEPENDENCIES
jquery-rails
pg
pry-rails
pry-rescue
pundit
rails (= 4.2.0)
rails_12factor
restclient
rspec
rspec-rails (~> 3.1.0)
sass-rails (~> 4.0.3)
sdoc (~> 0.4.0)
Expand Down
8 changes: 4 additions & 4 deletions app/controllers/api/api_controller.rb
@@ -1,5 +1,5 @@
class Api::ApiController < ActionController::Base

before_action :authenticate

private
Expand All @@ -10,11 +10,11 @@ def current_user

def authenticate
api_key = request.headers['X-Api-Key']
@user = User.where(api_key: api_key).first if api_key
@user = User.find_by(api_key: api_key) if api_key

unless @user
head status: :unauthorized
return false
end
end
end
end
26 changes: 19 additions & 7 deletions app/controllers/api/v1/lists_controller.rb
Expand Up @@ -2,31 +2,43 @@ class Api::V1::ListsController < Api::ApiController
respond_to :json

def index
render json: @user.lists
render json: current_user.lists
end

def new
@list = List.new
def show
render json: current_user.lists.find(params[:id])
end

def create
@list = @user.lists.new(list_params)
if @list.save
render json: @list
list = current_user.lists.new(list_params)
if list.save
render json: list, status: :created
else
render_errors list
end
end

def update
respond_with current_user.lists.find(params[:id]).update_attributes(list_params)
list = current_user.lists.find(params[:id])
if list.update(list_params)
head :no_content
else
render_errors list
end
end

def destroy
respond_with current_user.lists.destroy(params[:id])
end

private

def list_params
params.require(:list).permit(:title)
end

def render_errors(list)
render json: {errors: list.errors.full_messages}, status: :unprocessable_entity
end

end
2 changes: 2 additions & 0 deletions app/models/list.rb
@@ -1,4 +1,6 @@
class List < ActiveRecord::Base
belongs_to :user
has_many :items

validates :title, presence: true
end
3 changes: 3 additions & 0 deletions app/serializers/list_serializer.rb
@@ -0,0 +1,3 @@
class ListSerializer < ActiveModel::Serializer
attributes :id, :title
end
16 changes: 16 additions & 0 deletions bin/kill-pry-rescue
@@ -0,0 +1,16 @@
#!/usr/bin/env ruby
#
# This file was generated by Bundler.
#
# The application 'kill-pry-rescue' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)

require 'rubygems'
require 'bundler/setup'

load Gem.bin_path('pry-rescue', 'kill-pry-rescue')
16 changes: 16 additions & 0 deletions bin/rescue
@@ -0,0 +1,16 @@
#!/usr/bin/env ruby
#
# This file was generated by Bundler.
#
# The application 'rescue' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)

require 'rubygems'
require 'bundler/setup'

load Gem.bin_path('pry-rescue', 'rescue')
13 changes: 13 additions & 0 deletions client/app/authorizers/application.js
@@ -0,0 +1,13 @@
import Ember from 'ember';
import Base from 'simple-auth/authorizers/base';

export default Base.extend({
authorize(jqXHR/*, requestOptions*/) {
let isAuthenticated = this.get('session.isAuthenticated');
let token = this.get('session.secure.token');

if (isAuthenticated && !Ember.isEmpty(token)) {
jqXHR.setRequestHeader('X-Api-Key', token);
}
}
});