Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: sectore/CafeTownsend-Spine-Rails
base: 4b99c0f21a
...
head fork: sectore/CafeTownsend-Spine-Rails
compare: eda6a88970
Checking mergeability… Don't worry, you can still create the pull request.
  • 2 commits
  • 47 files changed
  • 0 commit comments
  • 1 contributor
Showing with 1,333 additions and 324 deletions.
  1. +3 −0  .gitmodules
  2. +16 −5 Gemfile
  3. +16 −6 Gemfile.lock
  4. +1 −0  Procfile
  5. +22 −6 README.md
  6. +210 −0 app/assets/javascripts/app/controllers/employees_controller.coffee
  7. +46 −0 app/assets/javascripts/app/controllers/header_controller.coffee
  8. +54 −0 app/assets/javascripts/app/controllers/main_controller.coffee
  9. +72 −0 app/assets/javascripts/app/controllers/session_controller.coffee
  10. +39 −0 app/assets/javascripts/app/index.js.coffee
  11. +7 −0 app/assets/javascripts/app/lib/view.js.coffee
  12. +4 −0 app/assets/javascripts/app/models/employee_model.coffee
  13. +4 −0 app/assets/javascripts/app/models/session_model.coffee
  14. +61 −0 app/assets/javascripts/app/views/employees/edit.jst.eco
  15. +11 −0 app/assets/javascripts/app/views/employees/index.jst.eco
  16. +5 −0 app/assets/javascripts/app/views/employees/item.jst.eco
  17. +60 −0 app/assets/javascripts/app/views/employees/new.jst.eco
  18. +11 −0 app/assets/javascripts/app/views/footer.jst.eco
  19. +4 −0 app/assets/javascripts/app/views/header.jst.eco
  20. +32 −0 app/assets/javascripts/app/views/login.jst.eco
  21. +1 −0  app/assets/javascripts/application.js
  22. +319 −0 app/assets/stylesheets/index.css.scss
  23. +117 −0 app/assets/stylesheets/mixin.css.scss
  24. +18 −0 app/controllers/application_controller.rb
  25. +51 −0 app/controllers/employees_controller.rb
  26. +24 −0 app/controllers/sessions_controller.rb
  27. +2 −0  app/helpers/employees_helper.rb
  28. +2 −0  app/helpers/sessions_helper.rb
  29. +2 −0  app/models/employee.rb
  30. +5 −0 app/models/user.rb
  31. +0 −14 app/views/layouts/application.html.erb
  32. +18 −0 app/views/layouts/index.html.erb
  33. +3 −52 config/routes.rb
  34. +12 −0 db/migrate/20120120101212_create_employees.rb
  35. +10 −0 db/migrate/20120120101448_create_users.rb
  36. +32 −0 db/schema.rb
  37. +35 −0 db/seeds.rb
  38. BIN  public/images/header.png
  39. BIN  public/images/invalid.png
  40. BIN  public/images/valid.png
  41. +0 −241 public/index.html
  42. +3 −0  test/test_helper.rb
  43. 0  {app/models → vendor/assets/javascripts}/.gitkeep
  44. +1 −0  vendor/assets/javascripts/spine
  45. BIN  wiki/cafetownsend-spine-rails-edit.png
  46. BIN  wiki/cafetownsend-spine-rails-login.png
  47. BIN  wiki/cafetownsend-spine-rails-overview.png
View
3  .gitmodules
@@ -0,0 +1,3 @@
+[submodule "vendor/assets/javascripts/spine"]
+ path = vendor/assets/javascripts/spine
+ url = git://github.com/maccman/spine.git
View
21 Gemfile
@@ -5,8 +5,6 @@ gem 'rails', '3.1.1'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
-gem 'sqlite3'
-
# Gems used only for assets and not required
# in production environments by default.
@@ -14,14 +12,14 @@ group :assets do
gem 'sass-rails', '~> 3.1.4'
gem 'coffee-rails', '~> 3.1.1'
gem 'uglifier', '>= 1.0.3'
- gem 'spine-rails'
- gem 'eco'
end
gem 'jquery-rails'
+gem 'eco'
+
# To use ActiveModel has_secure_password
-# gem 'bcrypt-ruby', '~> 3.0.0'
+gem 'bcrypt-ruby', '~> 3.0.0'
# Use unicorn as the web server
# gem 'unicorn'
@@ -35,4 +33,17 @@ gem 'jquery-rails'
group :test do
# Pretty printed test output
gem 'turn', :require => false
+ gem 'minitest'
+end
+
+
+group :development, :test do
+ gem 'sqlite3'
+end
+# Switch from SQLite to PostgreSQL for deployment to Heroku
+# Also, Heroku is running Thin (not Webrick) as a webserver
+# http://railsapps.github.com/rails-heroku-tutorial.html
+group :production do
+ gem 'pg'
+ gem 'thin'
end
View
22 Gemfile.lock
@@ -31,6 +31,7 @@ GEM
multi_json (~> 1.0)
ansi (1.4.1)
arel (2.2.1)
+ bcrypt-ruby (3.0.1)
builder (3.0.0)
coffee-rails (3.1.1)
coffee-script (>= 2.2.0)
@@ -39,26 +40,30 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.2.0)
+ daemons (1.1.6)
eco (1.0.0)
coffee-script
eco-source
execjs
eco-source (1.1.0.rc.1)
erubis (2.7.0)
- execjs (1.2.13)
+ eventmachine (0.12.10)
+ execjs (1.3.0)
multi_json (~> 1.0)
hike (1.2.1)
i18n (0.6.0)
jquery-rails (1.0.19)
railties (~> 3.0)
thor (~> 0.14)
- json (1.6.4)
+ json (1.6.5)
mail (2.3.0)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.17.2)
+ minitest (2.11.0)
multi_json (1.0.4)
+ pg (0.12.2)
polyglot (0.3.3)
rack (1.3.6)
rack-cache (1.1)
@@ -93,13 +98,15 @@ GEM
railties (~> 3.1.0)
sass (~> 3.1.10)
tilt (~> 1.3.2)
- spine-rails (0.0.9)
- rails (>= 3.1.0)
sprockets (2.0.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.5)
+ thin (1.3.1)
+ daemons (>= 1.0.9)
+ eventmachine (>= 0.12.6)
+ rack (>= 1.0.0)
thor (0.14.6)
tilt (1.3.3)
treetop (1.4.10)
@@ -108,7 +115,7 @@ GEM
turn (0.8.3)
ansi
tzinfo (0.3.31)
- uglifier (1.2.1)
+ uglifier (1.2.2)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
@@ -116,12 +123,15 @@ PLATFORMS
ruby
DEPENDENCIES
+ bcrypt-ruby (~> 3.0.0)
coffee-rails (~> 3.1.1)
eco
jquery-rails
+ minitest
+ pg
rails (= 3.1.1)
sass-rails (~> 3.1.4)
- spine-rails
sqlite3
+ thin
turn
uglifier (>= 1.0.3)
View
1  Procfile
@@ -0,0 +1 @@
+web: bundle exec rails server thin -p $PORT
View
28 README.md
@@ -1,18 +1,34 @@
#Spine + Rails port of Cafe Townsend application
-### Please note, this demo is still in progress...
-
##About
-[Spine](http://spinejs.com/) and [Rails](http://rubyonrails.org/) port of the famous Cafe Townsend application originally written in ActionScript. It's like a part 2 of the demo ["CafeTownsend-Spine"](https://github.com/sectore/CafeTownsend-Spine) I wrote few days before.
+[Spine](http://spinejs.com/) and [Rails](http://rubyonrails.org/) port of the famous Cafe Townsend application originally written in ActionScript. This is part 2 of the demo ["CafeTownsend-Spine"](https://github.com/sectore/CafeTownsend-Spine) - now with running Rails at the back-end.
##Screen shots
-coming soon
+[![Click on screen shot to see live demo on Heroku](https://github.com/sectore/CafeTownsend-Spine-Rails/raw/master/wiki/cafetownsend-spine-rails-login.png "Login")](http://cafetownsend-spine-rails.herokuapp.com)
+
+[![Click on screen shot to see live demo on Heroku](https://github.com/sectore/CafeTownsend-Spine-Rails/raw/master/wiki/cafetownsend-spine-rails-overview.png "Overview")](http://cafetownsend-spine-rails.herokuapp.com)
+
+[![Click on screen shot to see live demo on Heroku](https://github.com/sectore/CafeTownsend-Spine-Rails/raw/master/wiki/cafetownsend-spine-rails-edit.png "Edit")](http://cafetownsend-spine-rails.herokuapp.com)
+
##Live example
-coming soon
+[http://cafetownsend-spine-rails.herokuapp.com](http://cafetownsend-spine-rails.herokuapp.com/)
##Local installation
-coming soon
+1) Open Terminal
+
+ git clone git://github.com/sectore/CafeTownsend-Spine-Rails.git
+ cd CafeTownsend-Spine-Rails
+ bundle install --without production
+ rake db:migrate
+ rake db:seed
+ rails server
+
+2) Open [http://localhost:3000](http://localhost:3000/) using [Chrome](https://www.google.com/chrome)
##Author
Jens Krause // [WEBSECTOR.DE](http://www.websector.de)
+
+Please note:
+Coming from a strong [ActionScript background](http://www.websector.de) this demo is a personal project for a better understanding of using [Spine](http://spinejs.com/) and [Rails](http://rubyonrails.org). Any tips or improvements are welcome!
+
View
210 app/assets/javascripts/app/controllers/employees_controller.coffee
@@ -0,0 +1,210 @@
+#List = require 'spine/lib/list'
+$ = jQuery.sub()
+Employee = App.Employee
+
+
+###
+ MainController for employees views
+ It handles routes and the view stacks of employees
+ Also it handles EmployeeEvent's which are tiggered from other Controllers
+###
+class App.EmployeesController extends Spine.Controller
+
+ className:
+ 'employees'
+
+ constructor: ->
+ super
+
+ @employeeViewStack = new EmployeesViewStack()
+
+ @append @employeeViewStack
+
+ ###
+ routes using by employeesViewStack
+ ###
+ @routes
+ '/employees/new': (params) ->
+ data = { id: params.id, add: true }
+ @employeeViewStack.new.active( data )
+
+ '/employees/:id/edit': (params) ->
+ data = { id: params.id, edit: true }
+ @employeeViewStack.edit.active( data )
+
+ # handle global event using @proxy
+ # to ensure executing the event handler in the correct context
+ Spine.bind 'EmployeeEvent:DELETE', @proxy( @confirmDelete )
+
+
+ ###
+ @overridden
+ to ensure that the overview is active
+ Because we can define one route handler for '/employee' only
+ which is already in MainController defined
+ ###
+ active:(params) ->
+ super params
+ @employeeViewStack.index.active()
+
+ confirmDelete: (employee) ->
+ @delete(employee) if confirm "Are you sure you want to delete #{ employee.first_name } #{ employee.last_name }?"
+
+ delete:(employee) ->
+ employee.destroy()
+ @navigate '/employees'
+
+
+
+###
+ Controller to show a list of all employees.
+ Selected employee can be deleted or changed.
+ New employees can be added
+###
+class EmployeesOverview extends Spine.Controller
+
+ className:
+ 'employees-index'
+
+ elements:
+ '#employee-list': 'items'
+
+ events:
+ 'click #bAdd': 'add' # clicking Add button
+ 'click #bEdit': 'edit' # clicking Edit button
+ 'click #bDelete': 'delete' # clicking Delete button
+ 'dblclick .item': 'edit' # double clicking item of list
+
+ constructor: ->
+ super
+
+ Employee.bind 'refresh change', @render
+
+ @html @view('employees/index')()
+
+ @list = new Spine.List
+ el: @items,
+ template: @view('employees/item')
+ selectFirst: true
+
+ @list.bind 'change', @change
+
+ # a flag to fetch data only once
+ @fetchData = true
+
+ @active @handleActive
+
+
+ change: (employeeID) =>
+ @employee = Employee.find employeeID if employeeID?
+
+ render: =>
+ employees = Employee.all()
+ @list.render(employees)
+
+ edit: (event) ->
+ if @employee?
+ @navigate '/employees', @employee.id, 'edit'
+
+ handleActive: =>
+ # fetch data from data only once
+ # if the view is activated by the view stack for the first time
+ if @fetchData
+ Employee.fetch()
+ @fetchData = false
+ #trigger render
+ @render()
+
+ add: (event) ->
+ @navigate '/employees/new'
+
+ delete: ->
+ if @employee?
+ Spine.trigger 'EmployeeEvent:DELETE', @employee
+
+
+###
+ Controller to edit (or delete) an employee
+###
+class EditEmployee extends Spine.Controller
+
+ className:
+ 'employee-edit'
+
+ elements:
+ 'form': 'form'
+
+ events:
+ 'submit form': 'save' # clicking Save button
+ 'click .bBack': 'back' # clicking Back button
+ 'click .bDelete': 'delete' # clicking Delete button
+
+ constructor: ->
+ super
+ @active @render
+
+ render: (params) =>
+ @employee = Employee.find params.id
+ @html @view('employees/edit')( employee: @employee )
+
+ delete: ->
+ event.preventDefault()
+ Spine.trigger 'EmployeeEvent:DELETE', @employee
+
+ back: ->
+ @navigate '/employees'
+
+ save: (event) ->
+ event.preventDefault()
+ @employee.fromForm(@form).save()
+ @navigate '/employees'
+
+
+###
+ Controller to add an employee
+###
+class NewEmployee extends Spine.Controller
+
+ className:
+ 'employee-new'
+
+ elements:
+ 'form': 'form'
+
+ events:
+ 'submit form': 'save' # submit form
+ 'click .bCancel': 'cancel' # clicking Cancel button
+
+ constructor: ->
+ super
+ @active @render
+
+ render: =>
+ @html @view('employees/new')()
+
+ cancel: ->
+ @navigate '/employees'
+
+ save: (event) ->
+ event.preventDefault()
+ employee = Employee.fromForm(@form).save()
+ @navigate '/employees' if employee
+
+
+
+###
+ ViewStack of all employees-views (index/edit/new)
+###
+class EmployeesViewStack extends Spine.Stack
+
+ className:
+ 'employees-view stack'
+
+ controllers:
+ index: EmployeesOverview
+ edit: EditEmployee
+ new: NewEmployee
+
+ # Note: Avoid index as a default controller
+ # because it is activated and fetches data before an user is logged in
+ #default: 'index'
View
46 app/assets/javascripts/app/controllers/header_controller.coffee
@@ -0,0 +1,46 @@
+$ = jQuery.sub()
+
+Session = App.Session
+
+###
+ Controller for the header view
+###
+class App.HeaderController extends Spine.Controller
+
+ # overridden
+ tag:
+ 'header'
+
+ events:
+ 'click p.main-button': 'triggerLogout' # clicking logout
+
+ constructor: ->
+ super
+ @render()
+
+ render: ->
+ @html @view('header')()
+
+
+ activate:()->
+ # we do only have one session object after login
+ # grab it and show its username
+ session = Session.first()
+ # greetings text
+ if session?
+ greetings = 'Hello ' + session.name + "!"
+ else
+ greetings = ''
+ # add text
+ $('#greetings').text(greetings)
+ # animate header to show
+ $('header div').animate({top: '0'})
+
+ deactivate:->
+ # empty greetings text
+ $('#greetings').text('')
+ # animate header to hide
+ $('header div').animate({top: '50'})
+
+ triggerLogout: ->
+ @navigate '/logout'
View
54 app/assets/javascripts/app/controllers/main_controller.coffee
@@ -0,0 +1,54 @@
+$ = jQuery.sub()
+
+HeaderController = App.HeaderController
+SessionController = App.SessionController
+EmployeesController = App.EmployeesController
+
+###
+ MainController of the app
+ It instantiates all needed Controller for the main-view
+ and handles the "main" routes to show or hides views
+###
+class App.MainController extends Spine.Controller
+
+ className: 'main-view'
+
+ constructor: ->
+ super
+
+
+ mainViewStack = new MainViewStack()
+ header = new HeaderController()
+ footer = @view('footer')()
+
+ ###
+ defining routes
+ ###
+ @routes
+ '/login': ->
+ # change height of MainViewStack's @elem
+ $('div .main-view-content').height(400)
+ mainViewStack.login.active()
+ header.deactivate()
+ '/employees': ->
+ # change height of MainViewStack's @elem
+ $('div .main-view-content').height(530)
+ mainViewStack.employees.active()
+ header.activate()
+
+ @append header, mainViewStack, footer
+
+
+###
+ MainViewStack for handling login- and employees view
+ Note: All subviews for employees will be handled within EmployeesController
+###
+class MainViewStack extends Spine.Stack
+
+ className: 'main-view-content stack'
+
+ controllers:
+ employees: EmployeesController
+ login: SessionController
+
+ default: 'login'
View
72 app/assets/javascripts/app/controllers/session_controller.coffee
@@ -0,0 +1,72 @@
+Session = App.Session
+
+###
+ Controller to login / logout an user
+
+ Please note:
+ This controller handles again Spine's core values: Asynchronous UIs
+ Because logging in needs to wait of a server respond (authentication)
+ to avoid rendering content without a logged in user
+
+ To get more info about Spine's "Asynchronous UI"
+ check out http://spinejs.com/docs/ajax
+
+###
+class App.SessionController extends Spine.Controller
+
+ className: 'login'
+
+ elements:
+ 'form': 'form'
+
+ events:
+ 'submit form': 'login'
+
+
+ constructor: ->
+ super
+
+ @routes
+ '/logout': ->
+ @logout()
+
+ # bind active event to @render
+ @active @render
+
+ render: ->
+ @html @view('login')()
+
+
+ login: (event) ->
+ event.preventDefault()
+
+
+ @session = Session.fromForm(@form)
+ # bind ajax events of Session,
+ # because in this case we don't use Spines (build-in) asynchronous UI concept
+ @session.bind "ajaxSuccess", @loginResultHandler
+ @session.bind "ajaxError", @loginErrorHandler
+ @session.save()
+
+
+ logout: ->
+ # clear session data
+ @session.destroy()
+ delete @session
+ # navigate back to '/login'
+ @navigate '/login'
+
+
+ loginResultHandler: (status, xhr) =>
+ @session.unbind()
+ @session.authorized = xhr.authorized
+
+ if @session.authorized is "true"
+ @navigate '/employees'
+ else
+ alert "Invalid username or password!"
+
+
+ loginErrorHandler: (record, xhr, settings, error) =>
+ @session.unbind() if @session?
+ alert "Error: " + error
View
39 app/assets/javascripts/app/index.js.coffee
@@ -0,0 +1,39 @@
+#= require jquery
+#= require spine/lib/spine
+#= require spine/lib/manager
+#= require spine/lib/ajax
+#= require spine/lib/route
+#= require spine/lib/tmpl
+#= require spine/lib/list
+
+#= require_tree ./lib
+#= require_self
+
+# models
+#= require_tree ./models
+
+#
+# controllers has to be in a special order to avoid issues
+#= require ./controllers/session_controller
+#= require ./controllers/employees_controller
+#= require ./controllers/header_controller
+#= require ./controllers/main_controller
+
+# views
+#= require_tree ./views
+
+class App extends Spine.Controller
+
+ constructor: ->
+ super
+
+ # initialize and append controller of MainView
+ main = new App.MainController
+ @append main
+
+ # setup routes
+ Spine.Route.setup()
+ # let's start routing to show login
+ @navigate('/login')
+
+window.App = App
View
7 app/assets/javascripts/app/lib/view.js.coffee
@@ -0,0 +1,7 @@
+Spine.Controller.include
+
+ ###
+ helper method for rendering eco templates
+ ###
+ view: (name) ->
+ JST["app/views/#{name}"]
View
4 app/assets/javascripts/app/models/employee_model.coffee
@@ -0,0 +1,4 @@
+class App.Employee extends Spine.Model
+ @configure 'Employee', 'first_name', 'last_name', 'start_date', 'email'
+
+ @extend Spine.Model.Ajax
View
4 app/assets/javascripts/app/models/session_model.coffee
@@ -0,0 +1,4 @@
+class App.Session extends Spine.Model
+ @configure 'Session', 'name', 'password', 'authorized'
+
+ @extend Spine.Model.Ajax
View
61 app/assets/javascripts/app/views/employees/edit.jst.eco
@@ -0,0 +1,61 @@
+<ul id="sub-nav">
+ <li><a class="subButton bBack">Back</a></li>
+</ul>
+<form>
+ <fieldset>
+ <legend>
+ Edit
+ </legend>
+ <label>
+ <span>First name:</span>
+ <input
+ type="text"
+ name="first_name"
+ value="<%= @employee.first_name %>"
+ required
+ autofocus
+ />
+ </label>
+ <label>
+ <span>Last name:</span>
+ <input
+ type="text"
+ name="last_name"
+ value="<%= @employee.last_name %>"
+ required
+ />
+ </label>
+
+
+ <label>
+ <span>Start date:</span>
+ <!--
+ RegEx for date format YYYY-MM-DD:
+ @see: http://www.regular-expressions.info/regexbuddy/datemmddyyyy.html
+ -->
+ <input
+ type="text"
+ name="start_date"
+ value="<%= @employee.start_date %>"
+ pattern="(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])"
+ title="Please enter a date formatting YYYY-MM-DD"
+ required
+ />
+ </label>
+
+ <label><span>Email:</span>
+ <input
+ type="email"
+ name="email"
+ value="<%= @employee.email %>"
+ required
+ />
+ </label>
+
+ <div class="formFooter">
+ <button type="submit" class="main-button">Save</button>
+ <button class="bDelete main-button">Delete</button>
+ </div>
+
+ </fieldset>
+</form>
View
11 app/assets/javascripts/app/views/employees/index.jst.eco
@@ -0,0 +1,11 @@
+<ul id="sub-nav">
+ <li><a id="bAdd" class="subButton">Create</a></li>
+ <li><a id="bEdit" class="subButton">Edit</a></li>
+ <li><a id="bDelete" class="subButton">Delete</a></li>
+</ul>
+
+<div id="employee-list-container">
+ <ul id="employee-list">
+
+ </ul>
+</div>
View
5 app/assets/javascripts/app/views/employees/item.jst.eco
@@ -0,0 +1,5 @@
+<% for employee in @: %>
+<li class="item" data-item="<%= employee.id %>">
+ <%= employee.first_name %> <%= employee.last_name %>
+</li>
+<% end %>
View
60 app/assets/javascripts/app/views/employees/new.jst.eco
@@ -0,0 +1,60 @@
+<ul id="sub-nav">
+ <li><a class="subButton bCancel">Cancel</a></li>
+</ul>
+<form>
+ <fieldset>
+ <legend>
+ New
+ </legend>
+ <label>
+ <span>First name:</span>
+ <input
+ type="text"
+ value="<%= @first_name %>"
+ name="first_name"
+ required
+ autofocus
+ />
+ </label>
+ <label>
+ <span>Last name:</span>
+ <input
+ type="text"
+ value="<%= @last_name %>"
+ name="last_name"
+ required
+ />
+ </label>
+
+
+ <label>
+ <span>Start date:</span>
+ <!--
+ RegEx for date format YYYY-MM-DD:
+ @see: http://www.regular-expressions.info/regexbuddy/datemmddyyyy.html
+ -->
+ <input
+ type="text"
+ value="<%= @start_date %>"
+ name="start_date"
+ pattern="(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])"
+ title="Please enter a date formatting YYYY-MM-DD"
+ required
+ />
+ </label>
+
+ <label><span>Email:</span>
+ <input
+ type="email"
+ value="<%= @email %>"
+ name="email"
+ required
+ />
+ </label>
+
+ <div class="formFooter">
+ <button type="submit" class="main-button">Save</button>
+ </div>
+
+ </fieldset>
+</form>
View
11 app/assets/javascripts/app/views/footer.jst.eco
@@ -0,0 +1,11 @@
+<footer>
+ <p>
+ Built with <a href="http://spinejs.com/">Spine</a>,
+ <a href="http://rubyonrails.org/">Rails</a>,
+ <a href="http://sass-lang.com/">Sass</a>
+ and <a href="https://github.com/sstephenson/eco">Eco</a>, most written in <a href="http://coffeescript.org/">CoffeeScript</a>.
+ </p>
+ <p>
+ <a href="https://github.com/sectore/CafeTownsend-Spine">Get source code</a> by <a href="http://www.websector.de">Jens Krause</a> @2012
+ </p>
+</footer>
View
4 app/assets/javascripts/app/views/header.jst.eco
@@ -0,0 +1,4 @@
+<div>
+ <p class="main-button">Logout</p>
+ <p id="greetings" />
+</div>
View
32 app/assets/javascripts/app/views/login.jst.eco
@@ -0,0 +1,32 @@
+<form id="login-form">
+ <fieldset>
+ <legend>
+ Login
+ </legend>
+ <label>
+ <span>Username *</span>
+ <input
+ type="text"
+ name="name"
+ title="Please enter your username"
+ required
+ autofocus
+ />
+ </label>
+
+ <label>
+ <span>Passwort *</span>
+ <input
+ type="password"
+ name="password"
+ title="Please enter your password"
+ required
+ />
+ </label>
+
+ <button type="submit" class="main-button">Login</button>
+ <p>Username: "Luke" Password: "Skywalker"</p>
+
+
+ </fieldset>
+</form>
View
1  app/assets/javascripts/application.js
@@ -6,4 +6,5 @@
//
//= require jquery
//= require jquery_ujs
+//= require app
//= require_tree .
View
319 app/assets/stylesheets/index.css.scss
@@ -0,0 +1,319 @@
+// Place all the styles related to the employees controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+//
+// Mixins
+//
+@import "mixin";
+
+//
+// constants
+//
+$MAIN_CONTENT_WIDTH: 480px;
+$MAIN_CONTENT_MARGIN: 0 auto;
+
+$MAIN_FONT: "Helvetica Neue", helvetica, arial, sans-serif;
+$MAIN_FONT_SIZE: 17px;
+
+$TRANSITION_DURATION: .5s;
+$TRANSITION_EASE_FUNC: linear;
+
+//
+// global tags
+//
+body,
+html,
+p {
+ padding: 0;
+ margin: 0;
+}
+
+*:focus {
+ outline: none;
+}
+
+
+body {
+ line-height: 19px;
+ font-size: $MAIN_FONT_SIZE;
+ font-family: $MAIN_FONT;
+ color: #363636;
+ font-weight: normal;
+ background-color: #F4F4F4;
+}
+
+a {
+
+ text-decoration: underline;
+ color: #888;
+ &:hover{
+ color: #333;
+ }
+}
+
+ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.main-view{
+ width: $MAIN_CONTENT_WIDTH;
+ margin: $MAIN_CONTENT_MARGIN;
+ padding: 80px 0 0 0;
+}
+
+.main-view-content {
+ position: relative; /* needed to move header content */
+ @include border-box;
+ @include box-shadow( 0, 0, 15px, #888);
+ width: 480px;
+ height: 430px;
+ background: #FFF url(/images/header.png) no-repeat top left;
+ padding-top: 110px;
+ border: 10px solid #363636;
+}
+
+
+header
+footer
+.content{
+ width: $MAIN_CONTENT_WIDTH;
+ margin: $MAIN_CONTENT_MARGIN;
+}
+
+header{
+
+ height: 50px;
+
+ div{
+ position: relative;
+ height: 50px;
+ top: 50px;
+
+ p#greetings{
+ position: absolute;
+ bottom: 4px;
+ left: 40px;
+ }
+
+ p.main-button{
+ position: absolute;
+ right: 15px;
+ bottom: -5px;
+ }
+ }
+
+}
+
+footer{
+ padding-top: 8px;
+ font-size: 15px;
+ line-height: 21px;
+ color: #888;
+ text-align: center;
+ text-shadow: white 1px 1px 1px;
+}
+
+
+/*
+ @overridden
+ .ng-invalid
+ .ng-valid
+ are CSS classes used by angular
+ http://docs-next.angularjs.org/guide/dev_guide.templates.css-styling
+*/
+form{
+ @include vbox;
+ padding: 20px;
+
+ label{
+ @include hbox;
+ padding: 10px 0;
+ }
+
+ label span{
+ display: block;
+ width: 100px;
+ }
+
+ p.error-message{
+ width: 100%;
+ }
+
+ input{
+ @include border-box;
+ width: 270px;
+ height: 35px;
+ padding: 5px 10px;
+ padding-right: 20px;
+ border: 1px solid #AAA;
+ @include box-shadow( 0px 0px 3px #ccc );
+ @include border-radius( 0 10px 15px #eee );
+ font-size: $MAIN_FONT_SIZE;
+
+ &:focus{
+ background: #FFF;
+ border: 1px solid #555;
+ @include box-shadow( 0 0 3px #aaa );
+
+ &:invalid{
+ background: #FFF url("/images/invalid.png") no-repeat 98% center !important;
+ border-color: #FF3366;
+ }
+ }
+
+ &:required.valid{
+ background: #FFF url("/images/valid.png") no-repeat 98% center;
+ }
+ }
+
+
+ div.formFooter{
+ @include hbox;
+ margin-top: 10px;
+ }
+
+ button[type="submit"].main-button{
+ margin: 10px 20px 0 100px;
+ }
+
+ p.main-button{
+ margin: 10px 20px 0 0;
+ }
+
+ p.bDelete,
+ p.bCancel{
+ color: #888;
+ text-decoration: underline;
+
+ &:hover{
+ color: #363636;
+ cursor: pointer;
+ }
+ }
+}
+
+
+legend{
+ display: none;
+}
+
+fieldset{
+ border: none;
+}
+
+#login-form{
+ margin-top: 10px;
+
+ p {
+ padding-left: 100px;
+ padding-top: 10px;
+ font-size: 13px;
+ color: #AAA;
+ }
+}
+
+.main-button{
+
+ @include border-box;
+ width: 125px;
+
+ background-color: #363636;
+ border: 5px solid #FFF;
+
+ padding: 5px 0;
+
+ font-size: 17px;
+
+ text-align: center;
+
+ color: #FFF;
+
+ @include box-shadow( 0, 0, 8px, #888);
+
+ @include transition( background-color, $TRANSITION_DURATION, $TRANSITION_EASE_FUNC );
+ @include transition( color, $TRANSITION_DURATION, $TRANSITION_EASE_FUNC );
+ @include transition( border-color, $TRANSITION_DURATION, $TRANSITION_EASE_FUNC );
+
+ &:hover{
+ background-color: #FFF;
+ border-color: #363636;
+ color: #363636;
+ cursor: pointer;
+ }
+
+ &:disabled{
+ opacity: .5;
+ &:hover{
+ background-color: #363636;
+ border-color: #FFF;
+ color: #FFF;
+ cursor: default;
+ }
+ }
+
+}
+
+.subButton{
+ display:block;
+ @include border-box;
+ width: 100px;
+
+ padding: 5px 0;
+
+ @include vbg-gradient(#FFF, #F4F4F4);
+ border: 1px solid #363636;
+
+ color: #363636;
+ font-size: 15px;
+
+ text-decoration: none;
+ text-align: center;
+
+ &:hover{
+ opacity:.85;
+ cursor: pointer;
+ @include vbg-gradient(#F4F4F4, #FFF);
+ }
+}
+
+#employee-list-container{
+ overflow-y: auto;
+ height: 340px;
+}
+
+#employee-list{
+ width: 100%;
+
+ li{
+ padding: 15px 30px;
+ @include transition( background-color, $TRANSITION_DURATION, $TRANSITION_EASE_FUNC );
+
+ &:hover{
+ background-color: #888;
+ color: #FFF;
+ cursor: pointer;
+ }
+
+ &.active{
+ background-color: #888;
+ color: #FFF;
+ }
+ }
+}
+
+#sub-nav{
+ @include hbox;
+ height: 60px;
+ background-color: #F4F4F4;
+
+ li{
+ padding-left: 30px;
+ }
+}
+
+.stack > *:not(.active) {
+ display: none;
+}
View
117 app/assets/stylesheets/mixin.css.scss
@@ -0,0 +1,117 @@
+// Place all the styles related to the sessions controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+//
+// mixins
+//
+// Most of the mixins are copied from CSS code generated by Hem (Spine.js)
+// @see http://spinejs.com/docs/hem
+//
+
+
+@mixin border-radius($arguments){
+ -moz-border-radius: $arguments;
+ -webkit-border-radius: $arguments;
+ border-radius: $arguments;
+}
+
+// Vertical Background Gradient
+@mixin vbg-gradient($fc: #FFF, $tc: #FFF){
+ background: $fc;
+ background: -webkit-gradient(linear, left top, left bottom, from($fc), to($tc));
+ background: -moz-linear-gradient(top, $fc, $tc);
+ background: linear-gradient(top, $fc, $tc);
+}
+
+// Horizontal Background Gradient
+@mixin hbg-gradient($fc: #FFF, $tc: #FFF){
+ background: $fc;
+ background: -webkit-gradient(linear, left top, right top, from(fc), to(tc));
+ background: -moz-linear-gradient(left, $fc, $tc);
+ background: linear-gradient(left, fc, tc);
+}
+
+@mixin box-shadow($x: 0px, $y: 0px, $length: 5px,$color: #000){
+ -moz-box-shadow: $x $y $length $color;
+ -webkit-box-shadow: $x $y $length $color;
+ box-shadow: $x $y $length $color;
+}
+
+@mixin inset-box-shadow($x: 0px, $y: 0px, $length: 5px,$color: #000){
+ -moz-box-shadow: inset $x $y $length $color;
+ -webkit-box-shadow: inset $x $y $length $color;
+ box-shadow: inset $x $y $blur $length;
+}
+
+@mixin box-flex($s: 0){
+ -webkit-box-flex: $s;
+ -moz-box-flex: $s;
+ box-flex: $s;
+}
+
+@mixin hbox(){
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: center;
+ -webkit-box-pack: start;
+
+ display: -moz-box;
+ -moz-box-orient: horizontal;
+ -moz-box-align: center;
+ -moz-box-pack: start;
+}
+
+@mixin vbox(){
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+}
+
+@mixin border-box(){
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+@mixin transition($t, $s: 0.3s, $e: linear){
+ -webkit-transition: $t $s $e;
+ -moz-transition: $t $s $e;
+ transition: $t $s $e;
+}
+
+@mixin ellipsis(){
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space:nowrap;
+}
+
+@mixin inset-line($opacity: 0.4, $size: 1px){
+ @include inset-box-shadow(0, $size, 0, rgba(255, 255, 255, $opacity));
+}
+
+@mixin outset-line($opacity: 0.4, $size: 1px){
+ @include box-shadow(0, $size, 0, rgba(255, 255, 255, $opacity));
+}
+
+@mixin box-pack($type: center){
+ -webkit-box-pack: $type;
+ -moz-box-pack: $type;
+ box-pack: $type;
+}
+
+@mixin transform($tr){
+ -webkit-transform: $tr;
+ -moz-transform: $tr;
+ -ms-transform: $tr;
+ -o-transform: $tr;
+ transform: $tr;
+}
+
+@mixin hacel(){
+ @include transform(translate3d(0,0,0));
+}
View
18 app/controllers/application_controller.rb
@@ -1,3 +1,21 @@
class ApplicationController < ActionController::Base
+
protect_from_forgery
+
+ layout nil
+
+ before_filter :intercept_html_requests
+
+ private
+
+ def ensure_authenticated
+ if session[:user_id].blank?
+ render :json => { authorized: false }
+ end
+ end
+
+ def intercept_html_requests
+ render 'layouts/index' if request.format == Mime::HTML
+ end
+
end
View
51 app/controllers/employees_controller.rb
@@ -0,0 +1,51 @@
+class EmployeesController < ApplicationController
+
+ before_filter :ensure_authenticated
+ before_filter :find_employees, :only => [:index]
+ before_filter :find_employee, :except => [:index, :create]
+
+ respond_to :json
+
+
+ # GET /employees
+ def index
+ respond_with @employees
+ end
+
+ # GET /employees/1
+ def show
+ respond_with @employee
+ end
+
+
+ # POST /employees
+ def create
+ @employee = Employee.new(params[:employee])
+ @employee.save
+ respond_with @employee
+ end
+
+ # PUT /employees/1.json
+ def update
+ @employee.update_attributes(params[:employee])
+ respond_with @employee
+ end
+
+ # DELETE /employees/1
+ def destroy
+ @employee.destroy
+ head :ok
+ end
+
+
+ private
+
+ def find_employees
+ @employees = Employee.all
+ end
+
+ def find_employee
+ @employee = Employee.find(params[:id])
+ end
+
+end
View
24 app/controllers/sessions_controller.rb
@@ -0,0 +1,24 @@
+class SessionsController < ApplicationController
+
+ respond_to :json
+
+ # POST /sessions
+ def create
+ user = User.find_by_name(params[:name])
+ if user && user.authenticate(params[:password])
+ session[:user_id] = user.id
+ render :json => { authorized: 'true' }
+ else
+ render :json => { :authorized => 'false' }
+ end
+ end
+
+
+ # DELETE /sessions/1
+ def destroy
+ session[:user_id] = nil
+ head :ok
+ end
+
+
+end
View
2  app/helpers/employees_helper.rb
@@ -0,0 +1,2 @@
+module EmployeesHelper
+end
View
2  app/helpers/sessions_helper.rb
@@ -0,0 +1,2 @@
+module SessionsHelper
+end
View
2  app/models/employee.rb
@@ -0,0 +1,2 @@
+class Employee < ActiveRecord::Base
+end
View
5 app/models/user.rb
@@ -0,0 +1,5 @@
+class User < ActiveRecord::Base
+ attr_accessible :name, :password, :password_confirmation
+ has_secure_password
+ validates_presence_of :password, :on => :create
+end
View
14 app/views/layouts/application.html.erb
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>CafeTownsendSpineRails</title>
- <%= stylesheet_link_tag "application" %>
- <%= javascript_include_tag "application" %>
- <%= csrf_meta_tags %>
-</head>
-<body>
-
-<%= yield %>
-
-</body>
-</html>
View
18 app/views/layouts/index.html.erb
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CafeTownsend - Spine - Rails</title>
+ <%= stylesheet_link_tag "application" %>
+ <%= javascript_include_tag "application" %>
+ <%= csrf_meta_tags %>
+
+ <script type="text/javascript" charset="utf-8">
+ jQuery(function(){
+ new App({el: $("#app")});
+ });
+ </script>
+</head>
+<body>
+ <div id="app"></div>
+</body>
+</html>
View
55 config/routes.rb
@@ -1,58 +1,9 @@
CafeTownsendSpineRails::Application.routes.draw do
- # The priority is based upon order of creation:
- # first created -> highest priority.
- # Sample of regular route:
- # match 'products/:id' => 'catalog#view'
- # Keep in mind you can assign values other than :controller and :action
+ root :to => "sessions#create"
- # Sample of named route:
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
- # This route can be invoked with purchase_url(:id => product.id)
+ resources :sessions
+ resources :employees
- # Sample resource route (maps HTTP verbs to controller actions automatically):
- # resources :products
- # Sample resource route with options:
- # resources :products do
- # member do
- # get 'short'
- # post 'toggle'
- # end
- #
- # collection do
- # get 'sold'
- # end
- # end
-
- # Sample resource route with sub-resources:
- # resources :products do
- # resources :comments, :sales
- # resource :seller
- # end
-
- # Sample resource route with more complex sub-resources
- # resources :products do
- # resources :comments
- # resources :sales do
- # get 'recent', :on => :collection
- # end
- # end
-
- # Sample resource route within a namespace:
- # namespace :admin do
- # # Directs /admin/products/* to Admin::ProductsController
- # # (app/controllers/admin/products_controller.rb)
- # resources :products
- # end
-
- # You can have the root of your site routed with "root"
- # just remember to delete public/index.html.
- # root :to => 'welcome#index'
-
- # See how all your routes lay out with "rake routes"
-
- # This is a legacy wild controller route that's not recommended for RESTful applications.
- # Note: This route will make all actions in every controller accessible via GET requests.
- # match ':controller(/:action(/:id(.:format)))'
end
View
12 db/migrate/20120120101212_create_employees.rb
@@ -0,0 +1,12 @@
+class CreateEmployees < ActiveRecord::Migration
+ def change
+ create_table :employees do |t|
+ t.string :first_name
+ t.string :last_name
+ t.string :email
+ t.date :start_date
+
+ t.timestamps
+ end
+ end
+end
View
10 db/migrate/20120120101448_create_users.rb
@@ -0,0 +1,10 @@
+class CreateUsers < ActiveRecord::Migration
+ def change
+ create_table :users do |t|
+ t.string :name
+ t.string :password_digest
+
+ t.timestamps
+ end
+ end
+end
View
32 db/schema.rb
@@ -0,0 +1,32 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended to check this file into your version control system.
+
+ActiveRecord::Schema.define(:version => 20120120101448) do
+
+ create_table "employees", :force => true do |t|
+ t.string "first_name"
+ t.string "last_name"
+ t.string "email"
+ t.date "start_date"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "users", :force => true do |t|
+ t.string "name"
+ t.string "password_digest"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+end
View
35 db/seeds.rb
@@ -5,3 +5,38 @@
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)
+
+
+
+# user name:string password:string
+User.create!(name: 'Luke', password: 'Skywalker')
+
+
+
+# employee first_name:string last_name:string email:string start_date:date
+Employee.create!([
+ {
+ :first_name => 'Sue',
+ :last_name => 'Hove',
+ :email => 'shove@cafetownsend.com',
+ :start_date => DateTime.new(2006,1,7)
+ },
+ {
+ :first_name => 'Matt',
+ :last_name => 'Boles',
+ :email => 'mboles@cafetownsend.com',
+ :start_date => DateTime.new(2006,2,17)
+ },
+ {
+ :first_name => 'Mike',
+ :last_name => 'Kollen',
+ :email => 'mkollen@cafetownsend.com',
+ :start_date => DateTime.new(2006,3,1)
+ },
+ {
+ :first_name => 'Jennifer',
+ :last_name => 'Jaegel',
+ :email => 'jjaegel@cafetownsend.com',
+ :start_date => DateTime.new(2006,4,1)
+ }
+ ])
View
BIN  public/images/header.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  public/images/invalid.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  public/images/valid.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
241 public/index.html
@@ -1,241 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <title>Ruby on Rails: Welcome aboard</title>
- <style type="text/css" media="screen">
- body {
- margin: 0;
- margin-bottom: 25px;
- padding: 0;
- background-color: #f0f0f0;
- font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
- font-size: 13px;
- color: #333;
- }
-
- h1 {
- font-size: 28px;
- color: #000;
- }
-
- a {color: #03c}
- a:hover {
- background-color: #03c;
- color: white;
- text-decoration: none;
- }
-
-
- #page {
- background-color: #f0f0f0;
- width: 750px;
- margin: 0;
- margin-left: auto;
- margin-right: auto;
- }
-
- #content {
- float: left;
- background-color: white;
- border: 3px solid #aaa;
- border-top: none;
- padding: 25px;
- width: 500px;
- }
-
- #sidebar {
- float: right;
- width: 175px;
- }
-
- #footer {
- clear: both;
- }
-
- #header, #about, #getting-started {
- padding-left: 75px;
- padding-right: 30px;
- }
-
-
- #header {
- background-image: url("/assets/rails.png");
- background-repeat: no-repeat;
- background-position: top left;
- height: 64px;
- }
- #header h1, #header h2 {margin: 0}
- #header h2 {
- color: #888;
- font-weight: normal;
- font-size: 16px;
- }
-
-
- #about h3 {
- margin: 0;
- margin-bottom: 10px;
- font-size: 14px;
- }
-
- #about-content {
- background-color: #ffd;
- border: 1px solid #fc0;
- margin-left: -55px;
- margin-right: -10px;
- }
- #about-content table {
- margin-top: 10px;
- margin-bottom: 10px;
- font-size: 11px;
- border-collapse: collapse;
- }
- #about-content td {
- padding: 10px;
- padding-top: 3px;
- padding-bottom: 3px;
- }
- #about-content td.name {color: #555}
- #about-content td.value {color: #000}
-
- #about-content ul {
- padding: 0;
- list-style-type: none;
- }
-
- #about-content.failure {
- background-color: #fcc;
- border: 1px solid #f00;
- }
- #about-content.failure p {
- margin: 0;
- padding: 10px;
- }
-
-
- #getting-started {
- border-top: 1px solid #ccc;
- margin-top: 25px;
- padding-top: 15px;
- }
- #getting-started h1 {
- margin: 0;
- font-size: 20px;
- }
- #getting-started h2 {
- margin: 0;
- font-size: 14px;
- font-weight: normal;
- color: #333;
- margin-bottom: 25px;
- }
- #getting-started ol {
- margin-left: 0;
- padding-left: 0;
- }
- #getting-started li {
- font-size: 18px;
- color: #888;
- margin-bottom: 25px;
- }
- #getting-started li h2 {
- margin: 0;
- font-weight: normal;
- font-size: 18px;
- color: #333;
- }
- #getting-started li p {
- color: #555;
- font-size: 13px;
- }
-
-
- #sidebar ul {
- margin-left: 0;
- padding-left: 0;
- }
- #sidebar ul h3 {
- margin-top: 25px;
- font-size: 16px;
- padding-bottom: 10px;
- border-bottom: 1px solid #ccc;
- }
- #sidebar li {
- list-style-type: none;
- }
- #sidebar ul.links li {
- margin-bottom: 5px;
- }
-
- .filename {
- font-style: italic;
- }
- </style>
- <script type="text/javascript">
- function about() {
- info = document.getElementById('about-content');
- if (window.XMLHttpRequest)
- { xhr = new XMLHttpRequest(); }
- else
- { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
- xhr.open("GET","rails/info/properties",false);
- xhr.send("");
- info.innerHTML = xhr.responseText;
- info.style.display = 'block'
- }
- </script>
- </head>
- <body>
- <div id="page">
- <div id="sidebar">
- <ul id="sidebar-items">
- <li>
- <h3>Browse the documentation</h3>
- <ul class="links">
- <li><a href="http://guides.rubyonrails.org/">Rails Guides</a></li>
- <li><a href="http://api.rubyonrails.org/">Rails API</a></li>
- <li><a href="http://www.ruby-doc.org/core/">Ruby core</a></li>
- <li><a href="http://www.ruby-doc.org/stdlib/">Ruby standard library</a></li>
- </ul>
- </li>
- </ul>
- </div>
-
- <div id="content">
- <div id="header">
- <h1>Welcome aboard</h1>
- <h2>You&rsquo;re riding Ruby on Rails!</h2>
- </div>
-
- <div id="about">
- <h3><a href="rails/info/properties" onclick="about(); return false">About your application&rsquo;s environment</a></h3>
- <div id="about-content" style="display: none"></div>
- </div>
-
- <div id="getting-started">
- <h1>Getting started</h1>
- <h2>Here&rsquo;s how to get rolling:</h2>
-
- <ol>
- <li>
- <h2>Use <code>rails generate</code> to create your models and controllers</h2>
- <p>To see all available options, run it without parameters.</p>
- </li>
-
- <li>
- <h2>Set up a default route and remove <span class="filename">public/index.html</span></h2>
- <p>Routes are set up in <span class="filename">config/routes.rb</span>.</p>
- </li>
-
- <li>
- <h2>Create your database</h2>
- <p>Run <code>rake db:create</code> to create your database. If you're not using SQLite (the default), edit <span class="filename">config/database.yml</span> with your username and password.</p>
- </li>
- </ol>
- </div>
- </div>
-
- <div id="footer">&nbsp;</div>
- </div>
- </body>
-</html>
View
3  test/test_helper.rb
@@ -10,4 +10,7 @@ class ActiveSupport::TestCase
fixtures :all
# Add more helper methods to be used by all tests here...
+ def loginDefaultUser()
+ post sessions_path, :user => {:name => 'Luke', :password => 'Skywalker'}
+ end
end
View
0  app/models/.gitkeep → vendor/assets/javascripts/.gitkeep
File renamed without changes
1  vendor/assets/javascripts/spine
@@ -0,0 +1 @@
+Subproject commit d50c5a8a4e4b8e7f79c950b5a6bc97bda0934c53
View
BIN  wiki/cafetownsend-spine-rails-edit.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  wiki/cafetownsend-spine-rails-login.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  wiki/cafetownsend-spine-rails-overview.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

No commit comments for this range

Something went wrong with that request. Please try again.