Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mike-burns
Created September 24, 2012 15:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mike-burns/9b4135f4c83c6331d4c0 to your computer and use it in GitHub Desktop.
Save mike-burns/9b4135f4c83c6331d4c0 to your computer and use it in GitHub Desktop.
Diff between suspenders and rails
diff --git a/.gitignore b/.gitignore
index eb3489a..080a3b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,11 @@
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
+public/system
+*.DS_Store
+coverage/*
+*.swp
+rerun.txt
+tags
+!.keep
+vendor/bundler_gems
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..53607ea
--- /dev/null
+++ b/.rspec
@@ -0,0 +1 @@
+--colour
diff --git a/Gemfile b/Gemfile
index 5367a9a..6f003dd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,7 +5,7 @@ gem 'rails', '3.2.8'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
-gem 'sqlite3'
+gem 'pg'
# Gems used only for assets and not required
@@ -21,6 +21,42 @@ group :assets do
end
gem 'jquery-rails'
+gem 'clearance'
+gem 'thin'
+gem 'high_voltage'
+gem 'paperclip'
+gem 'formtastic'
+gem 'flutie'
+gem 'bourbon'
+gem 'airbrake'
+gem 'therubyracer'
+
+group :development do
+ gem 'foreman'
+end
+
+group :development, :test do
+ gem 'guard'
+ gem 'guard-spork'
+ gem 'rspec-rails', '~> 2.9.0'
+ gem 'sham_rack'
+end
+
+group :test do
+ gem 'cucumber-rails', '1.3.0', :require => false
+ gem 'capybara-webkit', '~> 0.11.0'
+ gem 'factory_girl_rails'
+ gem 'bourne'
+ gem 'database_cleaner'
+ gem 'timecop'
+ gem 'shoulda-matchers'
+ gem 'launchy'
+end
+
+group :staging, :production do
+ gem 'newrelic_rpm'
+end
+
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index ef2fa3f..12b5992 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -28,8 +28,32 @@ GEM
activesupport (3.2.8)
i18n (~> 0.6)
multi_json (~> 1.0)
+ addressable (2.3.2)
+ airbrake (3.1.4)
+ builder
+ girl_friday
arel (3.0.2)
+ bourbon (2.1.1)
+ sass (>= 3.1)
+ bourne (1.1.2)
+ mocha (= 0.10.5)
builder (3.0.3)
+ capybara (1.1.2)
+ mime-types (>= 1.16)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ selenium-webdriver (~> 2.0)
+ xpath (~> 0.1.4)
+ capybara-webkit (0.11.0)
+ capybara (>= 1.0.0, < 1.2)
+ json
+ childprocess (0.3.5)
+ ffi (~> 1.0, >= 1.0.6)
+ clearance (0.16.3)
+ diesel (~> 0.1.5)
+ rails (>= 3.0)
+ cocaine (0.3.1)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
@@ -37,9 +61,49 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.3.3)
+ connection_pool (0.9.2)
+ cucumber (1.2.1)
+ builder (>= 2.1.2)
+ diff-lcs (>= 1.1.3)
+ gherkin (~> 2.11.0)
+ json (>= 1.4.6)
+ cucumber-rails (1.3.0)
+ capybara (>= 1.1.2)
+ cucumber (>= 1.1.8)
+ nokogiri (>= 1.5.0)
+ daemons (1.1.9)
+ database_cleaner (0.8.0)
+ diesel (0.1.5)
+ railties
+ diff-lcs (1.1.3)
erubis (2.7.0)
+ eventmachine (1.0.0)
execjs (1.4.0)
multi_json (~> 1.0)
+ factory_girl (4.1.0)
+ activesupport (>= 3.0.0)
+ factory_girl_rails (4.1.0)
+ factory_girl (~> 4.1.0)
+ railties (>= 3.0.0)
+ ffi (1.1.5)
+ flutie (1.3.3)
+ foreman (0.59.0)
+ thor (>= 0.13.6)
+ formtastic (2.2.1)
+ actionpack (>= 3.0)
+ gherkin (2.11.2)
+ json (>= 1.4.6)
+ girl_friday (0.10.0)
+ connection_pool (~> 0.9.0)
+ guard (1.3.3)
+ listen (>= 0.4.2)
+ thor (>= 0.14.6)
+ guard-spork (1.2.0)
+ childprocess
+ guard (>= 1.1)
+ spork (>= 0.8.4)
+ sys-proctable
+ high_voltage (1.2.0)
hike (1.2.1)
i18n (0.6.1)
journey (1.0.4)
@@ -47,12 +111,30 @@ GEM
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
json (1.7.5)
+ launchy (2.1.2)
+ addressable (~> 2.3)
+ libv8 (3.3.10.4)
+ libwebsocket (0.1.5)
+ addressable
+ listen (0.5.2)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
+ metaclass (0.0.1)
mime-types (1.19)
+ mocha (0.10.5)
+ metaclass (~> 0.0.1)
multi_json (1.3.6)
+ newrelic_rpm (3.4.2.1)
+ nokogiri (1.5.5)
+ paperclip (3.2.0)
+ activemodel (>= 3.0.0)
+ activerecord (>= 3.0.0)
+ activesupport (>= 3.0.0)
+ cocaine (>= 0.0.2)
+ mime-types
+ pg (0.14.1)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.2)
@@ -79,18 +161,49 @@ GEM
rake (0.9.2.2)
rdoc (3.12)
json (~> 1.4)
+ rspec (2.9.0)
+ rspec-core (~> 2.9.0)
+ rspec-expectations (~> 2.9.0)
+ rspec-mocks (~> 2.9.0)
+ rspec-core (2.9.0)
+ rspec-expectations (2.9.1)
+ diff-lcs (~> 1.1.3)
+ rspec-mocks (2.9.0)
+ rspec-rails (2.9.0)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec (~> 2.9.0)
+ rubyzip (0.9.9)
sass (3.2.1)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
+ selenium-webdriver (2.25.0)
+ childprocess (>= 0.2.5)
+ libwebsocket (~> 0.1.3)
+ multi_json (~> 1.0)
+ rubyzip
+ sham_rack (1.3.4)
+ rack
+ shoulda-matchers (1.3.0)
+ activesupport (>= 3.0.0)
+ spork (0.9.2)
sprockets (2.1.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
- sqlite3 (1.3.6)
+ sys-proctable (0.9.1)
+ therubyracer (0.10.2)
+ libv8 (~> 3.3.10)
+ thin (1.5.0)
+ daemons (>= 1.0.9)
+ eventmachine (>= 0.12.6)
+ rack (>= 1.0.0)
thor (0.16.0)
tilt (1.3.3)
+ timecop (0.5.2)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
@@ -98,14 +211,39 @@ GEM
uglifier (1.3.0)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
+ xpath (0.1.4)
+ nokogiri (~> 1.3)
PLATFORMS
ruby
DEPENDENCIES
+ airbrake
+ bourbon
+ bourne
+ capybara-webkit (~> 0.11.0)
+ clearance
coffee-rails (~> 3.2.1)
+ cucumber-rails (= 1.3.0)
+ database_cleaner
+ factory_girl_rails
+ flutie
+ foreman
+ formtastic
+ guard
+ guard-spork
+ high_voltage
jquery-rails
+ launchy
+ newrelic_rpm
+ paperclip
+ pg
rails (= 3.2.8)
+ rspec-rails (~> 2.9.0)
sass-rails (~> 3.2.3)
- sqlite3
+ sham_rack
+ shoulda-matchers
+ therubyracer
+ thin
+ timecop
uglifier (>= 1.0.3)
diff --git a/Guardfile b/Guardfile
new file mode 100644
index 0000000..eca0a25
--- /dev/null
+++ b/Guardfile
@@ -0,0 +1,12 @@
+guard 'spork' do
+ watch 'config/application.rb'
+ watch 'config/environment.rb'
+ watch %r{^config/environments/.*\.rb$}
+ watch %r{^config/initializers/.*\.rb$}
+ watch 'config/routes.rb'
+ watch 'Gemfile.lock'
+ watch 'spec/factories.rb'
+ watch 'spec/spec_helper.rb'
+ watch %r{^spec/support/.*\.rb$}
+ watch 'config/locales/.*'
+end
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..b41d8da
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: bundle exec rails server thin -p $PORT
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a3a0d8d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,404 @@
+Style Guide
+===========
+
+A guide for programming in style.
+
+Laptop setup
+------------
+
+Set up your laptop with [this script](https://github.com/thoughtbot/laptop)
+and [these dotfiles](https://github.com/thoughtbot/dotfiles).
+
+Project setup
+-------------
+
+Get the code.
+
+ git clone git@github.com:organization/project.git
+
+Set up the project's dependencies.
+
+ cd project
+ bundle --binstubs
+ rake db:create
+ rake db:schema:load
+ rake db:seed
+
+Add Heroku remotes for staging and production environments.
+
+ git remote add staging git@heroku.com:<app>-staging.git
+ git remote add production git@heroku.com:<app>-production.git
+
+Use [Heroku config](https://github.com/ddollar/heroku-config) to get `ENV`
+variables.
+
+ heroku config:pull --app <app>-staging
+
+Delete extra lines in `.env`, leaving only those needed for app to function
+properly.
+
+ BRAINTREE_MERCHANT_ID
+ BRAINTREE_PRIVATE_KEY
+ BRAINTREE_PUBLIC_KEY
+ S3_KEY
+ S3_SECRET
+
+Use [Foreman](http://goo.gl/oy4uw) to run the app locally.
+
+ foreman start
+
+It uses your `.env` file and `Procfile` to run processes just like Heroku's
+[Cedar](https://devcenter.heroku.com/articles/cedar/) stack.
+
+Development
+-----------
+
+Create a local feature branch based off master.
+
+ git checkout master
+ git pull --rebase
+ git checkout -b feature-xyz
+
+Rebase frequently to incorporate upstream changes.
+
+ git fetch origin
+ git rebase origin/master
+ <resolve conflicts>
+
+When feature is complete and tests pass, commit the changes.
+
+ rake
+ git add -A
+ git status
+ git commit -v
+
+Write a [good commit message](http://goo.gl/w11us).
+
+ Present-tense summary under 50 characters
+
+ * More information about commit (under 72 characters).
+ * More information about commit (under 72 characters).
+
+Share your branch.
+
+ git push origin [branch]
+
+Submit a [Github pull request](http://goo.gl/Kmdee).
+
+Ask for a code review in [Campfire](http://campfirenow.com).
+
+Code review
+-----------
+
+A team member other than the author reviews the pull request.
+
+They make comments and ask questions directly on lines of code in the Github
+web interface or in Campfire.
+
+For changes which they can make themselves, they check out the branch.
+
+ git checkout <branch>
+ rake db:migrate
+ rake
+ git diff staging..HEAD
+
+They make small changes right in the branch, test the feature in browser,
+run tests, commit, and push.
+
+When satisfied, they comment on the pull request `Ready to squash and merge.`
+
+Deploy
+------
+
+If there are multiple commits in the branch, squash them.
+
+ git rebase -i staging/master
+ rake
+
+View a list of new commits. View changed files. Merge branch into staging.
+
+ git checkout staging
+ git fetch staging
+ git reset --hard staging/master
+ git log staging..[branch]
+ git diff --stat [branch]
+ git merge [branch] --ff-only
+
+Deploy to [Heroku](https://devcenter.heroku.com/articles/quickstart).
+
+ git push staging
+
+Run migrations (if necessary).
+
+ heroku run rake db:migrate --app <app>
+
+Restart the dynos if migrations were run.
+
+ heroku restart --app <app>
+
+[Introspect](http://goo.gl/tTgVF) to make sure everything's ok.
+
+ watch heroku ps --app <app>
+
+Test the feature in browser.
+
+Delete your remote feature branch.
+
+ git push origin :[branch]
+
+Delete your local feature branch.
+
+ git branch -d [branch]
+
+Close pull request and comment `Merged.`
+
+Deploy to production.
+
+ git checkout production
+ git fetch production
+ git reset --hard production/master
+ git log production..staging
+ git diff --stat staging/master
+ git merge staging --ff-only
+ git push production
+ heroku run rake db:migrate --app <app>
+ heroku restart --app <app>
+ watch heroku ps --app <app>
+
+Watch logs and metrics dashboards. If the feature is working, merge into master.
+
+ git checkout master
+ git fetch origin
+ git log production..master
+ git merge production --ff-only
+ git push origin master
+
+Use scripts from [thoughtbot/dotfiles](http://github.com/thoughtbot/dotfiles)
+to quickly access the Heroku console, backup the production database, and
+transfer production data to staging.
+
+Formatting
+----------
+
+* Delete trailing whitespace.
+* Don't include spaces after `(`, `[` or before `]`, `)`.
+* Don't vertically align tokens on consecutive lines.
+* Include spaces around infix method invocations like `+` and `-`.
+* Indent continued lines two spaces.
+* Indent private methods equal to public methods.
+* Limit lines to a maximum of 80 characters.
+* Use 2 space indentation (no tabs) unless otherwise noted.
+* Use an empty line between methods, blocks and conditionals.
+* Use spaces around operators, after commas, colons and semicolons, around `{`
+ and before `}`.
+
+Naming
+------
+
+* Avoid abbreviations.
+* Avoid Hungarian notiation (`szName`).
+* Avoid types in names (`user_array`).
+* Name background jobs with a `Job` suffix.
+* Name the enumeration parameter the singular of the collection.
+* Name variables, methods, and classes to reveal intent.
+* Treat acronyms as words in names (`XmlHttpRequest` not `XMLHTTPRequest`),
+ even if the acronym is the entire name (`class Html` not `class HTML`).
+
+Design
+------
+
+* Aggressively remove duplication during development.
+* Avoid comments.
+* Avoid global variables.
+* Avoid long parameter lists.
+* Be consistent.
+* Don't duplicate the functionality of a built-in library.
+* Don't swallow exceptions or "fail silently."
+* Don't write code that guesses at future functionality.
+* [Exceptions should be exceptional](http://rdd.me/yichhgvu).
+* [Keep the code simple](http://rdd.me/ko2aqda2).
+* Limit the number of collaborators of an object.
+* Prefer composition over inheritance.
+* Prefer small methods. One line is best.
+* Prefer small objects with a single, well-defined responsibility.
+* [Tell, don't ask](http://goo.gl/Ztawt).
+
+Javascript
+----------
+
+* Define functions that operate on `window` or DOM in scope of `window`.
+* Initialize arrays using `[]`.
+* Initialize empty objects and hashes using `{}`.
+* Use `CamelCase` for prototypes, `mixedCase` for variables and functions,
+ `SCREAMING_SNAKE_CASE` for constants, `_single_leading_underscore` for
+ private variables and functions.
+* Use `data-` attributes to bind event handlers.
+* Use the [module pattern](http://goo.gl/JDtHN) to control method visibility.
+
+Ruby
+----
+
+* Avoid conditional modifiers (lines that end with conditionals).
+* Avoid hashes as optional parameters. Does the method do too much?
+* Avoid including code and gems in source control that are specific to your
+ development machine or process. Examples: `.rvmrc`, `.swp`
+* Avoid meta-programming.
+* Avoid monkey-patching core classes.
+* Avoid ternary operators (`boolean ? true : false`). Use multi-line `if`
+ instead to emphasize code branches.
+* Define the project's [Ruby version in the
+ Gemfile](http://gembundler.com/man/gemfile.5.html#RUBY-ruby-).
+* Prefer classes to modules when designing functionality that is shared by
+ multiple models.
+* Prefer `detect`, not `find`, and `select`, not `find_all`, to avoid confusion
+ with ActiveRecord and keep `select`/`reject` symmetry.
+* Prefer `map`, not `collect`, and `reduce`, not `inject`, due to symmetry and
+ familarity with mapping and reducing in other technologies.
+* Use `_` for unused block parameters: `hash.map { |_, v| v + 1 }`
+* Use `%{}` for single-line strings needing interpolation and double-quotes.
+* Use `%w()`, not `['', '']`, for an array of words.
+* Use `&&` and `||` for boolean expressions.
+* Use `||=` freely.
+* Use `{...}`, not `do..end`, for single-line blocks.
+* Use `!` suffix for dangerous methods (modifies `self`).
+* Use `?` suffix for predicate methods (return a boolean).
+* Use `CamelCase` for classes and modules, `snake_case` for variables and
+ methods, `SCREAMING_SNAKE_CASE` for constants.
+* Use `def` with parentheses when there are arguments.
+* Use `do..end`, not `{...}`, for multi-line blocks.
+* Use `each`, not `for`, for iteration.
+* Use heredocs for multi-line strings.
+* Use `/(?:first|second)/`, not `/(first|second)/`, when you don't need the
+ captured group.
+* Use `private`, not `protected`, to indicate scope.
+* Use `def self.method`, not `def Class.method` or `class << self`.
+* Use `Set`, not `Array`, for arrays with unique elements. The lookup is faster.
+* Use single-quotes for strings unless interpolating.
+
+Rails
+-----
+
+* Avoid the `:except` option in routes.
+* Avoid `member` and `collection` routes.
+* Avoid Single Table Inheritance.
+* Don't change a migration after it has been committed unless it cannot be
+ solved with another migration.
+* Don't invoke a model's class directly from a view.
+* Don't use SQL or SQL fragments (`where('inviter_id is not null')`) outside of
+ models.
+* Keep the `db/schema.rb` under version control.
+* Limit the number of instance variables shared between controller and view.
+* Name initializers for their gem name. Example: `paperclip.rb`
+* Order controller contents: filters, public methods, private methods.
+* Order model contents: constants, attributes, associations, nested attributes,
+ named scopes, validations, callbacks, public methods, private methods.
+* Prefer [decorators](http://goo.gl/yeF3X), not view helpers.
+* Put all copy text in models, views, controllers, and mailers in
+ `config/locales`.
+* Set `config.assets.initialize_on_precompile = false` in
+ `config/application.rb`.
+* Set default values in the database.
+* Use `_path`, not `_url`, for named routes everywhere except mailer views.
+* Use `def self.method`, not the `named_scope :method` DSL.
+* Use `I18n.t 'dot.separated.key'`, not `I18n.t :key,
+ :scope => [:dot, :separated]`.
+* Use `has_and_belongs_to_many` if all you need is a join table. Do not include
+ an `id` or timestamps.
+* Use namespaced locale lookup in views by prefixing a period: `t '.title'`.
+* Use nested routes to express `belongs_to` relationships between resources.
+* Use SQL, not `ActiveRecord` models, in migrations.
+* Use the default `render 'partial'` syntax over `render partial: 'partial'`.
+* Use the `:only` option to explicitly state exposed routes.
+
+Database
+--------
+
+* Avoid multicolumn indexes in Postgres. It [combines multiple
+ indexes](http://goo.gl/pY3Po) efficiently.
+* Create [indexes concurrently](https://gist.github.com/3186117) to avoid table
+ locks and [reduced performance](http://goo.gl/fi5ER) during deploys.
+* Consider a [partial index](http://goo.gl/YC8Jt) for queries on booleans.
+* Constrain most columns as [`NOT NULL`](http://goo.gl/0GeBr).
+* Create a read-only [Heroku Follower](http://goo.gl/xWDMx) for your
+ production database. If a Heroku database outage occurs, Heroku can use the
+ follower to get your app back up and running faster.
+* Index all foreign keys.
+* Use a Heroku Follower database for analytics to limit reads on the primary
+ database.
+
+Background Jobs
+---------------
+
+* Define a `PRIORITY` constant at the top of the class.
+* Define two public methods: `self.enqueue` and `perform`.
+* Enqueue the job in `self.enqueue` [like this](http://goo.gl/C7e54).
+* Put background jobs in `app/jobs`.
+* Store IDs, not `ActiveRecord` objects for cleaner serialization, then re-find
+ the `ActiveRecord` object in the `perform` method.
+* Subclass the job from `Struct.new(:something_id)`.
+* Use [`Delayed::Job`](http://goo.gl/sRYju) for background jobs.
+
+Email
+-----
+
+* Set `config.action_mailer.raise_delivery_errors = true` in the development
+ environment.
+* Set `config.action_mailer.delivery_method = :test` in the test environment.
+* Use one `ActionMailer` for the app. Name it `Mailer`.
+* Use [SendGrid](http://goo.gl/Kxu9W) or [Amazon SES](http://goo.gl/A5jAA) to
+ deliver email in staging and production environments.
+* Use [single recipient SMTP](http://goo.gl/FWdhG) in staging environment.
+* Use the user's name in the `From` header and email in the `Reply-To` when
+ [delivering email on behalf of the app's users](http://goo.gl/5w1ck).
+
+Gems
+----
+
+* Use [AssetSync](http://goo.gl/m58tF) to serve assets from S3.
+* Use [Bourbon](http://goo.gl/wpyee) for Sass mixins.
+* Use [Bourne](http://goo.gl/lE7zH) for stubs and spies.
+* Use [Braintree](http://goo.gl/mpWTp) for credit card processing.
+* Use [Clearance](http://goo.gl/svPGo) for authentication.
+* Use [Factory Girl](http://goo.gl/AB8bI) to set up test data.
+* Use [Geocoder](http://goo.gl/CKnYF) for geocoding.
+* Use [Haml](http://haml.info) for view templates.
+* Use [Money](http://goo.gl/2CNfc) for money objects.
+* Use [New Relic](http://goo.gl/F7Q56) for performance monitoring.
+* Use [Paperclip](http://goo.gl/eSESD) for file uploads.
+* Use [Thin](http://goo.gl/5Hlr) for serving web requests.
+* Use [WebMock](http://goo.gl/BC1Ac) to disable real HTTP requests.
+
+Testing
+-------
+
+* Avoid `its`, `let`, `let!`, `specify`, `subject`, and other DSLs. Prefer
+ explicitness and consistency.
+* Disable real HTTP requests to external services with
+ `WebMock.disable_net_connect!`.
+* Don't prefix `it` blocks with 'should'.
+* Name outer `describe` blocks after the method under test. Use `.method`
+ for class methods and `#method` for instance methods.
+* Order factories.rb: sequences, traits, factory definitions.
+* Order factory definitions alphabetically by factory name.
+* Order factory attributes: implicit attributes, newline, explicit attributes,
+ child factory definitions. Each section's attributes are alphabetical.
+* Prefix `context` blocks names with 'given' when receiving input. Prefix with
+ 'when' in most other cases.
+* Run specs with `--format documentation`.
+* Test background jobs with a [`Delayed::Job` matcher](http://goo.gl/bzBlN).
+* Use a `context` block for each execution path through the method.
+* Use a [Fake](http://goo.gl/YR7Hh) to stub requests to external services.
+* Use a `before` block to define phases of [Four Phase
+ Test](http://goo.gl/J9FiJ).
+* Use integration tests to execute the entire app.
+* Use non-[SUT](http://goo.gl/r5Ti2) methods in expectations when possible.
+* Use one expectation per `it` block.
+* Use [stubs and spies](http://goo.gl/EciDJ) (not mocks) in isolated tests.
+
+Browsers
+--------
+
+* Don't support clients without Javascript.
+* Don't support IE6.
+
+[Always be learning](http://learn.thoughtbot.com).
diff --git a/README.rdoc b/README.rdoc
deleted file mode 100644
index 7c36f23..0000000
--- a/README.rdoc
+++ /dev/null
@@ -1,261 +0,0 @@
-== Welcome to Rails
-
-Rails is a web-application framework that includes everything needed to create
-database-backed web applications according to the Model-View-Control pattern.
-
-This pattern splits the view (also called the presentation) into "dumb"
-templates that are primarily responsible for inserting pre-built data in between
-HTML tags. The model contains the "smart" domain objects (such as Account,
-Product, Person, Post) that holds all the business logic and knows how to
-persist themselves to a database. The controller handles the incoming requests
-(such as Save New Account, Update Product, Show Post) by manipulating the model
-and directing data to the view.
-
-In Rails, the model is handled by what's called an object-relational mapping
-layer entitled Active Record. This layer allows you to present the data from
-database rows as objects and embellish these data objects with business logic
-methods. You can read more about Active Record in
-link:files/vendor/rails/activerecord/README.html.
-
-The controller and view are handled by the Action Pack, which handles both
-layers by its two parts: Action View and Action Controller. These two layers
-are bundled in a single package due to their heavy interdependence. This is
-unlike the relationship between the Active Record and Action Pack that is much
-more separate. Each of these packages can be used independently outside of
-Rails. You can read more about Action Pack in
-link:files/vendor/rails/actionpack/README.html.
-
-
-== Getting Started
-
-1. At the command prompt, create a new Rails application:
- <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
-
-2. Change directory to <tt>myapp</tt> and start the web server:
- <tt>cd myapp; rails server</tt> (run with --help for options)
-
-3. Go to http://localhost:3000/ and you'll see:
- "Welcome aboard: You're riding Ruby on Rails!"
-
-4. Follow the guidelines to start developing your application. You can find
-the following resources handy:
-
-* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
-* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
-
-
-== Debugging Rails
-
-Sometimes your application goes wrong. Fortunately there are a lot of tools that
-will help you debug it and get it back on the rails.
-
-First area to check is the application log files. Have "tail -f" commands
-running on the server.log and development.log. Rails will automatically display
-debugging and runtime information to these files. Debugging info will also be
-shown in the browser on requests from 127.0.0.1.
-
-You can also log your own messages directly into the log file from your code
-using the Ruby logger class from inside your controllers. Example:
-
- class WeblogController < ActionController::Base
- def destroy
- @weblog = Weblog.find(params[:id])
- @weblog.destroy
- logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
- end
- end
-
-The result will be a message in your log file along the lines of:
-
- Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
-
-More information on how to use the logger is at http://www.ruby-doc.org/core/
-
-Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
-several books available online as well:
-
-* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
-* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
-
-These two books will bring you up to speed on the Ruby language and also on
-programming in general.
-
-
-== Debugger
-
-Debugger support is available through the debugger command when you start your
-Mongrel or WEBrick server with --debugger. This means that you can break out of
-execution at any point in the code, investigate and change the model, and then,
-resume execution! You need to install ruby-debug to run the server in debugging
-mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:
-
- class WeblogController < ActionController::Base
- def index
- @posts = Post.all
- debugger
- end
- end
-
-So the controller will accept the action, run the first line, then present you
-with a IRB prompt in the server window. Here you can do things like:
-
- >> @posts.inspect
- => "[#<Post:0x14a6be8
- @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
- #<Post:0x14a6620
- @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
- >> @posts.first.title = "hello from a debugger"
- => "hello from a debugger"
-
-...and even better, you can examine how your runtime objects actually work:
-
- >> f = @posts.first
- => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
- >> f.
- Display all 152 possibilities? (y or n)
-
-Finally, when you're ready to resume execution, you can enter "cont".
-
-
-== Console
-
-The console is a Ruby shell, which allows you to interact with your
-application's domain model. Here you'll have all parts of the application
-configured, just like it is when the application is running. You can inspect
-domain models, change values, and save to the database. Starting the script
-without arguments will launch it in the development environment.
-
-To start the console, run <tt>rails console</tt> from the application
-directory.
-
-Options:
-
-* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
- made to the database.
-* Passing an environment name as an argument will load the corresponding
- environment. Example: <tt>rails console production</tt>.
-
-To reload your controllers and models after launching the console run
-<tt>reload!</tt>
-
-More information about irb can be found at:
-link:http://www.rubycentral.org/pickaxe/irb.html
-
-
-== dbconsole
-
-You can go to the command line of your database directly through <tt>rails
-dbconsole</tt>. You would be connected to the database with the credentials
-defined in database.yml. Starting the script without arguments will connect you
-to the development database. Passing an argument will connect you to a different
-database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
-PostgreSQL and SQLite 3.
-
-== Description of Contents
-
-The default directory structure of a generated Ruby on Rails application:
-
- |-- app
- | |-- assets
- | |-- images
- | |-- javascripts
- | `-- stylesheets
- | |-- controllers
- | |-- helpers
- | |-- mailers
- | |-- models
- | `-- views
- | `-- layouts
- |-- config
- | |-- environments
- | |-- initializers
- | `-- locales
- |-- db
- |-- doc
- |-- lib
- | `-- tasks
- |-- log
- |-- public
- |-- script
- |-- test
- | |-- fixtures
- | |-- functional
- | |-- integration
- | |-- performance
- | `-- unit
- |-- tmp
- | |-- cache
- | |-- pids
- | |-- sessions
- | `-- sockets
- `-- vendor
- |-- assets
- `-- stylesheets
- `-- plugins
-
-app
- Holds all the code that's specific to this particular application.
-
-app/assets
- Contains subdirectories for images, stylesheets, and JavaScript files.
-
-app/controllers
- Holds controllers that should be named like weblogs_controller.rb for
- automated URL mapping. All controllers should descend from
- ApplicationController which itself descends from ActionController::Base.
-
-app/models
- Holds models that should be named like post.rb. Models descend from
- ActiveRecord::Base by default.
-
-app/views
- Holds the template files for the view that should be named like
- weblogs/index.html.erb for the WeblogsController#index action. All views use
- eRuby syntax by default.
-
-app/views/layouts
- Holds the template files for layouts to be used with views. This models the
- common header/footer method of wrapping views. In your views, define a layout
- using the <tt>layout :default</tt> and create a file named default.html.erb.
- Inside default.html.erb, call <% yield %> to render the view using this
- layout.
-
-app/helpers
- Holds view helpers that should be named like weblogs_helper.rb. These are
- generated for you automatically when using generators for controllers.
- Helpers can be used to wrap functionality for your views into methods.
-
-config
- Configuration files for the Rails environment, the routing map, the database,
- and other dependencies.
-
-db
- Contains the database schema in schema.rb. db/migrate contains all the
- sequence of Migrations for your schema.
-
-doc
- This directory is where your application documentation will be stored when
- generated using <tt>rake doc:app</tt>
-
-lib
- Application specific libraries. Basically, any kind of custom code that
- doesn't belong under controllers, models, or helpers. This directory is in
- the load path.
-
-public
- The directory available for the web server. Also contains the dispatchers and the
- default HTML files. This should be set as the DOCUMENT_ROOT of your web
- server.
-
-script
- Helper scripts for automation and generation.
-
-test
- Unit and functional tests along with fixtures. When using the rails generate
- command, template test files will be generated for you and placed in this
- directory.
-
-vendor
- External libraries that the application depends on. Also includes the plugins
- subdirectory. If the app has frozen rails, those gems also go here, under
- vendor/rails/. This directory is in the load path.
diff --git a/Rakefile b/Rakefile
index b2d78e7..4c794f4 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,3 +5,5 @@
require File.expand_path('../config/application', __FILE__)
DemoApp::Application.load_tasks
+task(:default).clear
+task :default => [:spec, :cucumber]
\ No newline at end of file
diff --git a/app/assets/images/.gitkeep b/app/assets/images/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/app/assets/images/rails.png b/app/assets/images/rails.png
deleted file mode 100644
index d5edc04..0000000
Binary files a/app/assets/images/rails.png and /dev/null differ
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 9097d83..1dc449f 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -12,4 +12,5 @@
//
//= require jquery
//= require jquery_ujs
+//= require jquery-ui
//= require_tree .
diff --git a/app/assets/javascripts/prefilled_input.js b/app/assets/javascripts/prefilled_input.js
new file mode 100644
index 0000000..e1153cf
--- /dev/null
+++ b/app/assets/javascripts/prefilled_input.js
@@ -0,0 +1,59 @@
+// clear inputs with starter values
+new function($) {
+ $.fn.prefilledInput = function() {
+
+ var focus = function () {
+ $(this).removeClass('prefilled');
+ if (this.value == this.prefilledValue) {
+ this.value = '';
+ }
+ };
+
+ var blur = function () {
+ if (this.value == '') {
+ $(this).addClass('prefilled').val(this.prefilledValue);
+ } else if (this.value != this.prefilledValue) {
+ $(this).removeClass('prefilled');
+ }
+ };
+
+ var extractPrefilledValue = function () {
+ if (this.title) {
+ this.prefilledValue = this.title;
+ this.title = '';
+ } else if (this.id) {
+ this.prefilledValue = $('label[for=' + this.id + ']').hide().text();
+ }
+ if (this.prefilledValue) {
+ this.prefilledValue = this.prefilledValue.replace(/\*$/, '');
+ }
+ };
+
+ var initialize = function (index) {
+ if (!this.prefilledValue) {
+ this.extractPrefilledValue = extractPrefilledValue;
+ this.extractPrefilledValue();
+ $(this).trigger('blur');
+ }
+ };
+
+ return this.filter(":input").
+ focus(focus).
+ blur(blur).
+ each(initialize);
+ };
+
+ var clearPrefilledInputs = function () {
+ var form = this.form || this;
+ $(form).find("input.prefilled, textarea.prefilled").val("");
+ };
+
+ var prefilledSetup = function () {
+ $('input.prefilled, textarea.prefilled').prefilledInput();
+ $('form').submit(clearPrefilledInputs);
+ $('input:submit, button:submit').click(clearPrefilledInputs);
+ };
+
+ $(document).ready(prefilledSetup);
+ $(document).ajaxComplete(prefilledSetup);
+}(jQuery);
diff --git a/app/assets/stylesheets/_screen.scss b/app/assets/stylesheets/_screen.scss
new file mode 100644
index 0000000..e69de29
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
deleted file mode 100644
index 3192ec8..0000000
--- a/app/assets/stylesheets/application.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This is a manifest file that'll be compiled into application.css, which will include all the files
- * listed below.
- *
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
- * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
- *
- * You're free to add application-wide styles to this file and they'll appear at the top of the
- * compiled file, but it's generally better to create a new file per style scope.
- *
- *= require_self
- *= require_tree .
- */
diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss
new file mode 100644
index 0000000..9b644a9
--- /dev/null
+++ b/app/assets/stylesheets/application.css.scss
@@ -0,0 +1,17 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+ */
+
+
+@import 'flutie';
+@import 'bourbon';
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index e8065d9..f8a344b 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,3 +1,4 @@
class ApplicationController < ActionController::Base
+ include Clearance::Authentication
protect_from_forgery
end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 0000000..e7bd019
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,4 @@
+class User < ActiveRecord::Base
+ include Clearance::User
+ attr_accessible :email, :password
+end
diff --git a/app/validators/email_validator.rb b/app/validators/email_validator.rb
new file mode 100644
index 0000000..676a654
--- /dev/null
+++ b/app/validators/email_validator.rb
@@ -0,0 +1,7 @@
+class EmailValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
+ record.errors[attribute] << (options[:message] || "is not an email")
+ end
+ end
+end
diff --git a/app/views/application/_flashes.html.erb b/app/views/application/_flashes.html.erb
new file mode 100644
index 0000000..ae7ff75
--- /dev/null
+++ b/app/views/application/_flashes.html.erb
@@ -0,0 +1,5 @@
+<div id="flash">
+ <% flash.each do |key, value| -%>
+ <div id="flash_<%= key %>"><%= value %></div>
+ <% end -%>
+</div>
diff --git a/app/views/application/_javascript.html.erb b/app/views/application/_javascript.html.erb
new file mode 100644
index 0000000..a5fa70a
--- /dev/null
+++ b/app/views/application/_javascript.html.erb
@@ -0,0 +1,9 @@
+<%= javascript_include_tag :application %>
+
+<%= yield :javascript %>
+
+<% if Rails.env.test? %>
+ <%= javascript_tag do %>
+ $.ajaxSetup({ async: false });
+ <% end %>
+<% end %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index c15e160..994c7b6 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,14 +1,22 @@
<!DOCTYPE html>
<html>
<head>
- <title>DemoApp</title>
- <%= stylesheet_link_tag "application", :media => "all" %>
- <%= javascript_include_tag "application" %>
+ <meta charset="utf-8" />
+ <meta name="ROBOTS" content="NOODP" />
+ <title><%= page_title %></title>
+ <%= stylesheet_link_tag :application, :media => 'all' %>
<%= csrf_meta_tags %>
</head>
-<body>
-
-<%= yield %>
-
+<body class="<%= body_class %>">
+ <header>
+ <% if signed_in? -%>
+ <%= link_to "Sign out", sign_out_path, :method => :delete %>
+ <% else -%>
+ <%= link_to "Sign in", sign_in_path %>
+ <% end -%>
+ </header>
+ <%= render 'flashes' -%>
+ <%= yield %>
+ <%= render 'javascript' %>
</body>
</html>
diff --git a/app/views/pages/.gitkeep b/app/views/pages/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/config/application.rb b/config/application.rb
index 5f91dbc..37cb118 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,6 +1,12 @@
require File.expand_path('../boot', __FILE__)
-require 'rails/all'
+# Pick the frameworks you want:
+require "active_record/railtie"
+require "action_controller/railtie"
+require "action_mailer/railtie"
+require "active_resource/railtie"
+require "sprockets/railtie"
+# require "rails/test_unit/railtie"
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
@@ -11,6 +17,14 @@ end
module DemoApp
class Application < Rails::Application
+ config.active_record.default_timezone = :utc
+ config.generators do |generate|
+ generate.test_framework :rspec
+ generate.helper false
+ generate.stylesheets false
+ generate.javascript_engine false
+ generate.view_specs false
+ end
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
@@ -55,6 +69,7 @@ module DemoApp
# Enable the asset pipeline
config.assets.enabled = true
+ config.assets.initialize_on_precompile = false
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
diff --git a/config/cucumber.yml b/config/cucumber.yml
new file mode 100644
index 0000000..0941e46
--- /dev/null
+++ b/config/cucumber.yml
@@ -0,0 +1,8 @@
+<%
+rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
+rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
+std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
+%>
+default: <%= std_opts %> features -drb -r features
+wip: --tags @wip:3 --wip features
+rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
diff --git a/config/database.yml b/config/database.yml
index 51a4dd4..7714782 100644
--- a/config/database.yml
+++ b/config/database.yml
@@ -1,25 +1,13 @@
-# SQLite version 3.x
-# gem install sqlite3
-#
-# Ensure the SQLite 3 gem is defined in your Gemfile
-# gem 'sqlite3'
-development:
- adapter: sqlite3
- database: db/development.sqlite3
+development: &default
+ adapter: postgresql
+ database: demo-app_development
pool: 5
timeout: 5000
-# Warning: The database defined as "test" will be erased and
-# re-generated from your development database when you run "rake".
-# Do not set this db to the same as development or production.
-test:
- adapter: sqlite3
- database: db/test.sqlite3
- pool: 5
- timeout: 5000
+test: &test
+ <<: *default
+ database: demo-app_test
+ min_messages: warning
-production:
- adapter: sqlite3
- database: db/production.sqlite3
- pool: 5
- timeout: 5000
+cucumber:
+ <<: *test
\ No newline at end of file
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 33676f2..0d87aec 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -14,7 +14,7 @@ DemoApp::Application.configure do
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
- config.action_mailer.raise_delivery_errors = false
+ config.action_mailer.raise_delivery_errors = true
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
@@ -34,4 +34,6 @@ DemoApp::Application.configure do
# Expands the lines which load the assets
config.assets.debug = true
+
+ config.action_mailer.default_url_options = { :host => 'demo-app.local' }
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index badcf19..5fc7f40 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -64,4 +64,6 @@ DemoApp::Application.configure do
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+ config.action_mailer.default_url_options = { :host => 'demo-app.com' }
end
diff --git a/config/environments/staging.rb b/config/environments/staging.rb
new file mode 100644
index 0000000..24fd369
--- /dev/null
+++ b/config/environments/staging.rb
@@ -0,0 +1,69 @@
+DemoApp::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # Code is not reloaded between requests
+ config.cache_classes = true
+
+ # Full error reports are disabled and caching is turned on
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Disable Rails's static asset server (Apache or nginx will already do this)
+ config.serve_static_assets = false
+
+ # Compress JavaScripts and CSS
+ config.assets.compress = true
+
+ # Don't fallback to assets pipeline if a precompiled asset is missed
+ config.assets.compile = false
+
+ # Generate digests for assets URLs
+ config.assets.digest = true
+
+ # Defaults to nil and saved in location specified by config.assets.prefix
+ # config.assets.manifest = YOUR_PATH
+
+ # Specifies the header that your server uses for sending files
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # See everything in the log (default is :info)
+ # config.log_level = :debug
+
+ # Prepend all log lines with the following tags
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server
+ # config.action_controller.asset_host = "http://assets.example.com"
+
+ # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
+ # config.assets.precompile += %w( search.js )
+
+ # Disable delivery errors, bad email addresses will be ignored
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable threaded mode
+ # config.threadsafe!
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation can not be found)
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners
+ config.active_support.deprecation = :notify
+
+ # Log the query plan for queries taking more than this (works
+ # with SQLite, MySQL, and PostgreSQL)
+ # config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+ config.action_mailer.default_url_options = { :host => 'staging.demo-app.com' }
+end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 9b2cd20..a1ac931 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -34,4 +34,6 @@ DemoApp::Application.configure do
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
+
+ config.action_mailer.default_url_options = { :host => 'example.com' }
end
diff --git a/config/initializers/clearance.rb b/config/initializers/clearance.rb
new file mode 100644
index 0000000..f0490ce
--- /dev/null
+++ b/config/initializers/clearance.rb
@@ -0,0 +1,3 @@
+Clearance.configure do |config|
+ config.mailer_sender = 'reply@example.com'
+end
diff --git a/config/initializers/errors.rb b/config/initializers/errors.rb
new file mode 100644
index 0000000..7b28e97
--- /dev/null
+++ b/config/initializers/errors.rb
@@ -0,0 +1,28 @@
+require 'net/http'
+require 'net/smtp'
+
+# Example:
+# begin
+# some http call
+# rescue *HTTP_ERRORS => error
+# notify_hoptoad error
+# end
+
+HTTP_ERRORS = [Timeout::Error,
+ Errno::EINVAL,
+ Errno::ECONNRESET,
+ EOFError,
+ Net::HTTPBadResponse,
+ Net::HTTPHeaderSyntaxError,
+ Net::ProtocolError]
+
+SMTP_SERVER_ERRORS = [TimeoutError,
+ IOError,
+ Net::SMTPUnknownError,
+ Net::SMTPServerBusy,
+ Net::SMTPAuthenticationError]
+
+SMTP_CLIENT_ERRORS = [Net::SMTPFatalError,
+ Net::SMTPSyntaxError]
+
+SMTP_ERRORS = SMTP_SERVER_ERRORS + SMTP_CLIENT_ERRORS
diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb
index e73baed..0853f0c 100644
--- a/config/initializers/secret_token.rb
+++ b/config/initializers/secret_token.rb
@@ -4,4 +4,4 @@
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
-DemoApp::Application.config.secret_token = 'f0f5527c8e636cab11af3ee3a3b63b7e171c36f042f88d96a2a8e8e7397065705d4e6f1b40e4aa6b0e1e875a964261fcd2ecfc94eda8c719322a30a26f9dd7ef'
+DemoApp::Application.config.secret_token = 'c56d2c8ee7590e6bdf813c4a1c0c9b4a3c2babf88f63c45c25848a4445def2c5149e32f5739e13c844a6e93186fd2ceb4321248746116106f1fb6e5becc7eb90'
diff --git a/config/initializers/time_formats.rb b/config/initializers/time_formats.rb
new file mode 100644
index 0000000..a57a761
--- /dev/null
+++ b/config/initializers/time_formats.rb
@@ -0,0 +1,6 @@
+# {
+# :short_date => "%x", # 04/13/10
+# :long_date => "%a, %b %d, %Y" # Tue, Apr 13, 2010
+# }.each do |format_name, format_string|
+# Time::DATE_FORMATS[format_name] = format_string
+# end
diff --git a/config/routes.rb b/config/routes.rb
index da61cfc..ba9c1c7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,58 +1,4 @@
DemoApp::Application.routes.draw do
- # The priority is based upon order of creation:
- # first created -> highest priority.
+ root :to => 'Clearance::Sessions#new'
- # Sample of regular route:
- # match 'products/:id' => 'catalog#view'
- # Keep in mind you can assign values other than :controller and :action
-
- # Sample of named route:
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
- # This route can be invoked with purchase_url(:id => product.id)
-
- # 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
diff --git a/db/migrate/.gitkeep b/db/migrate/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/db/migrate/20120924145640_create_diesel_clearance_users.rb b/db/migrate/20120924145640_create_diesel_clearance_users.rb
new file mode 100644
index 0000000..4e44358
--- /dev/null
+++ b/db/migrate/20120924145640_create_diesel_clearance_users.rb
@@ -0,0 +1,19 @@
+class CreateDieselClearanceUsers < ActiveRecord::Migration
+ def self.up
+ create_table(:users) do |t|
+ t.string :email
+ t.string :encrypted_password, :limit => 128
+ t.string :salt, :limit => 128
+ t.string :confirmation_token, :limit => 128
+ t.string :remember_token, :limit => 128
+ t.timestamps
+ end
+
+ add_index :users, :email
+ add_index :users, :remember_token
+ end
+
+ def self.down
+ drop_table :users
+ end
+end
diff --git a/features/clearance/visitor_resets_password.feature b/features/clearance/visitor_resets_password.feature
new file mode 100644
index 0000000..bd56869
--- /dev/null
+++ b/features/clearance/visitor_resets_password.feature
@@ -0,0 +1,41 @@
+Feature: Password reset
+
+ In order to sign in even if I forgot my password
+ As a user
+ I want to reset my password
+
+ Scenario: User is not signed up
+ When I reset the password for "unknown.email@example.com"
+ Then I am told email is unknown
+
+ Scenario: User is signed up and requests password reset
+ Given I signed up with "email@example.com"
+ When I reset the password for "email@example.com"
+ Then instructions for changing my password are emailed to "email@example.com"
+
+ Scenario: User tries to reset his password with a blank password
+ Given I signed up with "email@example.com"
+ When I reset the password for "email@example.com"
+ And I follow the password reset link sent to "email@example.com"
+ And I update my password with ""
+ Then I am told to enter a password
+ And I should be signed out
+
+ Scenario: User is signed up and updates his password
+ Given I signed up with "email@example.com"
+ When I reset the password for "email@example.com"
+ And I follow the password reset link sent to "email@example.com"
+ And I update my password with "newpassword"
+ Then I should be signed in
+ When I sign out
+ Then I should be signed out
+ When I sign in with "email@example.com" and "newpassword"
+ Then I should be signed in
+
+ Scenario: User who was created before Clearance was installed creates password for first time
+ Given a user "email@example.com" exists without a salt, remember token, or password
+ When I reset the password for "email@example.com"
+ When I follow the password reset link sent to "email@example.com"
+ And I update my password with "newpassword"
+ Then I should be signed in
+
diff --git a/features/clearance/visitor_signs_in.feature b/features/clearance/visitor_signs_in.feature
new file mode 100644
index 0000000..86542c8
--- /dev/null
+++ b/features/clearance/visitor_signs_in.feature
@@ -0,0 +1,26 @@
+Feature: Sign in
+
+ In order to get access to protected sections of the site
+ As a visitor
+ I want to sign in
+
+ Scenario: Visitor is not signed up
+ When I sign in as "unknown.email@example.com"
+ Then I am told email or password is bad
+ And I should be signed out
+
+ Scenario: Visitor enters wrong password
+ Given I am signed up as "email@example.com"
+ When I sign in as "email@example.com" and "badpassword"
+ Then I am told email or password is bad
+ And I should be signed out
+
+ Scenario: Visitor signs in successfully
+ Given I am signed up as "email@example.com"
+ When I sign in as "email@example.com"
+ Then I should be signed in
+
+ Scenario: Visitor signs in successfully with uppercase email
+ Given I am signed up as "email@example.com"
+ When I sign in as "Email@example.com"
+ Then I should be signed in
diff --git a/features/clearance/visitor_signs_out.feature b/features/clearance/visitor_signs_out.feature
new file mode 100644
index 0000000..7bb5a36
--- /dev/null
+++ b/features/clearance/visitor_signs_out.feature
@@ -0,0 +1,12 @@
+Feature: Sign out
+
+ In order to protect my account from unauthorized access
+ As a signed in user
+ I want to sign out
+
+ Scenario: User signs out
+ Given I am signed up as "email@example.com"
+ When I sign in as "email@example.com"
+ Then I should be signed in
+ When I sign out
+ Then I should be signed out
diff --git a/features/clearance/visitor_signs_up.feature b/features/clearance/visitor_signs_up.feature
new file mode 100644
index 0000000..19787e8
--- /dev/null
+++ b/features/clearance/visitor_signs_up.feature
@@ -0,0 +1,17 @@
+Feature: Sign up
+
+ In order to access protected sections of the site
+ As a visitor
+ I want to sign up
+
+ Scenario: Visitor signs up with invalid email
+ When I sign up with "invalidemail" and "password"
+ Then I am told to enter a valid email address
+
+ Scenario: Visitor signs up with blank password
+ When I sign up with "email@example.com" and ""
+ Then I am told to enter a password
+
+ Scenario: Visitor signs up with valid data
+ When I sign up with "email@example.com" and "password"
+ Then I should be signed in
diff --git a/features/step_definitions/clearance/clearance_steps.rb b/features/step_definitions/clearance/clearance_steps.rb
new file mode 100644
index 0000000..6f5d874
--- /dev/null
+++ b/features/step_definitions/clearance/clearance_steps.rb
@@ -0,0 +1,124 @@
+# Existing users
+
+require 'factory_girl_rails'
+
+Given /^(?:I am|I have|I) signed up (?:as|with) "(.*)"$/ do |email|
+ FactoryGirl.create(:user, :email => email)
+end
+
+Given /^a user "([^"]*)" exists without a salt, remember token, or password$/ do |email|
+ user = FactoryGirl.create(:user, :email => email)
+ sql = "update users set salt = NULL, encrypted_password = NULL, remember_token = NULL where id = #{user.id}"
+ ActiveRecord::Base.connection.update(sql)
+end
+
+# Sign up
+
+When /^I sign up (?:with|as) "(.*)" and "(.*)"$/ do |email, password|
+ visit sign_up_path
+ page.should have_css("input[type='email']")
+
+ fill_in "Email", :with => email
+ fill_in "Password", :with => password
+ click_button "Sign up"
+end
+
+# Sign in
+
+Given /^I sign in$/ do
+ email = FactoryGirl.generate(:email)
+ steps %{
+ I have signed up with "#{email}"
+ I sign in with "#{email}"
+ }
+end
+
+When /^I sign in (?:with|as) "([^"]*)"$/ do |email|
+ step %{I sign in with "#{email}" and "password"}
+end
+
+When /^I sign in (?:with|as) "([^"]*)" and "([^"]*)"$/ do |email, password|
+ visit sign_in_path
+ page.should have_css("input[type='email']")
+
+ fill_in "Email", :with => email
+ fill_in "Password", :with => password
+ click_button "Sign in"
+end
+
+# Sign out
+
+When "I sign out" do
+ visit "/"
+ click_link "Sign out"
+end
+
+# Reset password
+
+When /^I reset the password for "(.*)"$/ do |email|
+ visit new_password_path
+ page.should have_css("input[type='email']")
+
+ fill_in "Email address", :with => email
+ click_button "Reset password"
+end
+
+Then /^instructions for changing my password are emailed to "(.*)"$/ do |email|
+ page.should have_content("instructions for changing your password")
+
+ user = User.find_by_email!(email)
+ assert !user.confirmation_token.blank?
+ assert !ActionMailer::Base.deliveries.empty?
+ result = ActionMailer::Base.deliveries.any? do |email|
+ email.to == [user.email] &&
+ email.subject =~ /password/i &&
+ email.body =~ /#{user.confirmation_token}/
+ end
+ assert result
+end
+
+When /^I follow the password reset link sent to "(.*)"$/ do |email|
+ user = User.find_by_email!(email)
+ visit edit_user_password_path(:user_id => user,
+ :token => user.confirmation_token)
+end
+
+When /^I change the password of "(.*)" without token$/ do |email|
+ user = User.find_by_email!(email)
+ visit edit_user_password_path(:user_id => user)
+end
+
+When /^I update my password with "(.*)"$/ do |password|
+ fill_in "Choose password", :with => password
+ click_button "Save this password"
+end
+
+# Flashes
+
+Then /^I am told email or password is bad$/ do
+ page.should have_content("Bad email or password")
+end
+
+Then /^I am told email is unknown$/ do
+ page.should have_content("Unknown email")
+end
+
+Then /^I am told to enter a valid email address$/ do
+ page.should have_content("Must be a valid email address")
+end
+
+Then /^I am told to enter a password$/ do
+ page.should have_content("Password can't be blank")
+end
+
+# Verification
+
+Then /^I should be signed in$/ do
+ visit "/"
+ page.should have_content "Sign out"
+end
+
+Then /^I should be signed out$/ do
+ visit "/"
+ page.should have_content "Sign in"
+end
diff --git a/features/support/env.rb b/features/support/env.rb
new file mode 100644
index 0000000..3185d35
--- /dev/null
+++ b/features/support/env.rb
@@ -0,0 +1,17 @@
+require 'spork'
+
+Spork.prefork do
+ ENV['RAILS_ENV'] ||= 'test'
+ require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
+ require 'cucumber/rails'
+
+ Capybara.default_selector = :css
+ Capybara.javascript_driver = :webkit
+ DatabaseCleaner.strategy = :truncation
+end
+
+Spork.each_run do
+ After do
+ DatabaseCleaner.clean
+ end
+end
diff --git a/lib/tasks/cucumber.rake b/lib/tasks/cucumber.rake
new file mode 100644
index 0000000..83f7947
--- /dev/null
+++ b/lib/tasks/cucumber.rake
@@ -0,0 +1,65 @@
+# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
+# It is recommended to regenerate this file in the future when you upgrade to a
+# newer version of cucumber-rails. Consider adding your own code to a new file
+# instead of editing this one. Cucumber will automatically load all features/**/*.rb
+# files.
+
+
+unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
+
+vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
+$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
+
+begin
+ require 'cucumber/rake/task'
+
+ namespace :cucumber do
+ Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
+ t.fork = true # You may get faster startup if you set this to false
+ t.profile = 'default'
+ end
+
+ Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
+ t.binary = vendored_cucumber_bin
+ t.fork = true # You may get faster startup if you set this to false
+ t.profile = 'wip'
+ end
+
+ Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
+ t.binary = vendored_cucumber_bin
+ t.fork = true # You may get faster startup if you set this to false
+ t.profile = 'rerun'
+ end
+
+ desc 'Run all features'
+ task :all => [:ok, :wip]
+
+ task :statsetup do
+ require 'rails/code_statistics'
+ ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
+ ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
+ end
+ end
+ desc 'Alias for cucumber:ok'
+ task :cucumber => 'cucumber:ok'
+
+ task :default => :cucumber
+
+ task :features => :cucumber do
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
+ end
+
+ # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
+ task 'db:test:prepare' do
+ end
+
+ task :stats => 'cucumber:statsetup'
+rescue LoadError
+ desc 'cucumber rake task not available (cucumber not installed)'
+ task :cucumber do
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
+ end
+end
+
+end
diff --git a/public/404.html b/public/404.html
index 9a48320..a93f7ac 100644
--- a/public/404.html
+++ b/public/404.html
@@ -1,24 +1,14 @@
<!DOCTYPE html>
<html>
<head>
+ <meta charset='utf-8' />
+ <meta name='ROBOTS' content='NOODP' />
<title>The page you were looking for doesn't exist (404)</title>
- <style type="text/css">
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
- </style>
+ <link href='/assets/application.css' media='all' rel='stylesheet' type='text/css' />
</head>
<body>
- <!-- This file lives in public/404.html -->
- <div class="dialog">
+ <div class="dialog">
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
diff --git a/public/422.html b/public/422.html
index 83660ab..7299e45 100644
--- a/public/422.html
+++ b/public/422.html
@@ -1,24 +1,14 @@
<!DOCTYPE html>
<html>
<head>
+ <meta charset='utf-8' />
+ <meta name='ROBOTS' content='NOODP' />
<title>The change you wanted was rejected (422)</title>
- <style type="text/css">
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
- </style>
+ <link href='/assets/application.css' media='all' rel='stylesheet' type='text/css' />
</head>
<body>
- <!-- This file lives in public/422.html -->
- <div class="dialog">
+ <div class="dialog">
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
diff --git a/public/500.html b/public/500.html
index f3648a0..090f5f3 100644
--- a/public/500.html
+++ b/public/500.html
@@ -1,24 +1,14 @@
<!DOCTYPE html>
<html>
<head>
+ <meta charset='utf-8' />
+ <meta name='ROBOTS' content='NOODP' />
<title>We're sorry, but something went wrong (500)</title>
- <style type="text/css">
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
- </style>
+ <link href='/assets/application.css' media='all' rel='stylesheet' type='text/css' />
</head>
<body>
- <!-- This file lives in public/500.html -->
- <div class="dialog">
+ <div class="dialog">
<h1>We're sorry, but something went wrong.</h1>
</div>
</body>
diff --git a/public/index.html b/public/index.html
deleted file mode 100644
index a1d5099..0000000
--- a/public/index.html
+++ /dev/null
@@ -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>
diff --git a/script/cucumber b/script/cucumber
new file mode 100755
index 0000000..7fa5c92
--- /dev/null
+++ b/script/cucumber
@@ -0,0 +1,10 @@
+#!/usr/bin/env ruby
+
+vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
+if vendored_cucumber_bin
+ load File.expand_path(vendored_cucumber_bin)
+else
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
+ require 'cucumber'
+ load Cucumber::BINARY
+end
diff --git a/spec/controllers/.gitkeep b/spec/controllers/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/factories/clearance.rb b/spec/factories/clearance.rb
new file mode 100644
index 0000000..36144a3
--- /dev/null
+++ b/spec/factories/clearance.rb
@@ -0,0 +1,12 @@
+FactoryGirl.define do
+
+ sequence :email do |n|
+ "user#{n}@example.com"
+ end
+
+ factory :user do
+ email
+ password "password"
+ end
+
+end
diff --git a/spec/helpers/.gitkeep b/spec/helpers/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/lib/.gitkeep b/spec/lib/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/models/.gitkeep b/spec/models/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..bfd7ae0
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,32 @@
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+ENV["RAILS_ENV"] ||= 'test'
+require File.expand_path("../../config/environment", __FILE__)
+require 'rspec/rails'
+require 'rspec/autorun'
+
+# Requires supporting ruby files with custom matchers and macros, etc,
+# in spec/support/ and its subdirectories.
+Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
+
+RSpec.configure do |config|
+ # ## Mock Framework
+ #
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
+ #
+ config.mock_with :mocha
+ # config.mock_with :flexmock
+ # config.mock_with :rr
+
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, remove the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+
+ # If true, the base class of anonymous controllers will be inferred
+ # automatically. This will be the default behavior in future versions of
+ # rspec-rails.
+ config.infer_base_class_for_anonymous_controllers = false
+end
diff --git a/spec/support/.gitkeep b/spec/support/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/clearance.rb b/spec/support/clearance.rb
new file mode 100644
index 0000000..2eda1ea
--- /dev/null
+++ b/spec/support/clearance.rb
@@ -0,0 +1 @@
+require 'clearance/testing'
\ No newline at end of file
diff --git a/spec/support/factory_girl.rb b/spec/support/factory_girl.rb
new file mode 100644
index 0000000..eec437f
--- /dev/null
+++ b/spec/support/factory_girl.rb
@@ -0,0 +1,3 @@
+RSpec.configure do |config|
+ config.include FactoryGirl::Syntax::Methods
+end
diff --git a/spec/support/matchers/.gitkeep b/spec/support/matchers/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/mixins/.gitkeep b/spec/support/mixins/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/shared_examples/.gitkeep b/spec/support/shared_examples/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/views/.gitkeep b/spec/views/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/.gitkeep b/test/fixtures/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/.gitkeep b/test/functional/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/test/integration/.gitkeep b/test/integration/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/test/performance/browsing_test.rb b/test/performance/browsing_test.rb
deleted file mode 100644
index 3fea27b..0000000
--- a/test/performance/browsing_test.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'test_helper'
-require 'rails/performance_test_help'
-
-class BrowsingTest < ActionDispatch::PerformanceTest
- # Refer to the documentation for all available options
- # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory]
- # :output => 'tmp/performance', :formats => [:flat] }
-
- def test_homepage
- get '/'
- end
-end
diff --git a/test/test_helper.rb b/test/test_helper.rb
deleted file mode 100644
index 8bf1192..0000000
--- a/test/test_helper.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-ENV["RAILS_ENV"] = "test"
-require File.expand_path('../../config/environment', __FILE__)
-require 'rails/test_help'
-
-class ActiveSupport::TestCase
- # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
- #
- # Note: You'll currently still have to declare fixtures explicitly in integration tests
- # -- they do not yet inherit this setting
- fixtures :all
-
- # Add more helper methods to be used by all tests here...
-end
diff --git a/test/unit/.gitkeep b/test/unit/.gitkeep
deleted file mode 100644
index e69de29..0000000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment