├── log
└── .gitkeep
├── lib
├── tasks
│ └── .gitkeep
├── assets
│ └── .gitkeep
├── maintenance.rb
└── shorten.rb
├── public
├── favicon.ico
├── robots.txt
├── 422.html
├── 404.html
└── 500.html
├── app
├── mailers
│ ├── .gitkeep
│ ├── user_mailer.rb
│ └── delivery_mailer.rb
├── models
│ ├── .gitkeep
│ ├── comment.rb
│ ├── sighting.rb
│ ├── journal.rb
│ ├── schedule.rb
│ ├── fee.rb
│ ├── location.rb
│ ├── package.rb
│ ├── user.rb
│ └── delivery.rb
├── assets
│ ├── javascripts
│ │ ├── util.js
│ │ ├── schedule_add.js
│ │ ├── application.js
│ │ ├── delivery_edit.js
│ │ └── gmaps.js.erb
│ ├── images
│ │ ├── logo.png
│ │ ├── wheel.png
│ │ ├── favicon.png
│ │ ├── wheel-e.png
│ │ ├── don-hottub-deck.jpg
│ │ ├── aol_button_150_47.png
│ │ ├── openid_small_logo.png
│ │ ├── google_button_150_47.png
│ │ ├── yahoo_button_150_47.png
│ │ ├── wheel.svg
│ │ ├── wheel-e.svg
│ │ └── seal.svg
│ └── stylesheets
│ │ ├── application.css
│ │ └── main.scss
├── views
│ ├── dashboard
│ │ ├── gaignore.html.erb
│ │ ├── start_delivery.html
│ │ ├── ready_delivery.html.erb
│ │ ├── biglogin.html
│ │ ├── index.html.erb
│ │ └── contact.html.erb
│ ├── users
│ │ ├── _location.html.erb
│ │ ├── _deliveries.html.erb
│ │ ├── show.html.erb
│ │ ├── _billing.html.erb
│ │ ├── _menu.html.erb
│ │ ├── _profile.html.erb
│ │ ├── edit.html.erb
│ │ └── schedule.html.erb
│ ├── delivery_mailer
│ │ ├── updated.text.erb
│ │ ├── accepted.text.erb
│ │ └── comment.text.erb
│ ├── deliveries
│ │ ├── _list.html.erb
│ │ ├── _single_due.html.erb
│ │ ├── _single_address_map.html.erb
│ │ ├── index.html.erb
│ │ ├── _single.html.erb
│ │ ├── confirm.html.erb
│ │ ├── show.html.erb
│ │ └── edit.html.erb
│ ├── user_mailer
│ │ └── login_token_email.text.erb
│ ├── layouts
│ │ ├── _footer.html.erb
│ │ ├── _google_maps.html.erb
│ │ ├── _menubar.html.erb
│ │ ├── _flashmsg.html.erb
│ │ ├── _google_analytics.html.erb
│ │ ├── _getsatisfaction.html.erb
│ │ ├── application.html.erb
│ │ ├── _header.html.erb
│ │ └── _geode.html.erb
│ └── journal
│ │ └── index.html.erb
├── controllers
│ ├── payments_controller.rb
│ ├── dashboard_controller.rb
│ ├── application_controller.rb
│ ├── journal_controller.rb
│ ├── session_controller.rb
│ ├── git_hub_controller.rb
│ ├── users_controller.rb
│ └── deliveries_controller.rb
├── jobs
│ └── twitter_job.rb
└── helpers
│ └── application_helper.rb
├── vendor
├── plugins
│ └── .gitkeep
└── assets
│ └── stylesheets
│ └── .gitkeep
├── spec
├── rcov.opts
├── spec.opts
├── models
│ ├── schedule_spec.rb
│ ├── journal_spec.rb
│ ├── location_spec.rb
│ ├── fee_spec.rb
│ ├── package_spec.rb
│ ├── user_spec.rb
│ └── delivery_spec.rb
├── mailers
│ ├── user_mailer_spec.rb
│ └── delivery_mailer_spec.rb
├── fixtures
│ ├── fees.yml
│ ├── users.yml
│ ├── journal.yml
│ ├── locations.yml
│ ├── packages.yml
│ ├── openidentities.yml
│ └── deliveries.yml
├── controllers
│ ├── journal_controller_spec.rb
│ ├── dashboard_controller_spec.rb
│ ├── git_hub_controller_spec.rb
│ ├── session_controller_spec.rb
│ ├── users_controller_spec.rb
│ └── deliveries_controller_spec.rb
├── views
│ ├── users
│ │ └── show.html.erb_spec.rb
│ ├── git_hub
│ │ └── commit.html.erb_spec.rb
│ ├── layouts
│ │ └── application.html.erb_spec.rb
│ ├── dashboard
│ │ └── index.html.erb_spec.rb
│ └── deliveries
│ │ ├── edit.html.erb_spec.rb
│ │ ├── index.html.erb_spec.rb
│ │ └── show.html.erb_spec.rb
└── spec_helper.rb
├── config
├── initializers
│ ├── _settings.rb
│ ├── mime_types.rb
│ ├── exception_notifier.rb
│ ├── twitter.rb
│ ├── inflections.rb
│ ├── backtrace_silencers.rb
│ ├── session_store.rb
│ ├── secret_token.rb
│ ├── wrap_parameters.rb
│ └── devise.rb
├── environment.rb
├── boot.rb
├── locales
│ ├── en.yml
│ └── devise.en.yml
├── settings.yml.example
├── routes.rb
├── environments
│ ├── development.rb
│ ├── test.rb
│ └── production.rb
└── application.rb
├── script
├── hourly.rb
├── delayed_job
└── rails
├── db
├── migrate
│ ├── 20111003183742_location_name.rb
│ ├── 20090421175806_add_user.rb
│ ├── 20090807223209_add_email_to_user.rb
│ ├── 20110115184624_add_fee_method.rb
│ ├── 20090828195035_add_users_clocked_in.rb
│ ├── 20101123223921_add_featured_flag.rb
│ ├── 20130929215541_add_queue_to_delayed_jobs.rb
│ ├── 20090727203928_add_price_to_package.rb
│ ├── 20090424180923_create_fees.rb
│ ├── 20090916183925_add_accepted_at_to_delivery.rb
│ ├── 20091028235007_user_email_on_new_listing.rb
│ ├── 20110920184328_devise_user.rb
│ ├── 20111004010538_create_comments.rb
│ ├── 20090824161024_add_delivery_start_end_distance.rb
│ ├── 20090421182229_create_locations.rb
│ ├── 20090424003438_create_openids.rb
│ ├── 20090812000239_create_sightings.rb
│ ├── 20090908222348_clockedin_boolean_to_time.rb
│ ├── 20090506004017_user_add_timezone_displaymeasurement.rb
│ ├── 20111012174153_create_schedules.rb
│ ├── 20090421182220_create_packages.rb
│ ├── 20090428170519_create_journal.rb
│ ├── 20090811235813_add_lat_long_to_location.rb
│ ├── 20090421181738_create_deliveries.rb
│ ├── 20090803214257_add_time_to_fee.rb
│ ├── 20101228194334_add_workflow_state.rb
│ ├── 20101207021937_create_slugs.rb
│ ├── 20090424003439_add_open_id_store_to_db.rb
│ └── 20111006165028_create_delayed_jobs.rb
├── seeds.rb
└── schema.rb
├── .gitignore
├── doc
└── README_FOR_APP
├── Rakefile
├── config.ru
├── Gemfile
├── Gemfile.lock
└── README
/log/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/tasks/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/mailers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/plugins/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/assets/javascripts/util.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/views/dashboard/gaignore.html.erb:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/rcov.opts:
--------------------------------------------------------------------------------
1 | --exclude "spec/*,gems/*"
2 | --rails
--------------------------------------------------------------------------------
/spec/spec.opts:
--------------------------------------------------------------------------------
1 | --colour
2 | --format specdoc
3 | --loadby mtime
4 | --reverse
5 |
--------------------------------------------------------------------------------
/app/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/logo.png
--------------------------------------------------------------------------------
/app/assets/images/wheel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/wheel.png
--------------------------------------------------------------------------------
/app/models/comment.rb:
--------------------------------------------------------------------------------
1 | class Comment < ActiveRecord::Base
2 | belongs_to :delivery
3 | belongs_to :user
4 | end
5 |
--------------------------------------------------------------------------------
/app/assets/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/favicon.png
--------------------------------------------------------------------------------
/app/assets/images/wheel-e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/wheel-e.png
--------------------------------------------------------------------------------
/app/models/sighting.rb:
--------------------------------------------------------------------------------
1 | class Sighting < ActiveRecord::Base
2 | belongs_to :user
3 | belongs_to :location
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/payments_controller.rb:
--------------------------------------------------------------------------------
1 | class PaymentsController < ApplicationController
2 | def paypal
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/jobs/twitter_job.rb:
--------------------------------------------------------------------------------
1 | class TwitterJob < Struct.new(:update)
2 | def perform
3 | Twitter.update(update)
4 | end
5 | end
--------------------------------------------------------------------------------
/config/initializers/_settings.rb:
--------------------------------------------------------------------------------
1 | SETTINGS = YAML.load(File.open(Rails.root+"config/settings.yml")) unless defined? SETTINGS
2 |
3 |
--------------------------------------------------------------------------------
/app/assets/images/don-hottub-deck.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/don-hottub-deck.jpg
--------------------------------------------------------------------------------
/app/assets/images/aol_button_150_47.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/aol_button_150_47.png
--------------------------------------------------------------------------------
/app/assets/images/openid_small_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/openid_small_logo.png
--------------------------------------------------------------------------------
/app/assets/images/google_button_150_47.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/google_button_150_47.png
--------------------------------------------------------------------------------
/app/assets/images/yahoo_button_150_47.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/donpdonp/everyonedelivers/master/app/assets/images/yahoo_button_150_47.png
--------------------------------------------------------------------------------
/script/hourly.rb:
--------------------------------------------------------------------------------
1 | # Run hourly
2 | require 'maintenance'
3 |
4 | # Clean out the clocked_in users older than an hour
5 | Maintenance.clock_clean
6 |
--------------------------------------------------------------------------------
/app/views/users/_location.html.erb:
--------------------------------------------------------------------------------
1 |
2 | Recorded <%= @user.sightings.size %> sightings at <%= @user.locations.size %> locations.
3 |
4 |
--------------------------------------------------------------------------------
/spec/models/schedule_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Schedule do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/mailers/user_mailer_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe UserMailer do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/mailers/delivery_mailer_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe DeliveryMailer do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/app/models/journal.rb:
--------------------------------------------------------------------------------
1 | class Journal < ActiveRecord::Base
2 | belongs_to :delivery
3 | belongs_to :user
4 | belongs_to :package
5 | belongs_to :location
6 | end
7 |
--------------------------------------------------------------------------------
/app/views/dashboard/start_delivery.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | To complete the delivery request, please use the email login form above.
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/db/migrate/20111003183742_location_name.rb:
--------------------------------------------------------------------------------
1 | class LocationName < ActiveRecord::Migration
2 | def change
3 | add_column :locations, :name, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/fixtures/fees.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 |
3 | # one:
4 | # column: value
5 | #
6 | # two:
7 | # column: value
8 |
--------------------------------------------------------------------------------
/spec/fixtures/users.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 |
3 | # one:
4 | # column: value
5 | #
6 | # two:
7 | # column: value
8 |
--------------------------------------------------------------------------------
/spec/fixtures/journal.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 |
3 | # one:
4 | # column: value
5 | #
6 | # two:
7 | # column: value
8 |
--------------------------------------------------------------------------------
/spec/fixtures/locations.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 |
3 | # one:
4 | # column: value
5 | #
6 | # two:
7 | # column: value
8 |
--------------------------------------------------------------------------------
/spec/fixtures/packages.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 |
3 | # one:
4 | # column: value
5 | #
6 | # two:
7 | # column: value
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle
2 | db/*.sqlite3
3 | log/*.log
4 | tmp/
5 | .sass-cache/
6 | gems/
7 | config/database.yml
8 | config/settings.yml
9 | .rspec
10 | bin/
11 | public/assets/
12 |
--------------------------------------------------------------------------------
/spec/fixtures/openidentities.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 |
3 | # one:
4 | # column: value
5 | #
6 | # two:
7 | # column: value
8 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the rails application
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the rails application
5 | EveryoneDelivers::Application.initialize!
6 |
--------------------------------------------------------------------------------
/script/delayed_job:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
4 | require 'delayed/command'
5 | Delayed::Command.new(ARGV).daemonize
6 |
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | def link_to_user(user)
3 | if user
4 | link_to user.username, user_path(user)
5 | else
6 | "(none)"
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/views/delivery_mailer/updated.text.erb:
--------------------------------------------------------------------------------
1 | Delivery #<%=@delivery.id%> has been updated.
2 |
3 | <%= url_for(:host => SETTINGS["email"]["domain"], :controller => :deliveries, :action => :show, :id => @delivery.id )%>
4 |
5 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 |
3 | # Set up gems listed in the Gemfile.
4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5 |
6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
7 |
--------------------------------------------------------------------------------
/doc/README_FOR_APP:
--------------------------------------------------------------------------------
1 | Use this README file to introduce your application and point to useful places in the API for learning more.
2 | Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
3 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-Agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/app/views/deliveries/_list.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <% deliveries.each do |delivery| %>
3 |
4 | <%= render :partial => "deliveries/single", :locals => {:delivery => delivery} %>
5 |
6 | <% end %>
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/views/user_mailer/login_token_email.text.erb:
--------------------------------------------------------------------------------
1 | Welcome to <%= SETTINGS["email"]["domain"]%>, <%= @user.username %>
2 | ===============================================
3 |
4 | Follow this link to login:
5 |
6 | <%= @url %>
7 |
8 | -- Email Robot
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/db/migrate/20090421175806_add_user.rb:
--------------------------------------------------------------------------------
1 | class AddUser < ActiveRecord::Migration
2 | def self.up
3 | create_table :users do |t|
4 | t.string :username
5 | t.timestamps
6 | end
7 | end
8 |
9 | def self.down
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20090807223209_add_email_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddEmailToUser < ActiveRecord::Migration
2 | def self.up
3 | add_column :users, :email, :string
4 | end
5 |
6 | def self.down
7 | remove_column :users, :email, :string
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20110115184624_add_fee_method.rb:
--------------------------------------------------------------------------------
1 | class AddFeeMethod < ActiveRecord::Migration
2 | def self.up
3 | add_column :fees, :payment_method, :string
4 | end
5 |
6 | def self.down
7 | add_column :fees, :payment_method
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20090828195035_add_users_clocked_in.rb:
--------------------------------------------------------------------------------
1 | class AddUsersClockedIn < ActiveRecord::Migration
2 | def self.up
3 | add_column :users, :clocked_in, :boolean
4 | end
5 |
6 | def self.down
7 | remove_column :users, :clocked_in
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20101123223921_add_featured_flag.rb:
--------------------------------------------------------------------------------
1 | class AddFeaturedFlag < ActiveRecord::Migration
2 | def self.up
3 | add_column :deliveries, :featured, :boolean
4 | end
5 |
6 | def self.down
7 | remove_column :deliveries, :featured
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/views/delivery_mailer/accepted.text.erb:
--------------------------------------------------------------------------------
1 | Delivery #<%=@delivery.id%> has been accepted for delivery by <%= @delivery.delivering_user.username%>.
2 |
3 | <%= url_for(:host => SETTINGS["email"]["domain"], :controller => :deliveries, :action => :show, :id => @delivery.id )%>
4 |
--------------------------------------------------------------------------------
/config/initializers/exception_notifier.rb:
--------------------------------------------------------------------------------
1 | EveryoneDelivers::Application.config.middleware.use(ExceptionNotifier,
2 | :sender_address => SETTINGS["email"]["from"],
3 | :exception_recipients => SETTINGS["exception_notifier"]["email"])
4 |
--------------------------------------------------------------------------------
/db/migrate/20130929215541_add_queue_to_delayed_jobs.rb:
--------------------------------------------------------------------------------
1 | class AddQueueToDelayedJobs < ActiveRecord::Migration
2 | def self.up
3 | add_column :delayed_jobs, :queue, :string
4 | end
5 |
6 | def self.down
7 | remove_column :delayed_jobs, :queue
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/views/delivery_mailer/comment.text.erb:
--------------------------------------------------------------------------------
1 | Delivery #<%=@delivery.id%> has a new comment from <%= @comment.user.username %>.
2 |
3 | "<%= @comment.text %>"
4 |
5 | <%= url_for(:host => SETTINGS["email"]["domain"], :controller => :deliveries, :action => :show, :id => @delivery.id )%>
6 |
--------------------------------------------------------------------------------
/db/migrate/20090727203928_add_price_to_package.rb:
--------------------------------------------------------------------------------
1 | class AddPriceToPackage < ActiveRecord::Migration
2 | def self.up
3 | add_column :packages, :price_in_cents, :integer
4 | end
5 |
6 | def self.down
7 | remove_column :packages, :price_in_cents
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20090424180923_create_fees.rb:
--------------------------------------------------------------------------------
1 | class CreateFees < ActiveRecord::Migration
2 | def self.up
3 | create_table :fees do |t|
4 | t.integer :price_in_cents
5 | t.timestamps
6 | end
7 | end
8 |
9 | def self.down
10 | drop_table :fees
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20090916183925_add_accepted_at_to_delivery.rb:
--------------------------------------------------------------------------------
1 | class AddAcceptedAtToDelivery < ActiveRecord::Migration
2 | def self.up
3 | add_column :deliveries, :accepted_at, :datetime
4 | end
5 |
6 | def self.down
7 | remove_column :deliveries, :accepted_at
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20091028235007_user_email_on_new_listing.rb:
--------------------------------------------------------------------------------
1 | class UserEmailOnNewListing < ActiveRecord::Migration
2 | def self.up
3 | add_column :users, :email_on_new_listing, :boolean
4 | end
5 |
6 | def self.down
7 | remove_column :users, :email_on_new_listing
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20110920184328_devise_user.rb:
--------------------------------------------------------------------------------
1 | require 'uuidtools'
2 | class DeviseUser < ActiveRecord::Migration
3 | def change
4 | add_column :users, :authentication_token, :string
5 | User.all.each{|u| u.update_attribute :authentication_token, UUIDTools::UUID.random_create.to_s}
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20111004010538_create_comments.rb:
--------------------------------------------------------------------------------
1 | class CreateComments < ActiveRecord::Migration
2 | def change
3 | create_table :comments do |t|
4 | t.integer :delivery_id
5 | t.integer :user_id
6 | t.string :text
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path('../config/application', __FILE__)
6 |
7 | EveryoneDelivers::Application.load_tasks
8 |
--------------------------------------------------------------------------------
/db/migrate/20090824161024_add_delivery_start_end_distance.rb:
--------------------------------------------------------------------------------
1 | class AddDeliveryStartEndDistance < ActiveRecord::Migration
2 | def self.up
3 | add_column :deliveries, :start_end_distance, :integer
4 | end
5 |
6 | def self.down
7 | remove_column :deliveries, :start_end_distance
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | APP_PATH = File.expand_path('../../config/application', __FILE__)
5 | require File.expand_path('../../config/boot', __FILE__)
6 | require 'rails/commands'
7 |
--------------------------------------------------------------------------------
/spec/controllers/journal_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe JournalController do
4 |
5 | before(:each) do
6 | controller.stub!(:set_timezone)
7 | end
8 |
9 | it "should show the journal" do
10 | get :index
11 | end
12 |
13 | end
14 |
--------------------------------------------------------------------------------
/config/initializers/twitter.rb:
--------------------------------------------------------------------------------
1 | Twitter.configure do |config|
2 | config.consumer_key = SETTINGS["twitter"]["consumer_key"]
3 | config.consumer_secret = SETTINGS["twitter"]["consumer_secret"]
4 | config.oauth_token = SETTINGS["twitter"]["oauth_token"]
5 | config.oauth_token_secret = SETTINGS["twitter"]["oauth_secret"]
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20090421182229_create_locations.rb:
--------------------------------------------------------------------------------
1 | class CreateLocations < ActiveRecord::Migration
2 | def self.up
3 | create_table :locations do |t|
4 | t.string :street
5 | t.string :zipcode
6 | t.timestamps
7 | end
8 | end
9 |
10 | def self.down
11 | drop_table :locations
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | header:
6 | login: "Login"
7 | logout: "logout"
8 | email_login_placeholder: "Login with email address"
--------------------------------------------------------------------------------
/db/migrate/20090424003438_create_openids.rb:
--------------------------------------------------------------------------------
1 | class CreateOpenids < ActiveRecord::Migration
2 | def self.up
3 | create_table :openidentities do |t|
4 | t.string :url
5 | t.integer :user_id
6 | t.timestamps
7 | end
8 | end
9 |
10 | def self.down
11 | drop_table :openidentites
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/models/journal_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe Journal do
4 | before(:each) do
5 | @valid_attributes = {
6 | }
7 | end
8 |
9 | it "should create a new instance given valid attributes" do
10 | Journal.create!(@valid_attributes)
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/models/location_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe Location do
4 | before(:each) do
5 | @valid_attributes = {
6 | }
7 | end
8 |
9 | it "should create a new instance given valid attributes" do
10 | Location.create!(@valid_attributes)
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/views/layouts/_footer.html.erb:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/lib/maintenance.rb:
--------------------------------------------------------------------------------
1 | class Maintenance
2 | def self.clock_clean
3 | User.clocked_ins.each do |user|
4 | if user.clocked_in < Time.now - 1.hour
5 | user.clock_out!
6 | Journal.create({:delivery => nil, :user => user, :note => "Clocked out #{user.username} after an hour"})
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/views/users/_deliveries.html.erb:
--------------------------------------------------------------------------------
1 | Listed deliveries
2 |
3 | <%= render :partial => 'deliveries/list', :locals => {:timedesc => "", :deliveries => user.listed_deliveries} %>
4 |
5 | Accepted deliveries
6 |
7 | <%= render :partial => 'deliveries/list', :locals => {:timedesc => "", :deliveries => user.accepted_deliveries} %>
8 |
--------------------------------------------------------------------------------
/db/migrate/20090812000239_create_sightings.rb:
--------------------------------------------------------------------------------
1 | class CreateSightings < ActiveRecord::Migration
2 | def self.up
3 | create_table :sightings do |t|
4 | t.column :user_id, :integer
5 | t.column :location_id, :integer
6 | t.timestamps
7 | end
8 | end
9 |
10 | def self.down
11 | drop_table :sightings
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/controllers/dashboard_controller.rb:
--------------------------------------------------------------------------------
1 | class DashboardController < ApplicationController
2 |
3 | def index
4 | @featured_delivery = Delivery.first(:conditions => {:featured => true})
5 | end
6 |
7 | def start_delivery
8 | end
9 |
10 | def ready_delivery
11 | redirect_to :action => :start_delivery unless user_signed_in?
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20090908222348_clockedin_boolean_to_time.rb:
--------------------------------------------------------------------------------
1 | class ClockedinBooleanToTime < ActiveRecord::Migration
2 | def self.up
3 | remove_column :users, :clocked_in
4 | add_column :users, :clocked_in, :datetime
5 | end
6 |
7 | def self.down
8 | remove_column :users, :clocked_in
9 | add_column :users, :clocked_in, :boolean
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/mailers/user_mailer.rb:
--------------------------------------------------------------------------------
1 | class UserMailer < ActionMailer::Base
2 | default from: SETTINGS["email"]["from"]
3 |
4 | def login_token_email(user)
5 | @user = user
6 | @url = "http://#{SETTINGS["email"]["domain"]}/session/login_token?token=#{user.authentication_token}"
7 | mail(:to => user.email, :subject => "EveryoneDelivers Login Button")
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/views/layouts/_google_maps.html.erb:
--------------------------------------------------------------------------------
1 |
3 |
10 |
--------------------------------------------------------------------------------
/spec/controllers/dashboard_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe DashboardController do
4 |
5 | before(:each) do
6 | controller.stub!(:set_timezone)
7 | end
8 |
9 | it "should display the splash" do
10 | get :index
11 | response.should render_template("dashboard/index")
12 | end
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/app/views/dashboard/ready_delivery.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | You did it!
4 |
5 |
6 | Press the link below to
7 | start filling in details about your delivery requset.
8 |
9 | <%= form_for Delivery.new do |f| %>
10 | <%= submit_tag "Create a delivery"%>
11 | <% end %>
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll automatically include all the stylesheets available in this directory
3 | * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4 | * the top of the compiled file, but it's generally better to create a new file per style scope.
5 | *= require_self
6 | *= require_tree .
7 | */
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery # See ActionController::RequestForgeryProtection for details
3 | before_filter :set_timezone
4 |
5 | def set_timezone
6 | # current_user.time_zone #=> 'London'
7 | Time.zone = current_user.time_zone if current_user && !current_user.time_zone.blank?
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20090506004017_user_add_timezone_displaymeasurement.rb:
--------------------------------------------------------------------------------
1 | class UserAddTimezoneDisplaymeasurement < ActiveRecord::Migration
2 | def self.up
3 | add_column :users, :time_zone, :string
4 | add_column :users, :display_measurement, :string
5 | end
6 |
7 | def self.down
8 | remove_column :users, :time_zone
9 | remove_column :users, :display_measurement
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/assets/javascripts/schedule_add.js:
--------------------------------------------------------------------------------
1 | function schedule_submit(event) {
2 | console.log("submit!");
3 | if($('#gmaplat').val().length > 0 &&
4 | $('#gmaplng').val().length > 0 &&
5 | $('#street1_field').val().length > 0 &&
6 | $('#street2_field').val().length > 0 ) {
7 | return true;
8 | } else {
9 | alert('Please position the map marker');
10 | return false;
11 | }
12 | }
--------------------------------------------------------------------------------
/app/views/deliveries/_single_due.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <% if fee.delivery_due %>
3 | <% if fee.delivery_due >= Time.now %>
4 | Due in
5 | <% else %>
6 | Overdue by
7 | <% end %>
8 | <%= distance_of_time_in_words_to_now(fee.delivery_due) %>
9 | <% else %>
10 | Due date missing.
11 | <% end %>
12 |
13 |
--------------------------------------------------------------------------------
/spec/views/users/show.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "/users/show.html.erb" do
4 | before(:each) do
5 | view.stub!(:user_signed_in?).and_return(true)
6 | @user = mock_model(User, :username => "bob")
7 | end
8 |
9 | it "should render" do
10 | assign(:user, @user)
11 | render
12 | rendered.should have_selector('div#sampledelivery')
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/db/migrate/20111012174153_create_schedules.rb:
--------------------------------------------------------------------------------
1 | class CreateSchedules < ActiveRecord::Migration
2 | def change
3 | create_table :schedules do |t|
4 | t.datetime :starting_at
5 | t.datetime :ending_at
6 | t.float :latitude
7 | t.float :longitude
8 | t.string :street1
9 | t.string :street2
10 |
11 | t.integer :user_id
12 | t.timestamps
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 |
9 | Delivery.create({featured: true})
10 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format
4 | # (all these examples are active by default):
5 | ActiveSupport::Inflector.inflections do |inflect|
6 | # inflect.plural /^(ox)$/i, '\1en'
7 | # inflect.singular /^(ox)en/i, '\1'
8 | # inflect.irregular 'person', 'people'
9 | inflect.uncountable %w( journal )
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20090421182220_create_packages.rb:
--------------------------------------------------------------------------------
1 | class CreatePackages < ActiveRecord::Migration
2 | def self.up
3 | create_table :packages do |t|
4 | t.string :description
5 | t.float :weight_in_grams
6 | t.float :height_in_meters
7 | t.float :width_in_meters
8 | t.float :depth_in_meters
9 | t.timestamps
10 | end
11 | end
12 |
13 | def self.down
14 | drop_table :packages
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/db/migrate/20090428170519_create_journal.rb:
--------------------------------------------------------------------------------
1 | class CreateJournal < ActiveRecord::Migration
2 | def self.up
3 | create_table :journal do |t|
4 | t.integer :delivery_id
5 | t.integer :package_id
6 | t.integer :user_id
7 | t.integer :location_id
8 | t.float :fee
9 | t.string :note
10 | t.timestamps
11 | end
12 | end
13 |
14 | def self.down
15 | drop_table :journal
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/db/migrate/20090811235813_add_lat_long_to_location.rb:
--------------------------------------------------------------------------------
1 | class AddLatLongToLocation < ActiveRecord::Migration
2 | def self.up
3 | add_column :locations, :latitude, :float
4 | add_column :locations, :longitude, :float
5 | add_column :locations, :accuracy, :float
6 | end
7 |
8 | def self.down
9 | remove_column :locations, :latitude
10 | remove_column :locations, :longitude
11 | remove_column :locations, :accuracy
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/controllers/git_hub_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe GitHubController do
4 |
5 | before(:each) do
6 | controller.stub!(:set_timezone)
7 | end
8 |
9 | describe "GET 'commit'" do
10 | it "should be successful" do
11 | controller.should_receive(:shell)
12 | get 'commit', :payload => '{}'
13 | response.should be_success
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/spec/views/git_hub/commit.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2 |
3 | describe "/git_hub/commit.html.erb" do
4 | # before(:each) do
5 | # render 'git_hub/commit'
6 | # end
7 |
8 | #Delete this example and add some real ones or delete this file
9 | # it "should tell you where to find the file" do
10 | # response.should have_tag('p', %r[Find me in app/views/git_hub/commit])
11 | # end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/views/layouts/application.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "/layouts/application.html.erb" do
4 | before(:each) do
5 | controller.should_receive(:user_signed_in?).and_return(false)
6 | render
7 | end
8 |
9 | it "should contain the google adsense code and unique ID" do
10 | rendered.should have_selector('div#google_adsense', :content => "getTracker\(\"#{SETTINGS["google"]["adsense"]["id"]}\"\)")
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/views/users/show.html.erb:
--------------------------------------------------------------------------------
1 | <% tab = params[:tab] || 'profile' %>
2 | <% content_for :title do %>
3 | User <%=h @user.username %>
4 | <% end %>
5 |
6 |
7 | User Profile for <%=h @user.username %>
8 |
9 |
10 | <%= render :partial => 'menu', :locals => {:user => @user} %>
11 |
12 | <% if ['profile', 'deliveries', 'location', 'billing'].include? tab %>
13 | <%= render :partial => tab, :locals => {:user => @user} %>
14 | <% end %>
15 |
16 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | EveryoneDelivers::Application.config.session_store :cookie_store, key: '_EveryoneDelivers_session'
4 |
5 | # Use the database for sessions instead of the cookie-based default,
6 | # which shouldn't be used to store highly confidential information
7 | # (create the session table with "rails generate session_migration")
8 | # EveryoneDelivers::Application.config.session_store :active_record_store
9 |
--------------------------------------------------------------------------------
/db/migrate/20090421181738_create_deliveries.rb:
--------------------------------------------------------------------------------
1 | class CreateDeliveries < ActiveRecord::Migration
2 | def self.up
3 | create_table :deliveries do |t|
4 | t.integer :fee_id
5 | t.integer :package_id
6 | t.integer :start_location_id
7 | t.integer :end_location_id
8 | t.integer :listing_user_id
9 | t.integer :delivering_user_id
10 | t.timestamps
11 | end
12 | end
13 |
14 | def self.down
15 | drop_table :deliveries
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/db/migrate/20090803214257_add_time_to_fee.rb:
--------------------------------------------------------------------------------
1 | class AddTimeToFee < ActiveRecord::Migration
2 | def self.up
3 | add_column :fees, :delivery_due, :datetime
4 | Fee.reset_column_information
5 | Delivery.all.each{|d| d.fee.update_attribute(:delivery_due, d.created_at) if d.fee}
6 | Fee.all(:conditions => {:delivery_due => nil}).each{|f| f.update_attribute :delivery_due, Time.now}
7 | end
8 |
9 | def self.down
10 | remove_column :fees, :delivery_due
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/views/layouts/_menubar.html.erb:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/app/views/users/_billing.html.erb:
--------------------------------------------------------------------------------
1 | <% year = Time.now.year; month = Time.now.month %>
2 | <% all_deliveries = user.accepted_deliveries %>
3 | <% month_deliveries = user.accepted_deliveries(year,month) %>
4 | Account
5 |
6 | Total Accepted deliveries : <%= all_deliveries.size %>
7 |
8 |
9 | Accepted deliveries for <%=year%>/<%=month%>: <%= month_deliveries.size %>
10 |
11 | $0.50 per delivery x <%= month_deliveries.size %> deliveries = $<%= 0.50 * month_deliveries.size %>
12 |
13 |
--------------------------------------------------------------------------------
/spec/views/dashboard/index.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "/dashboard/index.html.erb" do
4 | before(:each) do
5 | view.stub!(:user_signed_in?).and_return(false)
6 | end
7 |
8 | it "should render" do
9 | featured_delivery = mock_model(Delivery)
10 | featured_delivery.should_receive(:ok_to_display?).and_return(false)
11 | assign(:featured_delivery,featured_delivery)
12 | render
13 | rendered.should have_selector('div#sampledelivery')
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/views/layouts/_flashmsg.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <% if flash[:error] %>
3 |
4 | <%=h flash[:error] %>
5 |
6 | <% end %>
7 | <% if flash[:notice] %>
8 |
9 | <%=h flash[:notice] %>
10 |
11 | <% end %>
12 | <% if flash[:success] %>
13 |
14 | <%=h flash[:success] %>
15 |
16 | <% end %>
17 |
18 |
--------------------------------------------------------------------------------
/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into including all the files listed below.
2 | // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3 | // be included in the compiled file accessible from http://example.com/assets/application.js
4 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5 | // the compiled file.
6 | //
7 | //= require jquery
8 | //= require jquery_ujs
9 | //= require_tree .
10 |
--------------------------------------------------------------------------------
/app/controllers/journal_controller.rb:
--------------------------------------------------------------------------------
1 | class JournalController < ApplicationController
2 |
3 | def index
4 | @entries = Journal.all(:order => "id desc", :conditions => ["created_at > ?",1.month.ago])
5 | end
6 |
7 | def count
8 | @entries = Journal.count(:conditions => ["note = ? and created_at > ?",
9 | params[:note],
10 | params[:hours].to_i.hours.ago])
11 | render :json => {:count => @entries}.to_json
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | EveryoneDelivers::Application.config.secret_token = 'e1d1226ab2ebcd4d804bc15d3b6f88da26e04a5560da2094f2b178c03c664b4bfb1499948aa832caebde7acba9101c0a4d957c7d81548c457878e8cfae5ec1a2'
8 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 | #
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # Disable root element in JSON by default.
12 | ActiveSupport.on_load(:active_record) do
13 | self.include_root_in_json = false
14 | end
15 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | require 'yaml'
2 | # This file is used by Rack-based servers to start the application.
3 | SETTINGS = YAML.load(File.open(File.join(File.dirname(__FILE__), "config/settings.yml")))
4 |
5 | require './lib/shorten'
6 | require ::File.expand_path('../config/environment', __FILE__)
7 |
8 | use Shorten
9 |
10 | builder = Rack::Builder.new do
11 | map '/assets' do
12 | run Rack::File.new(File.join(File.dirname(__FILE__),"public/assets/"))
13 | end
14 |
15 | map '/' do
16 | run EveryoneDelivers::Application
17 | end
18 | end
19 | run builder
20 |
--------------------------------------------------------------------------------
/lib/shorten.rb:
--------------------------------------------------------------------------------
1 | class Shorten
2 | def initialize(app)
3 | @app = app
4 | end
5 |
6 | def call(env)
7 | if env["HTTP_HOST"] == SETTINGS["redirect"]["hostname"]
8 | redir = env["SERVER_PROTOCOL"].split('/').first + "://"+ SETTINGS["email"]["domain"] +
9 | "/deliveries" + env["PATH_INFO"]
10 | status, headers, response = [ 302, {"Content-Type"=>"text/plain", "Location"=> redir }, [] ]
11 | else
12 | status, headers, response = @app.call(env)
13 | end
14 | [status, headers, response]
15 | end
16 | end
--------------------------------------------------------------------------------
/spec/models/fee_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe Fee do
4 | before(:each) do
5 | @valid_attributes = {
6 | }
7 | end
8 |
9 | it "should create a new instance given valid attributes" do
10 | Fee.create!(@valid_attributes)
11 | end
12 |
13 | it "should sanitize and store new attributes" do
14 | fee = Fee.create!(@valid_attributes)
15 | new_attributes = { :display_price => "1.50" }
16 | fee.apply_form_attributes(new_attributes)
17 | fee.price_in_cents.should == 150
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/config/settings.yml.example:
--------------------------------------------------------------------------------
1 | ---
2 | journal:
3 | notification_email_address: ""
4 | bunny:
5 | start:
6 | user:
7 | pass:
8 | host:
9 | google:
10 | adsense:
11 | id: "UA-XXXXXX-X"
12 | maps:
13 | key: ""
14 | bing:
15 | maps:
16 | key: ""
17 | email:
18 | domain: ""
19 | from: ""
20 | getsatisfaction:
21 | company: ""
22 | exception_notifier:
23 | email: ""
24 | twitter:
25 | consumer_key: ""
26 | consumer_secret: ""
27 | oauth_token: ""
28 | oauth_secret: ""
29 | shortname:
30 | url: "http://shorturl.tld"
31 | geonames:
32 | username:
33 |
34 |
--------------------------------------------------------------------------------
/app/views/layouts/_google_analytics.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
--------------------------------------------------------------------------------
/spec/fixtures/deliveries.yml:
--------------------------------------------------------------------------------
1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 |
3 | tg11:
4 | id: 1
5 | created_at: <%= Time.zone.parse("2009-01-01 12:00") %>
6 | tg12:
7 | id: 2
8 | created_at: <%= Time.zone.parse("2009-01-01 12:10") %>
9 | tg21:
10 | id: 3
11 | created_at: <%= Time.zone.parse("2009-01-01 11:00") %>
12 | tg22:
13 | id: 4
14 | created_at: <%= Time.zone.parse("2009-01-01 11:10") %>
15 | tg31:
16 | id: 5
17 | created_at: <%= Time.zone.parse("2009-01-01 01:00") %>
18 | tg32:
19 | id: 6
20 | created_at: <%= Time.zone.parse("2009-01-01 01:11") %>
21 |
--------------------------------------------------------------------------------
/db/migrate/20101228194334_add_workflow_state.rb:
--------------------------------------------------------------------------------
1 | class AddWorkflowState < ActiveRecord::Migration
2 | def self.up
3 | add_column :deliveries, :workflow_state, :string
4 | Delivery.all.each do |d|
5 | if d.delivering_user
6 | d.update_attribute :workflow_state, "delivered"
7 | else
8 | if d.ok_to_display?
9 | d.update_attribute :workflow_state, "waiting"
10 | else
11 | d.update_attribute :workflow_state, "building"
12 | end
13 | end
14 | end
15 | end
16 |
17 | def self.down
18 | remove_column :deliveries, :workflow_state
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/controllers/session_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe SessionController do
4 | before(:each) do
5 | controller.stub!(:set_timezone)
6 | end
7 |
8 | it "logs in a first-time user" do
9 | token = 'abc123'
10 | user = mock_model(User)
11 | User.should_receive(:find_by_authentication_token).with(token).and_return(user)
12 | controller.should_receive(:sign_in)
13 | get :login_token, {:token => token}
14 | end
15 |
16 | it "should logout the user" do
17 | controller.should_receive(:reset_session)
18 | get :logout
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/views/deliveries/edit.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "/deliveries/edit.html.erb" do
4 | before(:each) do
5 | view.stub!(:user_signed_in?).and_return(false)
6 | view.stub!(:current_user)
7 | end
8 |
9 | it "renders an empty delivery edit form" do
10 | delivery = mock_model(Delivery, :package => nil, :fee => nil,
11 | :delivering_user => nil,
12 | :start_location => nil,
13 | :end_location => nil)
14 | assign(:delivery, delivery)
15 |
16 | render
17 |
18 | end
19 | end
--------------------------------------------------------------------------------
/app/views/users/_menu.html.erb:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/spec/views/deliveries/index.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "/deliveries/index.html.erb" do
4 | before(:each) do
5 | end
6 |
7 | it "should render when someone is logged in" do
8 | view.should_receive(:user_signed_in?).twice.and_return(true)
9 | user = mock_model(User)
10 | assign(:clocked_ins,[user])
11 | user.should_receive(:clocked_in?).and_return(false)
12 | user.should_receive(:username).and_return("bob")
13 | assign(:delivery_groups, [])
14 | view.should_receive(:current_user).twice.and_return(user)
15 | render
16 | rendered.should have_selector('p')
17 | end
18 |
19 | end
20 |
--------------------------------------------------------------------------------
/app/views/users/_profile.html.erb:
--------------------------------------------------------------------------------
1 | Username: <%=h @user.username %>
2 | Email:
3 | <% if current_user == @user %>
4 | <%= @user.email %>
5 | <% else %>
6 | Hidden
7 | <% end %>
8 |
9 | Time zone: <%= @user.time_zone %>
10 | Units: <%if @user.display_measurement == "imperial" %>
11 | Imperial (miles/pounds)
12 | <% end %>
13 | <%if @user.display_measurement == "metric" %>
14 | Metric (meters/kilograms)
15 | <% end %>
16 |
17 | <% if @user.email_on_new_listing %>
18 | Send
19 | <% else %>
20 | Do not send
21 | <% end %>
22 | an email when a new delivery is created.
23 |
--------------------------------------------------------------------------------
/app/views/journal/index.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for(:title) do %>
2 | Journal
3 | <% end %>
4 | <%= @entries.size %> journal entries in the last month.
5 |
6 |
7 |
8 | date
9 | delivery
10 | user
11 | note
12 |
13 |
14 | <% @entries.each do |e| %>
15 |
16 | <%=h e.created_at.in_time_zone("Pacific Time (US & Canada)").strftime('%h-%d %H:%m')%>
17 | <%=e.delivery ? link_to(e.delivery_id, delivery_path(e.delivery_id)) : nil%>
18 | <%=h e.user ? link_to(h(truncate(e.user.username, :length => 15)), user_path(e.user)) : nil%>
19 | <%=h e.note%>
20 |
21 | <% end %>
22 |
23 |
--------------------------------------------------------------------------------
/db/migrate/20101207021937_create_slugs.rb:
--------------------------------------------------------------------------------
1 | class CreateSlugs < ActiveRecord::Migration
2 | def self.up
3 | create_table :slugs do |t|
4 | t.string :name
5 | t.integer :sluggable_id
6 | t.integer :sequence, :null => false, :default => 1
7 | t.string :sluggable_type, :limit => 40
8 | t.string :scope
9 | t.datetime :created_at
10 | end
11 | add_index :slugs, :sluggable_id
12 | add_index :slugs, [:name, :sluggable_type, :sequence, :scope], :name => "index_slugs_on_n_s_s_and_s", :unique => true
13 |
14 | # add_column :users, :cached_slug, :string
15 | end
16 |
17 | def self.down
18 | drop_table :slugs
19 | # remove_column :users, :cached_slug
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/mailers/delivery_mailer.rb:
--------------------------------------------------------------------------------
1 | class DeliveryMailer < ActionMailer::Base
2 | default from: SETTINGS["email"]["from"]
3 |
4 | def updated(delivery, user)
5 | @delivery = delivery
6 | mail(:to => user.email,
7 | :subject => "Delivery ##{delivery.id} details updated.")
8 | end
9 |
10 | def accepted(delivery)
11 | @delivery = delivery
12 | mail(:to => delivery.listing_user.email,
13 | :subject => "Delivery ##{delivery.id} accepted for delivery.")
14 | end
15 |
16 | def comment(delivery, comment)
17 | @delivery = delivery
18 | @comment = comment
19 | mail(:to => delivery.listing_user.email,
20 | :subject => "Delivery ##{delivery.id} has a new comment")
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | EveryoneDelivers::Application.routes.draw do
2 | resources :deliveries do
3 | member do
4 | put :accept
5 | put :confirm
6 | post :comment
7 | delete :comment_delete
8 | end
9 | end
10 |
11 | resources :users do
12 | member do
13 | put :update_location
14 | post :clock_in
15 | post :clock_out
16 | post :add_schedule
17 | get :schedule
18 | end
19 | end
20 |
21 | resources :locations
22 | resources :packages
23 |
24 | devise_for :users
25 | match '/' => 'dashboard#index', :as => :root
26 | match '/journal' => 'journal#index'
27 | match '/journal/count' => 'journal#count'
28 | match '/:controller(/:action(/:id))'
29 |
30 | end
31 |
--------------------------------------------------------------------------------
/spec/models/package_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe Package do
4 | before(:each) do
5 | @valid_attributes = {
6 | }
7 | end
8 |
9 | it "should create a new instance given valid attributes" do
10 | Package.create!(@valid_attributes)
11 | end
12 |
13 | it "should sanitize and store new attributes" do
14 | package = Package.create!(@valid_attributes)
15 | description="desc"
16 | form_attributes = { :description => description, :height => "3.30" }
17 | package.apply_form_attributes(form_attributes)
18 | package.description.should == description
19 | package.height_in_meters.should > 0.08 #fix
20 | package.height_in_meters.should < 0.09 #fix
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/models/schedule.rb:
--------------------------------------------------------------------------------
1 | class Schedule < ActiveRecord::Base
2 | belongs_to :user
3 |
4 | def apply_form_fields(params)
5 | if params[:street1]
6 | self.street1 = params[:street1]
7 | end
8 | if params[:street2]
9 | self.street2 = params[:street2]
10 | end
11 |
12 | # default
13 | self.starting_at = Time.now
14 |
15 | if params["ending_at(1i)"]
16 | self.ending_at = Time.parse("#{params["ending_at(1i)"]}-#{params["ending_at(2i)"]}-#{params["ending_at(3i)"]} "+
17 | "#{params["ending_at(4i)"]}:#{params["ending_at(5i)"]}")
18 | end
19 |
20 | if params[:latitude]
21 | self.latitude = params[:latitude]
22 | end
23 | if params[:street2]
24 | self.longitude = params[:longitude]
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The change you wanted was rejected.
23 |
Maybe you tried to change something you didn't have access to.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/views/deliveries/_single_address_map.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= image_tag location.gmap_static_html(100,100,14).html_safe, :alt => "map of #{location.name}" %>
5 |
6 |
7 |
<%= direction %>
8 | <% if to %>
9 | <%= link_to(to.username, to) %>
10 | <% end %>
11 |
12 | <% if location.name %>
13 | <%= location.name %>
14 | <% end %>
15 | <% location.street_parts.each do |part| %>
16 | <%=h part %>
17 | <% end %>
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The page you were looking for doesn't exist.
23 |
You may have mistyped the address or the page may have moved.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
We're sorry, but something went wrong.
23 |
We've been notified about this issue and we'll take a look at it shortly.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/views/dashboard/biglogin.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Login with Google
5 | <%= link_to image_tag("google_button_150_47.png"), :controller => :session,
6 | :action => :login,
7 | :openid_identifier => "https://www.google.com/accounts/o8/id" %>
8 |
9 |
10 | Login with Yahoo
11 | <%= link_to image_tag("yahoo_button_150_47.png"), :controller => :session,
12 | :action => :login,
13 | :openid_identifier => "http://www.yahoo.com" %>
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/views/dashboard/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | EveryoneDelivers is a marketplace for delivery services.
4 |
5 |
6 |
7 |
8 |
9 | <%= link_to "Request a delivery.", deliveries_path, :method => :post %>
10 |
11 |
12 | Have items and food delivered to
13 | your door. You set the delivery cost.
14 |
15 |
16 |
17 |
18 | <%= link_to "See delivery requests.", deliveries_path %>
19 |
20 |
21 | Deliver items to people and earn
22 | the delivery bounty.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | <%= render :partial => "deliveries/single", :locals => {:delivery => @featured_delivery} %>
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/views/layouts/_getsatisfaction.html.erb:
--------------------------------------------------------------------------------
1 |
6 |
7 |
17 |
--------------------------------------------------------------------------------
/db/migrate/20090424003439_add_open_id_store_to_db.rb:
--------------------------------------------------------------------------------
1 | # Use this migration to create the tables for the ActiveRecord store
2 | class AddOpenIdStoreToDb < ActiveRecord::Migration
3 | def self.up
4 | create_table "open_id_associations", :force => true do |t|
5 | t.column "server_url", :binary, :null => false
6 | t.column "handle", :string, :null => false
7 | t.column "secret", :binary, :null => false
8 | t.column "issued", :integer, :null => false
9 | t.column "lifetime", :integer, :null => false
10 | t.column "assoc_type", :string, :null => false
11 | end
12 |
13 | create_table "open_id_nonces", :force => true do |t|
14 | t.column :server_url, :string, :null => false
15 | t.column :timestamp, :integer, :null => false
16 | t.column :salt, :string, :null => false
17 | end
18 | end
19 |
20 | def self.down
21 | drop_table "open_id_associations"
22 | drop_table "open_id_nonces"
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/app/views/dashboard/contact.html.erb:
--------------------------------------------------------------------------------
1 | Contact
2 |
3 | People
4 |
5 | <%= image_tag 'don-hottub-deck.jpg', :style => "float: right; margin-left: 4em" %>
6 |
7 | <%= link_to 'Don Park', user_path('don-park')%> - Founder.
8 | Portland technologist and systems experimenter.
9 | don.park@everyonedelivers.com
10 |
11 |
12 |
13 | Thanks to
14 |
15 | Various Nedspace residents - Bussiness Development
16 | Tamara Hill-Tanquist - Web design
17 | Beverly Fields <%= link_to "@beverlyfields", "http://twitter.com/beverlyfields" %>- Web design
18 | Callie Wheeler <%= link_to "@calliesaurus", "http://twitter.com/calliesaurus" %> - Business Development
19 | Brennan Novak <%= link_to "@brennannovak", "http://twitter.com/brennannovak" %>- Web design
20 | Clifton B <%= link_to "@maxticket", "http://twitter.com/maxticket" %> - Web design
21 |
22 |
--------------------------------------------------------------------------------
/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EveryoneDelivers <%= yield :title %>
5 | <%= favicon_link_tag 'wheel.png' %>
6 | <%= stylesheet_link_tag "application" %>
7 | <%= javascript_include_tag "application" %>
8 | <%= csrf_meta_tags %>
9 | <%= render :partial => "layouts/google_maps" %>
10 | <%= yield :header %>
11 |
12 |
13 |
14 | <%# render :partial => "layouts/geode" %>
15 | <%= render :partial => "layouts/header" %>
16 | <% unless params[:controller] == "dashboard" %>
17 | <%= render :partial => "layouts/menubar" %>
18 | <% end %>
19 | <%= render :partial => "layouts/flashmsg" %>
20 |
21 | <%= yield %>
22 |
23 | <%= render :partial => "layouts/footer" %>
24 | <%= render :partial => "layouts/google_analytics" %>
25 | <%= render :partial => "layouts/getsatisfaction" %>
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/models/fee.rb:
--------------------------------------------------------------------------------
1 | class Fee < ActiveRecord::Base
2 | has_many :deliveries
3 |
4 | def apply_form_attributes(params)
5 | return if params.nil?
6 |
7 | if params[:display_price]
8 | self.price_in_cents = (params[:display_price].to_f*100).to_i
9 | end
10 |
11 | if params["delivery_due(1i)"]
12 | time_string = "#{params["delivery_due(1i)"]}-#{params["delivery_due(2i)"]}-#{params["delivery_due(3i)"]} #{params["delivery_due(4i)"]}:#{params["delivery_due(5i)"]}"
13 | delivery_due_time = Time.zone.parse(time_string)
14 | self.delivery_due = delivery_due_time
15 | end
16 |
17 | if params[:payment_method]
18 | self.payment_method = params[:payment_method]
19 | end
20 | end
21 |
22 | def display_price
23 | "%0.2f" % float_price
24 | end
25 |
26 | def float_price
27 | if self.price_in_cents
28 | self.price_in_cents / 100.0
29 | else
30 | 0.0
31 | end
32 | end
33 |
34 | def ok_to_display?
35 | true
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/spec/models/user_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe User do
4 | before(:each) do
5 | valid_attributes = {
6 | :username => "testuser",
7 | :email => "some@user",
8 | :authentication_token => "abc123"
9 | }
10 | @user = User.create!(valid_attributes)
11 | end
12 |
13 | it "should create a new instance given valid attributes" do
14 | @user.should be_valid
15 | end
16 |
17 | it "should clock in a user" do
18 | @user.clock_in!
19 | @user.should be_clocked_in
20 | end
21 |
22 | it "should clock out a user" do
23 | @user.clock_out!
24 | @user.should_not be_clocked_in
25 | end
26 |
27 | it "should tell who can edit this user" do
28 | @user.available_for_edit_by(nil).should be_false
29 | @user.available_for_edit_by(@user).should be_true
30 | end
31 |
32 | it "should find the completed deliveries for a given month" do
33 | @deliveries = @user.accepted_deliveries(2009,10)
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source :rubygems
2 |
3 | gem 'rails', '3.2.11'
4 |
5 | # Bundle edge Rails instead:
6 | # gem 'rails', :git => 'git://github.com/rails/rails.git'
7 |
8 | gem 'pg'
9 |
10 |
11 | # Gems used only for assets and not required
12 | # in production environments by default.
13 | group :assets do
14 | gem 'sass-rails', " ~> 3.2.5"
15 | gem 'coffee-rails', "~> 3.2.2"
16 | gem 'uglifier'
17 | end
18 |
19 | gem 'jquery-rails'
20 | gem 'devise'
21 | gem 'workflow'
22 | gem 'friendly_id', "~> 3.3.3.0"
23 | gem 'loofah'
24 | gem 'uuidtools'
25 | gem 'exception_notification'
26 | gem 'delayed_job_active_record'
27 | gem 'twitter'
28 |
29 | # Use unicorn as the web server
30 | # gem 'unicorn'
31 |
32 | # Deploy with Capistrano
33 | # gem 'capistrano'
34 |
35 | # To use debugger
36 | # gem 'ruby-debug19', :require => 'ruby-debug'
37 |
38 | group :development, :test do
39 | gem 'sqlite3'
40 | # Pretty printed test output
41 | gem 'turn', :require => false
42 | gem 'rspec-rails'
43 | gem 'webrat'
44 | gem 'letter_opener'
45 | end
46 |
47 | group :production do
48 | gem 'unicorn'
49 | end
50 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # This file is copied to spec/ when you run 'rails generate rspec:install'
2 | ENV["RAILS_ENV"] ||= 'test'
3 | require File.expand_path("../../config/environment", __FILE__)
4 | require 'rspec/rails'
5 | require 'webrat'
6 |
7 | # Requires supporting ruby files with custom matchers and macros, etc,
8 | # in spec/support/ and its subdirectories.
9 | Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
10 |
11 | RSpec.configure do |config|
12 | # == Mock Framework
13 | #
14 | # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
15 | #
16 | # config.mock_with :mocha
17 | # config.mock_with :flexmock
18 | # config.mock_with :rr
19 | config.mock_with :rspec
20 |
21 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
22 | config.fixture_path = "#{::Rails.root}/spec/fixtures"
23 |
24 | # If you're not using ActiveRecord, or you'd prefer not to run each of your
25 | # examples within a transaction, remove the following line or assign false
26 | # instead of true.
27 | config.use_transactional_fixtures = true
28 | end
29 |
--------------------------------------------------------------------------------
/app/views/layouts/_header.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
25 |
26 |
27 |
33 |
--------------------------------------------------------------------------------
/spec/controllers/users_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe UsersController do
4 |
5 | before(:each) do
6 | controller.stub!(:authenticate_user!)
7 | controller.stub!(:set_timezone)
8 | @user = mock_model(User)
9 | controller.stub!(:current_user).and_return(@user)
10 | end
11 |
12 | it "should display details for a user" do
13 | user = mock_model(User)
14 | User.should_receive(:find).with(user.id.to_s).and_return(user)
15 | get :show, {:id => user.id}
16 | end
17 |
18 | it "should clock in a user" do
19 | User.should_receive(:find).with(@user.id.to_s).and_return(@user)
20 | @user.should_receive(:add_schedule)
21 | @user.should_receive(:clock_in!)
22 | @user.should_receive(:username).and_return('bob')
23 | get :clock_in, {:id => @user.id}
24 | response.should redirect_to(deliveries_path)
25 | end
26 |
27 | it "should clock out a user" do
28 | User.should_receive(:find).with(@user.id.to_s).and_return(@user)
29 | @user.should_receive(:clock_out!)
30 | @user.should_receive(:username).and_return('bob')
31 | get :clock_out, {:id => @user.id}
32 | response.should redirect_to(deliveries_path)
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/app/models/location.rb:
--------------------------------------------------------------------------------
1 | class Location < ActiveRecord::Base
2 | has_many :deliveries
3 | has_many :sightings
4 | has_many :users, :through => :sightings
5 |
6 | def apply_form_attributes(params)
7 | return if params.nil?
8 | self.name = params[:name]
9 | self.street = params[:address] #todo: google geocode the address
10 | self.latitude = params[:latitude]
11 | self.longitude = params[:longitude]
12 | self.accuracy = params[:accuracy]
13 | end
14 |
15 | def ok_to_display?
16 | street && street.size > 0
17 | end
18 |
19 | def geocode!
20 |
21 | end
22 |
23 | def gmap_static_html(h,w,z)
24 | "http://dev.virtualearth.net/REST/v1/Imagery/Map/Road/?mapSize=#{h},#{w}&pushpin=#{self.latitude},#{self.longitude};33&key=#{SETTINGS["bing"]["maps"]["key"]}"
25 | # "http://maps.google.com/staticmap?center=#{self.latitude},#{self.longitude}&zoom=#{z}&size=#{h}x#{w}&key=#{SETTINGS["google"]["maps"]["key"]}&sensor=false&markers=#{self.latitude},#{self.longitude}"
26 | # "http://staticmap.openstreetmap.de/staticmap.php?center=#{self.latitude},#{self.longitude}&zoom=#{z}&size=#{h}x#{w}&markers=#{self.latitude},#{self.longitude}"
27 | end
28 |
29 | def street_parts
30 | parts = street.split(',',street.count(','))
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/db/migrate/20111006165028_create_delayed_jobs.rb:
--------------------------------------------------------------------------------
1 | class CreateDelayedJobs < ActiveRecord::Migration
2 | def self.up
3 | create_table :delayed_jobs, :force => true do |table|
4 | table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
5 | table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
6 | table.text :handler # YAML-encoded string of the object that will do work
7 | table.text :last_error # reason for last failure (See Note below)
8 | table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
9 | table.datetime :locked_at # Set when a client is working on this object
10 | table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
11 | table.string :locked_by # Who is working on this object (if locked)
12 | table.timestamps
13 | end
14 |
15 | add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
16 | end
17 |
18 | def self.down
19 | drop_table :delayed_jobs
20 | end
21 | end
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | EveryoneDelivers::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send
17 | config.action_mailer.raise_delivery_errors = false
18 | config.action_mailer.delivery_method = :letter_opener
19 |
20 | # Print deprecation notices to the Rails logger
21 | config.active_support.deprecation = :log
22 |
23 | # Only use best-standards-support built into browsers
24 | config.action_dispatch.best_standards_support = :builtin
25 |
26 | # Do not compress assets
27 | config.assets.compress = false
28 |
29 | # Expands the lines which load the assets
30 | config.assets.debug = true
31 | end
32 |
--------------------------------------------------------------------------------
/app/controllers/session_controller.rb:
--------------------------------------------------------------------------------
1 | class SessionController < ApplicationController
2 |
3 | def login_token
4 | user = User.find_by_authentication_token(params[:token])
5 | if user
6 | logger.info("session: #{session.inspect}")
7 | sign_in user
8 | logger.info("session after login: #{session.inspect}")
9 | if session[:anonymous_delivery_id]
10 | delivery = Delivery.find(session[:anonymous_delivery_id])
11 | redirect_to edit_delivery_path(delivery)
12 | else
13 | redirect_to :deliveries
14 | end
15 | else
16 | flash[:error] = "The login link is not valid. Please login with your email address to get a new link."
17 | redirect_to :root
18 | end
19 | end
20 |
21 | def login
22 | # email validation
23 | unless params[:email] && params[:email][/.@./]
24 | flash[:error] = "Please use an email address."
25 | redirect_to :root
26 | return
27 | end
28 | user = User.find_by_email(params[:email])
29 | unless user
30 | logger.info "creating user #{params}"
31 | user = User.create_with_defaults!(:email => params[:email])
32 | end
33 | logger.info "sending login email to #{user.email}"
34 | UserMailer.login_token_email(user).deliver
35 | flash[:notice] = "Login instructions sent to #{user.email}."
36 | redirect_to :deliveries
37 | end
38 |
39 | def logout
40 | reset_session
41 | flash[:notice] = "logged out"
42 | redirect_to :root
43 | end
44 |
45 | end
46 |
--------------------------------------------------------------------------------
/app/controllers/git_hub_controller.rb:
--------------------------------------------------------------------------------
1 | class GitHubController < ApplicationController
2 | protect_from_forgery :except => :commit
3 |
4 | # Example github post
5 | #Processing ApplicationController#commit (for ::ffff:65.74.177.129 at 2009-06-23 06:03:24) [POST]
6 | #Parameters: {"payload"=>"{\"after\": \"801db8c488a37ff9a888a6fc1b5a5fca5290aeab\", \"ref\": \"refs/heads/master\", \"repository\": {\"owner\": {\"name\": \"donpdonp\", \"email\": \"don.park@gmail.com\"}, \"description\": \"crowdsourced services market\", \"forks\": 0, \"name\": \"everyonedelivers\", \"private\": false, \"url\": \"http://github.com/donpdonp/everyonedelivers\", \"fork\": false, \"watchers\": 1, \"homepage\": \"http://everyonedelivers.com\"}, \"before\": \"c4794c51b48bbf72951a8229556365fa67e1bbed\", \"commits\": [{\"modified\": [\"app/controllers/git_hub_controller.rb\"], \"added\": [], \"url\": \"http://github.com/donpdonp/everyonedelivers/commit/801db8c488a37ff9a888a6fc1b5a5fca5290aeab\", \"timestamp\": \"2009-06-22T23:03:14-07:00\", \"message\": \"always test.\", \"removed\": [], \"author\": {\"name\": \"Don Park\", \"email\": \"don@donpark.org\"}, \"id\": \"801db8c488a37ff9a888a6fc1b5a5fca5290aeab\"}]}"}
7 | def commit
8 | gparams = JSON.parse(params["payload"])
9 | logger.info("github params: #{gparams}")
10 | Journal.create({:note => "Website code updated to #{gparams["after"]}"})
11 | cmd = Rails.root+"github-pull.sh"
12 | logger.info("github commit: #{cmd}")
13 | out = shell(cmd)
14 | logger.info("github pull output: #{out}")
15 | render :nothing => true
16 | end
17 |
18 | # so we can mock this in a test
19 | def shell(cmd)
20 | `/bin/sh #{cmd}`
21 | end
22 |
23 | end
24 |
--------------------------------------------------------------------------------
/app/views/deliveries/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 | Deliver an item and earn the bounty!
3 |
4 |
5 |
6 |
7 |
8 | Available delivery people
9 |
10 |
11 |
12 | <% @clocked_ins.each do |user| %>
13 | <% schedule = user.schedules.last %>
14 |
15 |
16 | <%= link_to h(user.username), user %>
17 |
18 |
19 | <%= schedule.street1 %> and <%= schedule.street2 %>
20 |
21 |
22 |
23 |
24 | <% end %>
25 |
26 |
27 |
28 |
29 | <% if user_signed_in? %>
30 | <% clockedin = current_user.clocked_in? %>
31 |
">
32 | Clocked
33 | <%= clockedin ? "In" : "Out"%>
34 |
35 | <% if clockedin %>
36 | <%= form_tag(clockedin ? clock_out_user_path(current_user) : clock_in_user_path(current_user)) do %>
37 | <%= submit_tag "Clock #{clockedin ? "OUT" : "IN"}" %>
38 | <% end %>
39 | <% else %>
40 | <%= link_to 'Clock in', schedule_user_path(current_user) %>
41 | <% end %>
42 |
43 | <% end %>
44 |
45 |
46 |
47 | <% @delivery_groups.each do |group| %>
48 | <%= render :partial => 'deliveries/list', :locals => {:timedesc => group.first, :deliveries => group.last} %>
49 | <% end %>
50 |
51 |
52 | <% if user_signed_in? %>
53 | <% else %>
54 | Login to create or accept a delivery.
55 | <% end %>
56 |
--------------------------------------------------------------------------------
/app/views/layouts/_geode.html.erb:
--------------------------------------------------------------------------------
1 |
45 |
--------------------------------------------------------------------------------
/app/views/users/edit.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
Edit User
3 | <%= form_for @user do |f| %>
4 |
5 | Identity
6 | <%= f.label :username, "username:" %>
7 | <%= f.text_field :username, :size => 40 %>
8 | <%= f.label :email, "email:" %>
9 | <%= @user.errors[:email].join %>
10 | <%= f.text_field :email, :size => 40 %>
11 |
12 |
13 | Internationalization
14 | <%= f.label :time_zone, "time zone:" %>
15 | <%= @user.errors[:time_zone].join %>
16 | <%= f.time_zone_select :time_zone, ActiveSupport::TimeZone.us_zones, :include_blank => true %>
17 | <% if @user.time_zone.blank? %>
18 |
33 | <% end %>
34 |
35 | <%= f.label :display_measurement, "units:" %>
36 | <%= @user.errors[:display_measurement].join %>
37 | <%= f.select :display_measurement, [["Imperial (pounds/inches)","imperial"],["Metric (grams/meters)","metric"]] %>
38 |
39 |
40 | Notification
41 | <%= f.label :email_on_new_listing, "Send an email for each new delivery listing:" %>
42 | <%= f.check_box :email_on_new_listing %>
43 |
44 |
45 | <%= f.submit %>
46 | <% end %>
47 |
48 |
--------------------------------------------------------------------------------
/app/models/package.rb:
--------------------------------------------------------------------------------
1 | class Package < ActiveRecord::Base
2 | has_one :delivery
3 |
4 | def apply_form_attributes(params)
5 | return if params.nil?
6 |
7 | if params[:description]
8 | self.description = params[:description]
9 | end
10 | if params[:height]
11 | self.height_in_meters = inches_to_meters(params[:height])
12 | end
13 | if params[:width]
14 | self.width_in_meters = inches_to_meters(params[:width])
15 | end
16 | if params[:depth]
17 | self.depth_in_meters = inches_to_meters(params[:depth])
18 | end
19 | if params[:weight]
20 | self.weight_in_grams = ounces_to_grams(params[:weight])
21 | end
22 | if params[:display_price]
23 | self.price_in_cents = (params[:display_price].to_f*100).to_i
24 | end
25 | end
26 |
27 | def ok_to_display?
28 | description && description.size > 0
29 | end
30 |
31 | def has_dimensions?
32 | height_in_meters && width_in_meters && depth_in_meters
33 | end
34 |
35 | def height
36 | "%0.1f" % meters_to_inches(self.height_in_meters)
37 | end
38 |
39 | def width
40 | "%0.1f" % meters_to_inches(self.width_in_meters)
41 | end
42 |
43 | def depth
44 | "%0.1f" % meters_to_inches(self.depth_in_meters)
45 | end
46 |
47 | def weight
48 | "%0.1f" % grams_to_ounces(self.weight_in_grams)
49 | end
50 |
51 | def inches_to_meters(inch_s)
52 | inch_s.to_f*0.0254
53 | end
54 |
55 | def meters_to_inches(meters)
56 | meters/0.0254
57 | end
58 |
59 | def ounces_to_grams(ounces_s)
60 | ounces_s.to_f*28.3495
61 | end
62 |
63 | def grams_to_ounces(meters)
64 | weight_in_grams/28.3495
65 | end
66 |
67 | def display_price
68 | "%0.2f" % float_price
69 | end
70 |
71 | def float_price
72 | if self.price_in_cents
73 | self.price_in_cents / 100.0
74 | else
75 | 0.0
76 | end
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/app/views/users/schedule.html.erb:
--------------------------------------------------------------------------------
1 | <% last_schedule = current_user.schedules.last %>
2 |
11 |
12 |
13 |
14 |
15 | Clock-In Position
16 |
17 |
18 |
19 |
20 |
21 |
28 |
29 | <%= form_tag({:action => :clock_in}, {:id => "schedule_add"}) do %>
30 |
36 |
37 |
38 |
39 |
40 | Drag the map marker to your current location.
41 | The nearest intersection is used for
42 | your privacy.
43 |
44 | Nearest Intersection: (waiting for map)
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | <%= submit_tag "Clock In"%>
54 | <% end %>
55 |
56 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | EveryoneDelivers::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Configure static asset server for tests with Cache-Control for performance
11 | config.serve_static_assets = true
12 | config.static_cache_control = "public, max-age=3600"
13 |
14 | # Log error messages when you accidentally call methods on nil
15 | config.whiny_nils = true
16 |
17 | # Show full error reports and disable caching
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Use SQL instead of Active Record's schema dumper when creating the test database.
33 | # This is necessary if your schema can't be completely dumped by the schema dumper,
34 | # like if you have constraints or database-specific column types
35 | # config.active_record.schema_format = :sql
36 |
37 | # Print deprecation notices to the stderr
38 | config.active_support.deprecation = :stderr
39 |
40 | # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets
41 | config.assets.allow_debugging = true
42 | end
43 |
--------------------------------------------------------------------------------
/spec/models/delivery_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe Delivery do
4 | fixtures :deliveries
5 |
6 | before(:each) do
7 | @valid_attributes = {
8 | }
9 | end
10 |
11 | it "should create a new instance given valid attributes" do
12 | Delivery.create!(@valid_attributes)
13 | end
14 |
15 | it "should find deliveries at most X hours old" do
16 | time = Time.parse("2009-01-01 12:45 UTC")
17 | deliveries = Delivery.find_at_most_hours_old(1,time)
18 | deliveries.size.should == 2
19 | # return in time-sorted order
20 | deliveries.first.created_at.should > deliveries.last.created_at
21 | end
22 |
23 | it "should find deliveries between X and Y X hours old" do
24 | time = Time.parse("2009-01-01 12:45 UTC")
25 | deliveries = Delivery.find_between_hours_old(1, 2, time)
26 | deliveries.size.should == 2
27 | # return in time-sorted order
28 | deliveries.first.created_at.should > deliveries.last.created_at
29 | end
30 |
31 | it "should find deliveries more than X hours old" do
32 | time = Time.parse("2009-01-01 12:45 UTC")
33 | deliveries = Delivery.find_more_than_hours_old(4, time)
34 | deliveries.size.should == 2
35 | # return in time-sorted order
36 | deliveries.first.created_at.should > deliveries.last.created_at
37 | end
38 |
39 | it "should start with the building state" do
40 | delivery = Delivery.new
41 | delivery.building?.should be_true
42 | end
43 |
44 | it "test if the delivery data is complete" do
45 | delivery = Delivery.new
46 | delivery.should_receive(:building?).and_return(true)
47 | delivery.should_receive(:ok_to_display?).and_return(true)
48 | delivery.should_receive(:ready!).and_return(true)
49 | delivery.check_for_completeness
50 | end
51 |
52 | it "journal and send email when ready" do
53 | delivery = Delivery.new
54 | delivery.should_receive(:email_notify_users)
55 | delivery.ready!
56 | end
57 |
58 | end
59 |
--------------------------------------------------------------------------------
/app/views/deliveries/_single.html.erb:
--------------------------------------------------------------------------------
1 | <% if delivery.ok_to_display? %>
2 | " style="margin-bottom: 10px;">
3 |
4 |
">
5 |
6 | <% if delivery.delivered? %>
7 | Delivered by
8 | <%= link_to h(delivery.delivering_user.username), delivery.delivering_user %>
9 | <% else %>
10 | <%= render :partial => "deliveries/single_due", :locals => {:fee => delivery.fee} %>
11 | <% end %>
12 |
13 | <%= link_to h(truncate(delivery.package.description, :length => 45)), delivery_path(delivery) %>
14 |
15 |
16 |
17 |
18 | Bounty
19 |
20 |
21 | $<%= delivery.fee.display_price %>
22 |
23 |
24 |
25 |
26 |
27 | <%= render :partial => "deliveries/single_address_map",
28 | :locals => {:location => delivery.start_location,
29 | :direction => "From:", :to => nil} %>
30 |
31 |
32 |
33 | <%= render :partial => "deliveries/single_address_map",
34 | :locals => {:location => delivery.end_location,
35 | :direction => "To: ",
36 | :to => delivery.listing_user} %>
37 |
38 |
39 |
40 | <% if delivery.available_for_delivery_by(current_user) %>
41 |
42 | <%= form_for delivery, :url => confirm_delivery_path(delivery),
43 | :html => {:method => :put} do |f| %>
44 | <%= f.submit 'I can make this delivery' %>
45 | <% end %>
46 |
47 | <% end %>
48 |
49 | <% end %>
50 |
--------------------------------------------------------------------------------
/app/controllers/users_controller.rb:
--------------------------------------------------------------------------------
1 | class UsersController < ApplicationController
2 | before_filter :authenticate_user!, :except => [:show]
3 | protect_from_forgery :except => :update_location
4 |
5 | def show
6 | @user = User.find(params[:id])
7 | end
8 |
9 | def edit
10 | @user = User.find(params[:id])
11 | @user.soft_validate
12 | unless @user && @user.available_for_edit_by(current_user)
13 | flash[:error] = "Not allowed to edit #{params[:id]}"
14 | redirect_to root_path
15 | end
16 | end
17 |
18 | def update
19 | @user = User.find(params[:id])
20 | if current_user == @user
21 | @user.apply_form_attributes(params[:user])
22 | begin
23 | @user.save!
24 | flash[:notice] = "Profile updated"
25 | rescue ActiveRecord::RecordInvalid => e
26 | flash[:error] = "#{e}"
27 | end
28 | redirect_to @user
29 | else
30 | flash[:error] = "Permission denied"
31 | redirect_to root_path;
32 | end
33 | end
34 |
35 | def update_location
36 | @user = User.find(params[:id])
37 | if current_user == @user
38 | location = Location.new
39 | location.apply_form_attributes(params)
40 | @user.locations << location
41 | end
42 | render :nothing => true
43 | end
44 |
45 | def clock_in
46 | @user = User.find(params[:id])
47 | if current_user == @user
48 | schedule = Schedule.new
49 | schedule.apply_form_fields(params[:schedule])
50 | @user.schedules << schedule
51 | @user.clock_in!
52 | flash[:notice] = "#{@user.username} is clocked in for one hour! Good luck."
53 | else
54 | flash[:error] = "Not authorized to clock in #{@user.username}"
55 | end
56 | redirect_to deliveries_path
57 | end
58 |
59 | def clock_out
60 | @user = User.find(params[:id])
61 | if current_user == @user
62 | @user.clock_out!
63 | flash[:notice] = "#{@user.username} has been clocked out."
64 | else
65 | flash[:error] = "Not authorized to clock out #{@user.username}"
66 | end
67 | redirect_to deliveries_path
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | require 'rails/all'
4 |
5 | if defined?(Bundler)
6 | # If you precompile assets before deploying to production, use this line
7 | Bundler.require *Rails.groups(:assets => %w(development test))
8 | # If you want your assets lazily compiled in production, use this line
9 | # Bundler.require(:default, :assets, Rails.env)
10 | end
11 |
12 | module EveryoneDelivers
13 | class Application < Rails::Application
14 | # Settings in config/environments/* take precedence over those specified here.
15 | # Application configuration should go into files in config/initializers
16 | # -- all .rb files in that directory are automatically loaded.
17 |
18 | # Custom directories with classes and modules you want to be autoloadable.
19 | # config.autoload_paths += %W(#{config.root}/extras)
20 |
21 | # Only load the plugins named here, in the order given (default is alphabetical).
22 | # :all can be used as a placeholder for all plugins not explicitly named.
23 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24 |
25 | # Activate observers that should always be running.
26 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27 |
28 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30 | # config.time_zone = 'Central Time (US & Canada)'
31 |
32 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34 | # config.i18n.default_locale = :de
35 |
36 | # Configure the default encoding used in templates for Ruby 1.9.
37 | config.encoding = "utf-8"
38 |
39 | # Configure sensitive parameters which will be filtered from the log file.
40 | config.filter_parameters += [:password]
41 |
42 | # Enable the asset pipeline
43 | config.assets.enabled = true
44 |
45 | # Version of your assets, change this if you want to expire all your assets
46 | config.assets.version = '1.0'
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/views/deliveries/show.html.erb_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe "/deliveries/show.html.erb" do
4 | before(:each) do
5 | view.stub!(:user_signed_in?).and_return(false)
6 | user = mock_model(User, :display_measurement => "metric")
7 | view.stub!(:current_user).and_return(user)
8 | end
9 |
10 | it "should render a delivery in the building state" do
11 | # Setup an empty delivery
12 | location = mock("Location", :latitude => 1, :longitude => 2,
13 | :street => "123 main")
14 | delivery = mock_model(Delivery, :start_location => location, :end_location => location)
15 | delivery.should_receive(:created_at).and_return(Time.now)
16 | delivery.should_receive(:listing_user)
17 | delivery.should_receive(:package).twice
18 | fee = mock_model(Fee, :delivery_due => Time.now,
19 | :display_price => "1",
20 | :payment_method => "cash")
21 | delivery.should_receive(:fee).and_return(fee)
22 | delivery.should_receive(:delivering_user)
23 | delivery.should_receive(:available_for_edit_by)
24 | delivery.should_receive(:start_end_distance)
25 | delivery.should_receive(:waiting?).and_return(false)
26 | assign(:delivery, delivery)
27 |
28 | render
29 | end
30 |
31 | it "should render a delivery with waiting state" do
32 | current_user = mock_model(User)
33 | view.should_receive(:current_user).twice.and_return(current_user)
34 | # Setup an empty delivery
35 | delivery = mock_model(Delivery)
36 | delivery.should_receive(:created_at).and_return(Time.now)
37 | user = mock_model(User)
38 | user.should_receive(:username).and_return("Bob")
39 | delivery.should_receive(:listing_user).and_return(user)
40 | delivery.should_receive(:package)
41 | delivery.should_receive(:start_location)
42 | delivery.should_receive(:start_location)
43 | delivery.should_receive(:start_location)
44 | delivery.should_receive(:end_location)
45 | delivery.should_receive(:fee)
46 | delivery.should_receive(:delivering_user)
47 | delivery.should_receive(:start_end_distance)
48 | delivery.should_receive(:available_for_delivery_by).with(current_user).and_return(false)
49 | delivery.should_receive(:available_for_edit_by).with(current_user).and_return(false)
50 | delivery.should_receive(:waiting?).and_return(true)
51 | delivery.should_receive(:comments).and_return([])
52 | assign(:delivery, delivery)
53 |
54 | render
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | EveryoneDelivers::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 |
11 | # Disable Rails's static asset server (Apache or nginx will already do this)
12 | config.serve_static_assets = false
13 |
14 | # Compress JavaScripts and CSS
15 | config.assets.compress = true
16 |
17 | # Don't fallback to assets pipeline if a precompiled asset is missed
18 | config.assets.compile = false
19 |
20 | # Generate digests for assets URLs
21 | config.assets.digest = true
22 |
23 | # Defaults to Rails.root.join("public/assets")
24 | # config.assets.manifest = YOUR_PATH
25 |
26 | # Specifies the header that your server uses for sending files
27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29 |
30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31 | # config.force_ssl = true
32 |
33 | # See everything in the log (default is :info)
34 | # config.log_level = :debug
35 |
36 | # Use a different logger for distributed setups
37 | # config.logger = SyslogLogger.new
38 |
39 | # Use a different cache store in production
40 | # config.cache_store = :mem_cache_store
41 |
42 | # Enable serving of images, stylesheets, and JavaScripts from an asset server
43 | # config.action_controller.asset_host = "http://assets.example.com"
44 |
45 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
46 | # config.assets.precompile += %w( search.js )
47 |
48 | # Disable delivery errors, bad email addresses will be ignored
49 | # config.action_mailer.raise_delivery_errors = false
50 |
51 | # Enable threaded mode
52 | # config.threadsafe!
53 |
54 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
55 | # the I18n.default_locale when a translation can not be found)
56 | config.i18n.fallbacks = true
57 |
58 | # Send deprecation notices to registered listeners
59 | config.active_support.deprecation = :notify
60 | end
61 |
62 | ActionMailer::Base.smtp_settings = {:address=>"localhost",
63 | :port=>25,
64 | :domain=>"localhost.localdomain",
65 | :enable_starttls_auto=>false}
66 |
67 |
--------------------------------------------------------------------------------
/app/views/deliveries/confirm.html.erb:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 | Delivery #<%= @delivery.id %> "<%= @delivery.package.description %>"
16 |
17 |
18 | Are you sure you can make this delivery?
19 |
20 |
21 |
22 |
26 |
27 |
28 |
Plan
29 |
30 |
31 | Step 1: Travel to
32 |
<%= @delivery.start_location.street %>
33 |
34 | Step 2: Acquire item, cost: $<%=@delivery.package.display_price%>
35 |
36 |
37 |
38 | Step 3:
39 |
40 |
41 |
42 | Travel to
43 | <%= @delivery.end_location.street %>
44 | Distance: in
45 | <%= distance_of_time_in_words_to_now(@delivery.fee.delivery_due) %>
46 |
47 |
48 |
49 | Step 4: Give item to <%= link_to_user(@delivery.listing_user) %>
50 |
51 | Step 5: Collect $<%=@delivery.package.display_price%> + $<%= @delivery.fee.display_price %> = $<%= @delivery.display_retail_plus_bounty %> paid with <%= @delivery.fee.payment_method %>
52 |
53 |
54 |
55 |
56 | <% if @delivery.fee.payment_method == "visa" %>
57 |
58 | For VISA payments you must be signed up with squareup.com and
59 | have already received the VISA Card reader in the mail. Then you can process a VISA card
60 | at the same time you make the delivery. Accept this delivery only if you are setup
61 | to use Square.
62 |
63 | <% end %>
64 |
65 |
66 |
67 | <%= form_for @delivery, :url => accept_delivery_path(@delivery), :html => {:method => :put} do |f| %>
68 | <%= f.submit 'Yes I accept' %>
69 | <% end %>
70 |
71 |
72 |
73 | <%= form_tag delivery_path(@delivery), :method => :get do %>
74 | <%= submit_tag 'No Thanks' %>
75 | <% end %>
76 |
77 |
--------------------------------------------------------------------------------
/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at http://github.com/plataformatec/devise/wiki/I18n
2 |
3 | en:
4 | errors:
5 | messages:
6 | expired: "has expired, please request a new one"
7 | not_found: "not found"
8 | already_confirmed: "was already confirmed, please try signing in"
9 | not_locked: "was not locked"
10 | not_saved:
11 | one: "1 error prohibited this %{resource} from being saved:"
12 | other: "%{count} errors prohibited this %{resource} from being saved:"
13 |
14 | devise:
15 | failure:
16 | already_authenticated: 'You are already signed in.'
17 | unauthenticated: 'You need to sign in or sign up before continuing.'
18 | unconfirmed: 'You have to confirm your account before continuing.'
19 | locked: 'Your account is locked.'
20 | invalid: 'Invalid email or password.'
21 | invalid_token: 'Invalid authentication token.'
22 | timeout: 'Your session expired, please sign in again to continue.'
23 | inactive: 'Your account was not activated yet.'
24 | sessions:
25 | signed_in: 'Signed in successfully.'
26 | signed_out: 'Signed out successfully.'
27 | passwords:
28 | send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
29 | updated: 'Your password was changed successfully. You are now signed in.'
30 | updated_not_active: 'Your password was changed successfully.'
31 | send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
32 | confirmations:
33 | send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
34 | send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
35 | confirmed: 'Your account was successfully confirmed. You are now signed in.'
36 | registrations:
37 | signed_up: 'Welcome! You have signed up successfully.'
38 | inactive_signed_up: 'You have signed up successfully. However, we could not sign you in because your account is %{reason}.'
39 | updated: 'You updated your account successfully.'
40 | destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
41 | reasons:
42 | inactive: 'inactive'
43 | unconfirmed: 'unconfirmed'
44 | locked: 'locked'
45 | unlocks:
46 | send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
47 | unlocked: 'Your account was successfully unlocked. You are now signed in.'
48 | send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
49 | omniauth_callbacks:
50 | success: 'Successfully authorized from %{kind} account.'
51 | failure: 'Could not authorize you from %{kind} because "%{reason}".'
52 | mailer:
53 | confirmation_instructions:
54 | subject: 'Confirmation instructions'
55 | reset_password_instructions:
56 | subject: 'Reset password instructions'
57 | unlock_instructions:
58 | subject: 'Unlock Instructions'
59 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | class User < ActiveRecord::Base
2 | has_many :openidentities, :dependent => :destroy
3 | has_many :sightings
4 | has_many :locations, :through => :sightings
5 | has_many :schedules
6 | validates_presence_of :username, :email, :authentication_token
7 | validates_uniqueness_of :username, :email
8 |
9 | after_create :journal_on_create
10 |
11 | scope :clocked_ins, :conditions => "clocked_in is not null"
12 |
13 | has_friendly_id :username, :use_slug => true
14 |
15 | devise :token_authenticatable
16 |
17 | def self.create_with_defaults!(attributes)
18 | user = User.new(attributes)
19 | if attributes[:username].nil?
20 | user.username = pick_username(user.email)
21 | end
22 | user.display_measurement = "imperial"
23 | user.email_on_new_listing = false
24 | user.authentication_token = UUIDTools::UUID.random_create.to_s
25 | user.save!
26 | user
27 | end
28 |
29 | def apply_form_attributes(params)
30 | return if params.nil?
31 |
32 | if params[:email]
33 | self.email = params[:email]
34 | end
35 |
36 | if params[:username]
37 | self.username = params[:username]
38 | end
39 |
40 | if params[:time_zone]
41 | self.time_zone = params[:time_zone]
42 | end
43 |
44 | if params[:display_measurement]
45 | self.display_measurement = params[:display_measurement]
46 | end
47 |
48 | if params[:email_on_new_listing]
49 | self.email_on_new_listing = params[:email_on_new_listing]
50 | end
51 | end
52 |
53 | def available_for_edit_by(user)
54 | self == user
55 | end
56 |
57 | def openid
58 | self.openidentities.first
59 | end
60 |
61 | def journal_on_create
62 | Journal.create({:delivery => nil, :user => self, :note => "New User"})
63 | end
64 |
65 | def clock_in!
66 | update_attribute :clocked_in, Time.now
67 | Journal.create({:delivery => nil, :user => self, :note => "Clocked In"})
68 | end
69 |
70 | def clock_out!
71 | update_attribute :clocked_in, nil
72 | Journal.create({:delivery => nil, :user => self, :note => "Clocked Out"})
73 | end
74 |
75 | def soft_validate
76 | # suggest to the user that field be filled in.
77 | if time_zone.blank?
78 | errors.add(:time_zone, "Please set a timezone")
79 | end
80 | if email.blank?
81 | errors.add(:email, "Please provide an email address")
82 | end
83 | if display_measurement.blank?
84 | errors.add(:display_measurement, "Please choose your units of measurement")
85 | end
86 | end
87 |
88 | def listed_deliveries
89 | deliveries = Delivery.all(:conditions => {:listing_user_id => self.id}, :order => "created_at desc, delivering_user_id asc")
90 | deliveries.select{|d| d.ok_to_display? }
91 | end
92 |
93 | def accepted_deliveries(year=nil, month=nil)
94 | if year && month
95 | mark = Time.parse("#{year}-#{month}-01")
96 | conditions = ["delivering_user_id = ? and accepted_at >= ? and accepted_at < ?", self.id, mark, mark.next_month ]
97 | else
98 | conditions = {:delivering_user_id => self.id}
99 | end
100 | deliveries = Delivery.all(:conditions => conditions, :order => "created_at desc, delivering_user_id asc")
101 | deliveries.select{|d| d.ok_to_display? }
102 | end
103 |
104 | def self.pick_username(email)
105 | username = email.split('@')[0]
106 | if User.find_by_username(username)
107 | logger.info("found! addin number")
108 | username += (rand(89999)+10000).to_s
109 | end
110 | logger.info("picked: #{username}")
111 | username
112 | end
113 | end
114 |
--------------------------------------------------------------------------------
/app/assets/javascripts/delivery_edit.js:
--------------------------------------------------------------------------------
1 | function formvalidation(event) {
2 | if($('#from_latitude').val().length > 0) {
3 | if($('#to_latitude').val().length > 0) {
4 | // Both points are verified. compute the distance
5 | p1 = new google.maps.LatLng($('#from_latitude').val(),$('#from_longitude').val());
6 | p2 = new google.maps.LatLng($('#to_latitude').val(),$('#to_longitude').val());
7 | $('#delivery_start_end_distance').val(""+distanceBetweenPoints(p1,p2));
8 | return;
9 | } else {
10 | invalidate_to();
11 | alert("Please correct the To address.");
12 | }
13 | } else {
14 | invalidate_from();
15 | alert("Please correct the From address.");
16 | }
17 | return false;
18 | }
19 |
20 | function invalidate_from() {
21 | $('#from_latitude').val("");
22 | $('#from_longitude').val("");
23 | /*$('#from_address_msg').html("Validating.");*/
24 | $('#from_address_label').addClass('error');
25 | }
26 |
27 | function invalidate_to() {
28 | $('#to_latitude').val("");
29 | $('#to_longitude').val("");
30 | /*$('#to_address_msg').html("Validating.")*/
31 | $('#to_address_label').addClass('error');
32 | }
33 |
34 | function validate_from(latlng) {
35 | $('#from_address_map').html(static_map(latlng,150,70,15));
36 | $('#from_address_label').removeClass('error');
37 | }
38 |
39 | function validate_to(latlng) {
40 | $('#to_address_map').html(static_map(latlng,150,70,15));
41 | $('#to_address_label').removeClass('error');
42 | }
43 |
44 | function prevalidate_from() {
45 | var lat = $('#from_latitude').val();
46 | var lng = $('#from_longitude').val();
47 | if(lat.length > 0) {
48 | var latlng = new google.maps.LatLng(lat,lng);
49 | validate_from(latlng);
50 | }
51 | }
52 |
53 | function prevalidate_to() {
54 | var lat = $('#to_latitude').val();
55 | var lng = $('#to_longitude').val();
56 | if(lat.length > 0) {
57 | var latlng = new google.maps.LatLng(lat,lng);
58 | validate_to(latlng);
59 | }
60 | }
61 |
62 | function geocallback_from(results, status) {
63 | if(status == "OK") {
64 | var gLatLng = results[0].geometry.location;
65 | $('#from_latitude').val(""+gLatLng.lat());
66 | $('#from_longitude').val(""+gLatLng.lng());
67 | validate_from(gLatLng);
68 | } else {
69 | invalidate_from();
70 | }
71 | }
72 |
73 | function geocallback_to(results, status) {
74 | if(status == "OK") {
75 | var gLatLng = results[0].geometry.location;
76 | $('#to_latitude').val(""+gLatLng.lat());
77 | $('#to_longitude').val(""+gLatLng.lng());
78 | validate_to(gLatLng);
79 | } else {
80 | invalidate_to();
81 | }
82 | }
83 |
84 | function static_map(gLatLng, h, w, zoom) {
85 | var map_url = " ";
88 | console.log(map_url)
89 | return map_url;
90 | }
91 |
92 | function address_from_validate_click(event) {
93 | var geocoder = new google.maps.Geocoder();
94 | var request = { address : $('#from_address').val() }
95 | geocoder.geocode(request, geocallback_from);
96 | event.preventDefault();
97 | }
98 |
99 | function address_to_validate_click(event) {
100 | var geocoder = new google.maps.Geocoder();
101 | var request = { address : $('#to_address').val() }
102 | geocoder.geocode(request, geocallback_to);
103 | event.preventDefault();
104 | }
105 |
106 | function distanceBetweenPoints(p1, p2) {
107 | if (!p1 || !p2) {
108 | return 0;
109 | }
110 |
111 | var R = 6371000; // Radius of the Earth in m
112 | var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
113 | var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
114 | var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
115 | Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
116 | Math.sin(dLon / 2) * Math.sin(dLon / 2);
117 | var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
118 | var d = R * c;
119 | return d;
120 | }
121 |
122 |
123 | function setup() {
124 | $('#from_address').blur(address_from_validate_click)
125 | /*$('#from_address_validate').click(address_from_validate_click);*/
126 | $('#to_address').blur(address_to_validate_click)
127 | /*$('#to_address_validate').click(address_to_validate_click);*/
128 | $('.edit_delivery').submit(formvalidation);
129 | $('#from_address').change(invalidate_from);
130 | $('#to_address').change(invalidate_to);
131 | prevalidate_from();
132 | prevalidate_to();
133 | }
134 |
135 |
136 |
--------------------------------------------------------------------------------
/app/models/delivery.rb:
--------------------------------------------------------------------------------
1 | class Delivery < ActiveRecord::Base
2 |
3 | include Workflow
4 | include ActionView::Helpers::DateHelper
5 |
6 | belongs_to :fee
7 | belongs_to :package
8 | belongs_to :start_location, :class_name => "Location"
9 | belongs_to :end_location, :class_name => "Location"
10 | belongs_to :listing_user, :class_name => "User"
11 | belongs_to :delivering_user, :class_name => "User"
12 | has_many :comments
13 |
14 | after_create :journal_on_create
15 | after_save :check_for_completeness
16 |
17 | workflow do
18 | state :building do
19 | event :ready, :transitions_to => :waiting
20 | end
21 | state :waiting do
22 | event :accept, :transitions_to => :accepted
23 | end
24 | state :accepted do
25 | event :deliver, :transitions_to => :delivered
26 | end
27 | state :delivered
28 | end
29 |
30 | scope :buildings, :conditions => { :workflow_state => "building" }
31 | scope :waitings, :conditions => { :workflow_state => "waiting" }
32 |
33 | def check_for_completeness
34 | if building? && ok_to_display?
35 | ready!
36 | end
37 | end
38 |
39 | def ready
40 | Journal.create({:delivery => self, :user => listing_user, :note => "Emailed delivery update notice"})
41 | email_notify_users # todo: make job
42 | TwitterJob.new(ready_message).send_later(:perform)
43 | end
44 |
45 | def email_notify_users
46 | User.all(:conditions => {:email_on_new_listing => true}).each do |user|
47 | DeliveryMailer.updated(self, user).deliver
48 | end
49 | end
50 |
51 | def apply_form_attributes(params)
52 | return if params.nil?
53 | self.start_end_distance = params[:start_end_distance].to_i
54 | end
55 |
56 | def ok_to_display?
57 | !!(fee && fee.ok_to_display? && package && package.ok_to_display? && start_location && start_location.ok_to_display? && end_location && end_location.ok_to_display? && listing_user)
58 | end
59 |
60 | def overdue?(time = Time.now)
61 | if fee
62 | fee.delivery_due < time
63 | else
64 | true
65 | end
66 | end
67 |
68 | def delivered?
69 | !!delivering_user
70 | end
71 |
72 | def available_for_delivery_by(user)
73 | user && user != listing_user && delivering_user.nil? && !overdue? && !featured
74 | end
75 |
76 | def available_for_edit_by(user)
77 | user && user == listing_user
78 | end
79 |
80 | def journal_on_create
81 | Journal.create({:delivery => self, :user => self.listing_user, :note => "Building Delivery"})
82 | end
83 |
84 | def deliverer(user)
85 | self.delivering_user = user
86 | self.accepted_at = Time.now
87 | Journal.create({:delivery => self, :user => user, :note => "Accepted delivery."})
88 | end
89 |
90 | def display_retail_plus_bounty
91 | "%0.2f" % ((self.package.price_in_cents + self.fee.price_in_cents) / 100.0)
92 | end
93 |
94 | def listing_fee_in_cents
95 | if self.fee.price_in_cents >= 300
96 | 0.50
97 | else
98 | 0.0
99 | end
100 | end
101 |
102 | def display_listing_fee
103 | "%0.2f" % (listing_fee_in_cents/100.0)
104 | end
105 |
106 | def ready_message
107 | url = "#{SETTINGS["shortname"]["url"]}/#{id}"
108 | due = "Due in #{distance_of_time_in_words_to_now(fee.delivery_due)}."
109 | "\"#{package.description[0,136-url.length-due.length]}\" #{due} #{url}"
110 | end
111 |
112 | def self.find_at_most_hours_old(hours, time=Time.zone.now)
113 | start = hours.hours.ago(time)
114 | stop = time
115 | find_between_times(start,stop)
116 | end
117 |
118 | def self.find_more_than_hours_old(hours, time=Time.zone.now)
119 | start = Time.zone.at(0)
120 | stop = hours.hours.ago(time)
121 | find_between_times(start,stop)
122 | end
123 |
124 | def self.find_between_hours_old(smaller, larger, time=Time.zone.now)
125 | start = larger.hours.ago(time)
126 | stop = smaller.hours.ago(time)
127 | find_between_times(start,stop)
128 | end
129 |
130 | def self.find_between_times(start,stop)
131 | all(:conditions => ["created_at >= ? and created_at < ?", start, stop], :order => "created_at desc, delivering_user_id asc")
132 | end
133 |
134 | def self.find_due_after_time(due_time)
135 | joins(:fee).
136 | where(["fees.delivery_due >= ?", due_time]).
137 | order("fees.delivery_due asc")
138 | end
139 |
140 | def self.find_due_between_times(start,stop)
141 | joins(:fee).
142 | where(["fees.delivery_due >= ? and fees.delivery_due < ?", start, stop]).
143 | order("fees.delivery_due desc")
144 | end
145 | end
146 |
--------------------------------------------------------------------------------
/app/assets/javascripts/gmaps.js.erb:
--------------------------------------------------------------------------------
1 | function mapinitialize(start_lat, start_long, draggable) {
2 | var lat, lng, zoom;
3 | if(start_lat) {
4 | lat = start_lat
5 | lng = start_long
6 | zoom = 12
7 | } else {
8 | lat = 45
9 | lng = -120
10 | zoom = 4
11 | }
12 | var start = new google.maps.LatLng(lat, lng);
13 | var map = new google.maps.Map(document.getElementById("gmap"),
14 | {mapTypeId: google.maps.MapTypeId.ROADMAP,
15 | center: start,
16 | zoom: zoom});
17 | marker_start = new google.maps.Marker({position:start,
18 | draggable: draggable});
19 | if(draggable) {
20 | google.maps.event.addListener(marker_start, 'dragend', function(event) {mark_dragged(event.latLng)});
21 | }
22 |
23 | marker_start.setMap(map);
24 | return map;
25 | }
26 |
27 | function map_destination(map, end_lat, end_long, units) {
28 | var start = map.getCenter();
29 | var end = new google.maps.LatLng(end_lat, end_long);
30 | var bounds = new google.maps.LatLngBounds();
31 | bounds.extend(start);
32 | bounds.extend(end);
33 | map.fitBounds(bounds);
34 |
35 | var marker_end = new google.maps.Marker({position:end});
36 | marker_end.setMap(map);
37 |
38 |
39 | var directions = new google.maps.DirectionsService();
40 | var request = { origin : start,
41 | destination : end,
42 | travelMode : google.maps.DirectionsTravelMode.DRIVING,
43 | unitSystem: units };
44 | directions.route(request, show_directions_callback_builder(map));
45 | }
46 |
47 | function map_riders(map, riders) {
48 | var bounds = map.getBounds()
49 | for(var i=0,len=riders.length; i",
66 | {success:intersection_update, dataType: "json"})
67 | }
68 |
69 | function intersection_update(data, status) {
70 | if (status == "success") {
71 | var streetname, msg;
72 | if (data.intersection) {
73 | msg = ""+data.intersection.street1+" " +
74 | ' and ' +
75 | ""+data.intersection.street2+" "
76 | $('#street1_field').val(data.intersection.street1)
77 | $('#street2_field').val(data.intersection.street2)
78 | } else {
79 | msg = "No intersection near this location. Please try again."
80 | }
81 | $('#gmapmsg').html(msg)
82 | }
83 | }
84 |
85 | function show_directions_callback_builder(map) {
86 | // use a closure to make map a local variable
87 | return function show_directions(result, status) {
88 | if(status == "NOT_FOUND") {
89 | $('#gmaperror').html("Route not found");
90 | }
91 | if(status == "OK") {
92 | renderer = new google.maps.DirectionsRenderer({directions: result,
93 | suppressMarkers : true});
94 | renderer.setMap(map);
95 | $('#travel_distance').html(result.routes[0].legs[0].distance.text)
96 | }
97 | }
98 | }
99 |
100 | function gmapcenter(map, street) {
101 | var geocoder = new google.maps.Geocoder();
102 | var request = {address: street};
103 | geocoder.geocode(request, function(addresses, result, status){
104 | gmapcenterfinish(map, addresses, result, status)})
105 | }
106 |
107 | function gmapcenterfinish(map, addresses, result, status){
108 | if (addresses[0]) {
109 | var address = addresses[0];
110 | var start = new google.maps.LatLng(address.geometry.location.lat(),
111 | address.geometry.location.lng());
112 | map.setCenter(start)
113 | map.setZoom(14)
114 | marker_start.setPosition(start)
115 | mark_dragged(start)
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/app/assets/images/wheel.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
23 |
41 |
43 |
44 |
46 | image/svg+xml
47 |
49 |
50 |
51 |
52 |
53 |
58 |
68 |
78 |
84 |
90 |
96 |
102 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/spec/controllers/deliveries_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2 |
3 | describe DeliveriesController do
4 |
5 | context "when logged in" do
6 | before(:each) do
7 | controller.stub!(:user_signed_in?).and_return(true)
8 | @user = mock_model(User)
9 | controller.stub!(:current_user).and_return(@user)
10 | controller.stub!(:set_timezone)
11 | end
12 |
13 | it "lists deliveries" do
14 | get :index
15 | end
16 |
17 | it "creates a delivery" do
18 | delivery = mock_model(Delivery)
19 | Delivery.should_receive(:create).and_return(delivery)
20 | post :create
21 | response.should redirect_to(edit_delivery_path(delivery))
22 | end
23 |
24 | it "shows the details of a delivery" do
25 | delivery = mock_model(Delivery)
26 | Delivery.should_receive(:find).and_return(delivery)
27 | get :show, {:id => delivery.id}
28 | response.should render_template("show")
29 | end
30 |
31 | it "edits a delivery" do
32 | delivery = mock_model(Delivery)
33 | Delivery.should_receive(:find).and_return(delivery)
34 | delivery.should_receive(:listing_user).and_return(mock_model(User))
35 | delivery.should_receive(:available_for_edit_by).with(@user).and_return(true)
36 | get :edit, {:id => delivery.id}
37 | response.should render_template("edit")
38 | end
39 |
40 | context "updates a delivery" do
41 | before(:each) do
42 | bob = mock_model(User)
43 | #bob.should_receive(:username).and_return("bob")
44 | @delivery = mock_model(Delivery)
45 | @delivery.should_receive(:fee=)
46 | @delivery.should_receive(:package=)
47 | @delivery.should_receive(:start_location=)
48 | @delivery.should_receive(:end_location=)
49 | @delivery.should_receive(:save).and_return(true)
50 | @delivery.should_receive(:apply_form_attributes)
51 | Delivery.should_receive(:find).and_return(@delivery)
52 | end
53 |
54 | it "when the delivery has a creator" do
55 | @delivery.should_receive(:available_for_edit_by).with(@user).and_return(true)
56 | @delivery.should_receive(:listing_user).and_return(@user)
57 | put :update, {:id => @delivery.id}
58 | response.should redirect_to(delivery_path(@delivery))
59 | end
60 |
61 | it "when the delivery was created anonymously" do
62 | @delivery.should_receive(:listing_user)
63 | session[:anonymous_delivery_id] = @delivery.id
64 | put :update, {:id => @delivery.id}
65 | response.should redirect_to(:controller => :dashboard, :action => :start_delivery)
66 | end
67 | end
68 |
69 | it "should destroy a delivery" do
70 | delivery = mock_model(Delivery)
71 | delivery.should_receive(:destroy)
72 | Delivery.should_receive(:find).and_return(delivery)
73 | delete :destroy
74 | response.should redirect_to(deliveries_path)
75 | end
76 |
77 | it "should accept a delivery" do
78 | bob = mock_model(User)
79 | lister = mock_model(User)
80 | delivery = mock_model(Delivery)
81 | delivery.should_receive(:building?).and_return(false)
82 | delivery.should_receive(:accepted?).and_return(false)
83 | delivery.should_receive(:waiting?).and_return(true)
84 | delivery.should_receive(:deliverer).with(@user)
85 | delivery.should_receive(:save!)
86 | delivery.should_receive(:accept!)
87 | delivery.should_receive(:listing_user).and_return(bob)
88 | mailer = mock("Delivery Mailer")
89 | mailer.should_receive(:deliver)
90 | DeliveryMailer.should_receive(:accepted).with(delivery).and_return(mailer)
91 | Delivery.should_receive(:find).with(delivery.id.to_s).and_return(delivery)
92 | put :accept, {:id => delivery.id, "commit"=>"Yes I accept"}
93 | response.should redirect_to(delivery_path(delivery))
94 | end
95 | end
96 |
97 | context "when logged out" do
98 | before(:each) do
99 | controller.stub!(:user_signed_in?).and_return(false)
100 | controller.stub!(:current_user)
101 | controller.stub!(:set_timezone)
102 | end
103 |
104 | it "edits a delivery" do
105 | delivery = mock_model(Delivery)
106 | Delivery.should_receive(:find).and_return(delivery)
107 | session[:anonymous_delivery_id] = delivery.id
108 | get :edit, {:id => delivery.id}
109 | response.should render_template("edit")
110 | end
111 |
112 |
113 | it "should update a delivery" do
114 | bob = mock_model(User)
115 | #bob.should_receive(:username).and_return("bob")
116 | delivery = mock_model(Delivery)
117 | delivery.should_receive(:available_for_edit_by).with(@user).and_return(true)
118 | delivery.should_receive(:fee=)
119 | delivery.should_receive(:package=)
120 | delivery.should_receive(:start_location=)
121 | delivery.should_receive(:end_location=)
122 | delivery.should_receive(:save).and_return(true)
123 | delivery.should_receive(:apply_form_attributes)
124 | delivery.should_receive(:listing_user).and_return(nil)
125 | Delivery.should_receive(:find).and_return(delivery)
126 | put :update, {:id => delivery.id}
127 | response.should redirect_to(:controller => :dashboard, :action => :start_delivery)
128 | end
129 | end
130 | end
131 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 | # This file is auto-generated from the current state of the database. Instead
3 | # of editing this file, please use the migrations feature of Active Record to
4 | # incrementally modify your database, and then regenerate this schema definition.
5 | #
6 | # Note that this schema.rb definition is the authoritative source for your
7 | # database schema. If you need to create the application database on another
8 | # system, you should be using db:schema:load, not running all the migrations
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 | # you'll amass, the slower it'll run and the greater likelihood for issues).
11 | #
12 | # It's strongly recommended to check this file into your version control system.
13 |
14 | ActiveRecord::Schema.define(:version => 20130929215541) do
15 |
16 | create_table "comments", :force => true do |t|
17 | t.integer "delivery_id"
18 | t.integer "user_id"
19 | t.string "text"
20 | t.datetime "created_at"
21 | t.datetime "updated_at"
22 | end
23 |
24 | create_table "delayed_jobs", :force => true do |t|
25 | t.integer "priority", :default => 0
26 | t.integer "attempts", :default => 0
27 | t.text "handler"
28 | t.text "last_error"
29 | t.datetime "run_at"
30 | t.datetime "locked_at"
31 | t.datetime "failed_at"
32 | t.string "locked_by"
33 | t.datetime "created_at"
34 | t.datetime "updated_at"
35 | t.string "queue"
36 | end
37 |
38 | add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
39 |
40 | create_table "deliveries", :force => true do |t|
41 | t.integer "fee_id"
42 | t.integer "package_id"
43 | t.integer "start_location_id"
44 | t.integer "end_location_id"
45 | t.integer "listing_user_id"
46 | t.integer "delivering_user_id"
47 | t.datetime "created_at"
48 | t.datetime "updated_at"
49 | t.integer "start_end_distance"
50 | t.datetime "accepted_at"
51 | t.boolean "featured"
52 | t.string "workflow_state"
53 | end
54 |
55 | create_table "fees", :force => true do |t|
56 | t.integer "price_in_cents"
57 | t.datetime "created_at"
58 | t.datetime "updated_at"
59 | t.datetime "delivery_due"
60 | t.string "payment_method"
61 | end
62 |
63 | create_table "journal", :force => true do |t|
64 | t.integer "delivery_id"
65 | t.integer "package_id"
66 | t.integer "user_id"
67 | t.integer "location_id"
68 | t.float "fee"
69 | t.string "note"
70 | t.datetime "created_at"
71 | t.datetime "updated_at"
72 | end
73 |
74 | create_table "locations", :force => true do |t|
75 | t.string "street"
76 | t.string "zipcode"
77 | t.datetime "created_at"
78 | t.datetime "updated_at"
79 | t.float "latitude"
80 | t.float "longitude"
81 | t.float "accuracy"
82 | t.string "name"
83 | end
84 |
85 | create_table "open_id_associations", :force => true do |t|
86 | t.binary "server_url", :null => false
87 | t.string "handle", :null => false
88 | t.binary "secret", :null => false
89 | t.integer "issued", :null => false
90 | t.integer "lifetime", :null => false
91 | t.string "assoc_type", :null => false
92 | end
93 |
94 | create_table "open_id_nonces", :force => true do |t|
95 | t.string "server_url", :null => false
96 | t.integer "timestamp", :null => false
97 | t.string "salt", :null => false
98 | end
99 |
100 | create_table "openidentities", :force => true do |t|
101 | t.string "url"
102 | t.integer "user_id"
103 | t.datetime "created_at"
104 | t.datetime "updated_at"
105 | end
106 |
107 | create_table "packages", :force => true do |t|
108 | t.string "description"
109 | t.float "weight_in_grams"
110 | t.float "height_in_meters"
111 | t.float "width_in_meters"
112 | t.float "depth_in_meters"
113 | t.datetime "created_at"
114 | t.datetime "updated_at"
115 | t.integer "price_in_cents"
116 | end
117 |
118 | create_table "schedules", :force => true do |t|
119 | t.datetime "starting_at"
120 | t.datetime "ending_at"
121 | t.float "latitude"
122 | t.float "longitude"
123 | t.string "street1"
124 | t.string "street2"
125 | t.integer "user_id"
126 | t.datetime "created_at"
127 | t.datetime "updated_at"
128 | end
129 |
130 | create_table "sightings", :force => true do |t|
131 | t.integer "user_id"
132 | t.integer "location_id"
133 | t.datetime "created_at"
134 | t.datetime "updated_at"
135 | end
136 |
137 | create_table "slugs", :force => true do |t|
138 | t.string "name"
139 | t.integer "sluggable_id"
140 | t.integer "sequence", :default => 1, :null => false
141 | t.string "sluggable_type", :limit => 40
142 | t.string "scope"
143 | t.datetime "created_at"
144 | end
145 |
146 | add_index "slugs", ["name", "sluggable_type", "sequence", "scope"], :name => "index_slugs_on_n_s_s_and_s", :unique => true
147 | add_index "slugs", ["sluggable_id"], :name => "index_slugs_on_sluggable_id"
148 |
149 | create_table "users", :force => true do |t|
150 | t.string "username"
151 | t.datetime "created_at"
152 | t.datetime "updated_at"
153 | t.string "time_zone"
154 | t.string "display_measurement"
155 | t.string "email"
156 | t.datetime "clocked_in"
157 | t.boolean "email_on_new_listing"
158 | t.string "authentication_token"
159 | end
160 |
161 | end
162 |
--------------------------------------------------------------------------------
/app/controllers/deliveries_controller.rb:
--------------------------------------------------------------------------------
1 | class DeliveriesController < ApplicationController
2 | before_filter :load_resource, :except => [:index, :create]
3 |
4 | def index
5 | @delivery_groups = [ ]
6 | if params[:q]
7 | # postgresql full-text search
8 | one_month = Delivery.all(:conditions => ["to_tsvector('english', packages.description) "+
9 | "@@ to_tsquery('english', ?)", params[:q]], :include => :package)
10 | flash[:notice] = "Search results for \"#{params[:q]}\""
11 | else
12 | now = Time.now
13 | one_month = Delivery.waitings.find_due_after_time(now) +
14 | Delivery.waitings.find_due_between_times(1.month.ago, now)
15 | end
16 | @delivery_groups << ["less than a month old", one_month] if one_month.size > 0
17 | #four_hours = Delivery.find_between_hours_old(1,4).select{|d| d.ok_to_display?}
18 | #@delivery_groups << ["one to four hours old", four_hours] if four_hours.size > 0
19 | #many_hours = Delivery.find_more_than_hours_old(4).select{|d| d.ok_to_display?}
20 | #@delivery_groups << ["more than four hours old", many_hours] if many_hours.size > 0
21 |
22 | @clocked_ins = User.clocked_ins
23 | end
24 |
25 | def create
26 | delivery = Delivery.create({:listing_user => current_user})
27 | session[:anonymous_delivery_id] = delivery.id unless user_signed_in?
28 | redirect_to edit_delivery_path(delivery)
29 | end
30 |
31 | def show
32 | end
33 |
34 | def edit
35 | if user_signed_in?
36 | if @delivery.listing_user.nil?
37 | if params[:id].to_i == session[:anonymous_delivery_id]
38 | flash[:notice] = "Thank you for logging in. Please review the delivery before saving."
39 | session[:anonymous_delivery_id] = nil
40 | logger.info("assigning formerly anonymous listing")
41 | @delivery.listing_user = current_user
42 | @delivery.save!
43 | else
44 | flash[:error] = "Delivery ##{@delivery.id} was not started with this browser."
45 | redirect_to root_path
46 | end
47 | else
48 | unless @delivery.available_for_edit_by(current_user)
49 | flash[:error] = "Not allowed to edit delivery #{params[:id]}"
50 | redirect_to root_path
51 | end
52 | end
53 | else
54 | if @delivery.id == session[:anonymous_delivery_id]
55 | logger.info("editing under anonymous_delivery_id")
56 | else
57 | flash[:error] = "Login to edit a delivery request."
58 | redirect_to root_path
59 | end
60 | end
61 | end
62 |
63 | def update
64 | # update form is also a creation form for the dependent models
65 | unless (params[:id].to_i == session[:anonymous_delivery_id]) ||
66 | @delivery.available_for_edit_by(current_user)
67 | flash[:error] = "Not allowed to edit delivery #{params[:id]}"
68 | redirect_to root_path
69 | return
70 | end
71 | @delivery.apply_form_attributes(params[:delivery])
72 |
73 | fee = Fee.new
74 | fee.apply_form_attributes(params[:fee])
75 | fee.save!
76 | @delivery.fee = fee
77 |
78 | package = Package.new
79 | package.apply_form_attributes(params[:package])
80 | package.save!
81 | @delivery.package = package
82 |
83 | location = Location.new
84 | location.apply_form_attributes(params[:from])
85 | location.save!
86 | @delivery.start_location = location
87 |
88 | location = Location.new
89 | location.apply_form_attributes(params[:to])
90 | location.save!
91 | @delivery.end_location = location
92 |
93 | if @delivery.save
94 | if @delivery.listing_user
95 | redirect_to delivery_path(@delivery)
96 | else
97 | redirect_to :controller => :dashboard, :action => :start_delivery
98 | end
99 | else
100 | redirect_to edit_delivery_path(@delivery)
101 | end
102 | end
103 |
104 | def destroy
105 | @delivery.destroy
106 | Journal.create({:delivery => @delivery, :user => current_user, :note => "Destroyed Delivery"})
107 | redirect_to :deliveries
108 | end
109 |
110 | def confirm
111 | end
112 |
113 | def accept
114 | if params["commit"]=="Yes I accept"
115 | if @delivery.accepted?
116 | flash[:error] = "Delivery has already been accepted!"
117 | end
118 | if @delivery.waiting?
119 | @delivery.deliverer(current_user)
120 | @delivery.save!
121 | @delivery.accept!
122 | DeliveryMailer.accepted(@delivery).deliver
123 | Journal.create({:delivery => @delivery, :user => @delivery.listing_user, :note => "emailed delivery accepted letter"})
124 | flash[:notice] = "Delivery accepted!"
125 | end
126 | if @delivery.building?
127 | flash[:error] = "Delivery is not ready yet!"
128 | end
129 | end
130 | redirect_to delivery_path(@delivery)
131 | end
132 |
133 | def comment
134 | comment = @delivery.comments.create(:text => params[:comment][:text],
135 | :user_id => current_user.id)
136 | DeliveryMailer.comment(@delivery, comment).deliver
137 | redirect_to @delivery
138 | end
139 |
140 | def comment_delete
141 | @delivery.comments.find(params[:comment_id]).destroy
142 | redirect_to @delivery
143 | end
144 |
145 | private
146 | def load_resource
147 | @delivery = Delivery.find(params[:id])
148 | unless @delivery
149 | flash[:error] = "Delivery ##{params[:id]} does not exist."
150 | redirect_to :deliveries
151 | end
152 | end
153 | end
154 |
--------------------------------------------------------------------------------
/app/assets/images/wheel-e.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
23 |
41 |
43 |
44 |
46 | image/svg+xml
47 |
49 |
50 |
51 |
52 |
53 |
58 |
68 |
78 |
84 |
90 |
96 |
102 |
110 | E
122 |
123 |
124 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: http://rubygems.org/
3 | specs:
4 | actionmailer (3.2.11)
5 | actionpack (= 3.2.11)
6 | mail (~> 2.4.4)
7 | actionpack (3.2.11)
8 | activemodel (= 3.2.11)
9 | activesupport (= 3.2.11)
10 | builder (~> 3.0.0)
11 | erubis (~> 2.7.0)
12 | journey (~> 1.0.4)
13 | rack (~> 1.4.0)
14 | rack-cache (~> 1.2)
15 | rack-test (~> 0.6.1)
16 | sprockets (~> 2.2.1)
17 | activemodel (3.2.11)
18 | activesupport (= 3.2.11)
19 | builder (~> 3.0.0)
20 | activerecord (3.2.11)
21 | activemodel (= 3.2.11)
22 | activesupport (= 3.2.11)
23 | arel (~> 3.0.2)
24 | tzinfo (~> 0.3.29)
25 | activeresource (3.2.11)
26 | activemodel (= 3.2.11)
27 | activesupport (= 3.2.11)
28 | activesupport (3.2.11)
29 | i18n (~> 0.6)
30 | multi_json (~> 1.0)
31 | addressable (2.3.2)
32 | ansi (1.4.3)
33 | arel (3.0.2)
34 | babosa (0.3.8)
35 | bcrypt-ruby (3.0.1)
36 | builder (3.0.4)
37 | coffee-rails (3.2.2)
38 | coffee-script (>= 2.2.0)
39 | railties (~> 3.2.0)
40 | coffee-script (2.2.0)
41 | coffee-script-source
42 | execjs
43 | coffee-script-source (1.4.0)
44 | delayed_job (3.0.4)
45 | activesupport (~> 3.0)
46 | delayed_job_active_record (4.0.0)
47 | activerecord (>= 3.0, < 4.1)
48 | delayed_job (>= 3.0, < 4.1)
49 | devise (2.2.0)
50 | bcrypt-ruby (~> 3.0)
51 | orm_adapter (~> 0.1)
52 | railties (~> 3.1)
53 | warden (~> 1.2.1)
54 | diff-lcs (1.1.3)
55 | erubis (2.7.0)
56 | eventmachine (1.0.0)
57 | exception_notification (3.0.0)
58 | actionmailer (>= 3.0.4)
59 | tinder (~> 1.8)
60 | execjs (1.4.0)
61 | multi_json (~> 1.0)
62 | faraday (0.8.4)
63 | multipart-post (~> 1.1)
64 | faraday_middleware (0.9.0)
65 | faraday (>= 0.7.4, < 0.9)
66 | friendly_id (3.3.3.0)
67 | babosa (~> 0.3.0)
68 | hashie (1.2.0)
69 | hike (1.2.1)
70 | http_parser.rb (0.5.3)
71 | i18n (0.6.1)
72 | journey (1.0.4)
73 | jquery-rails (2.1.4)
74 | railties (>= 3.0, < 5.0)
75 | thor (>= 0.14, < 2.0)
76 | json (1.7.6)
77 | kgio (2.7.4)
78 | launchy (2.1.2)
79 | addressable (~> 2.3)
80 | letter_opener (1.0.0)
81 | launchy (>= 2.0.4)
82 | loofah (1.2.1)
83 | nokogiri (>= 1.4.4)
84 | mail (2.4.4)
85 | i18n (>= 0.4.0)
86 | mime-types (~> 1.16)
87 | treetop (~> 1.4.8)
88 | mime-types (1.19)
89 | multi_json (1.5.0)
90 | multipart-post (1.1.5)
91 | nokogiri (1.5.6)
92 | orm_adapter (0.4.0)
93 | pg (0.14.1)
94 | polyglot (0.3.3)
95 | rack (1.4.3)
96 | rack-cache (1.2)
97 | rack (>= 0.4)
98 | rack-ssl (1.3.2)
99 | rack
100 | rack-test (0.6.2)
101 | rack (>= 1.0)
102 | rails (3.2.11)
103 | actionmailer (= 3.2.11)
104 | actionpack (= 3.2.11)
105 | activerecord (= 3.2.11)
106 | activeresource (= 3.2.11)
107 | activesupport (= 3.2.11)
108 | bundler (~> 1.0)
109 | railties (= 3.2.11)
110 | railties (3.2.11)
111 | actionpack (= 3.2.11)
112 | activesupport (= 3.2.11)
113 | rack-ssl (~> 1.3.2)
114 | rake (>= 0.8.7)
115 | rdoc (~> 3.4)
116 | thor (>= 0.14.6, < 2.0)
117 | raindrops (0.10.0)
118 | rake (10.0.3)
119 | rdoc (3.12)
120 | json (~> 1.4)
121 | rspec-core (2.12.2)
122 | rspec-expectations (2.12.1)
123 | diff-lcs (~> 1.1.3)
124 | rspec-mocks (2.12.1)
125 | rspec-rails (2.12.1)
126 | actionpack (>= 3.0)
127 | activesupport (>= 3.0)
128 | railties (>= 3.0)
129 | rspec-core (~> 2.12.0)
130 | rspec-expectations (~> 2.12.0)
131 | rspec-mocks (~> 2.12.0)
132 | sass (3.2.5)
133 | sass-rails (3.2.5)
134 | railties (~> 3.2.0)
135 | sass (>= 3.1.10)
136 | tilt (~> 1.3)
137 | simple_oauth (0.1.9)
138 | sprockets (2.2.2)
139 | hike (~> 1.2)
140 | multi_json (~> 1.0)
141 | rack (~> 1.0)
142 | tilt (~> 1.1, != 1.3.0)
143 | sqlite3 (1.3.6)
144 | thor (0.16.0)
145 | tilt (1.3.3)
146 | tinder (1.9.2)
147 | eventmachine (~> 1.0)
148 | faraday (~> 0.8)
149 | faraday_middleware (~> 0.9)
150 | hashie (~> 1.0)
151 | json (~> 1.7.5)
152 | mime-types (~> 1.19)
153 | multi_json (~> 1.5)
154 | twitter-stream (~> 0.1)
155 | treetop (1.4.12)
156 | polyglot
157 | polyglot (>= 0.3.1)
158 | turn (0.9.6)
159 | ansi
160 | twitter (4.4.0)
161 | faraday (~> 0.8)
162 | multi_json (~> 1.3)
163 | simple_oauth (~> 0.1.6)
164 | twitter-stream (0.1.16)
165 | eventmachine (>= 0.12.8)
166 | http_parser.rb (~> 0.5.1)
167 | simple_oauth (~> 0.1.4)
168 | tzinfo (0.3.35)
169 | uglifier (1.3.0)
170 | execjs (>= 0.3.0)
171 | multi_json (~> 1.0, >= 1.0.2)
172 | unicorn (4.5.0)
173 | kgio (~> 2.6)
174 | rack
175 | raindrops (~> 0.7)
176 | uuidtools (2.1.3)
177 | warden (1.2.1)
178 | rack (>= 1.0)
179 | webrat (0.7.3)
180 | nokogiri (>= 1.2.0)
181 | rack (>= 1.0)
182 | rack-test (>= 0.5.3)
183 | workflow (0.8.6)
184 |
185 | PLATFORMS
186 | ruby
187 |
188 | DEPENDENCIES
189 | coffee-rails (~> 3.2.2)
190 | delayed_job_active_record
191 | devise
192 | exception_notification
193 | friendly_id (~> 3.3.3.0)
194 | jquery-rails
195 | letter_opener
196 | loofah
197 | pg
198 | rails (= 3.2.11)
199 | rspec-rails
200 | sass-rails (~> 3.2.5)
201 | sqlite3
202 | turn
203 | twitter
204 | uglifier
205 | unicorn
206 | uuidtools
207 | webrat
208 | workflow
209 |
--------------------------------------------------------------------------------
/app/views/deliveries/show.html.erb:
--------------------------------------------------------------------------------
1 | <% if @delivery.start_location && @delivery.end_location %>
2 |
20 | <% end %>
21 |
22 |
23 |
24 |
25 | Delivery #<%= @delivery.id %>
26 | <% package = @delivery.package %>
27 | <% if package %>
28 | <%=h @delivery.package.description %>
29 | <% end %>
30 | <% if @delivery.available_for_edit_by(current_user) %>
31 | (<%= link_to "edit", edit_delivery_path(@delivery) %>)
32 | <% end %>
33 |
34 |
35 |
36 |
Status
37 |
38 | <% if @delivery.delivering_user %>
39 | Delivery accepted by: <%= link_to_user @delivery.delivering_user %>
40 | <% else %>
41 | <% if @delivery.waiting? %>
42 | Available for delivery.
43 | <% else %>
44 | Unfinished
45 | <% end %>
46 | <% end %>
47 |
48 |
49 | Listed by: <%= link_to_user @delivery.listing_user %>
50 |
51 | Listed at: <%= @delivery.created_at.strftime("%l:%M%P %Z %d-%b-%Y") %>
52 |
53 |
54 |
55 |
56 |
Package
57 | <% if package %>
58 |
59 | Description: "<%=h @delivery.package.description %>"
60 |
61 | <% if package.has_dimensions? %>
62 | Height: <%= @delivery.package.height %>"
63 | Width: <%= @delivery.package.width %>"
64 | Depth: <%= @delivery.package.depth %>"
65 | <% end %>
66 |
67 | <% else %>
68 |
69 | no package has been specified
70 |
71 | <% end %>
72 |
73 |
74 |
75 |
Price and Bounty
76 |
77 | <% if package %>
78 | Retail price: $<%= @delivery.package.display_price %>
79 | <% end %>
80 | <% if @delivery.fee %>
81 | Bounty: $<%= @delivery.fee.display_price %>
82 | Payment method: <%= @delivery.fee.payment_method %>
83 |
84 | <% else %>
85 | no delivery fee has been specified
86 | <% end %>
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | <% if @delivery.start_location && @delivery.end_location %>
95 |
96 |
97 | <% end %>
98 |
99 |
100 |
101 |
102 |
From
103 |
104 | <% if @delivery.start_location %>
105 | <%= @delivery.start_location.name %>
106 | <%= @delivery.start_location.street %>
107 | <% else %>
108 | no start location has been specified
109 | <% end %>
110 |
111 |
112 |
113 |
114 |
To
115 |
116 | <% if @delivery.end_location %>
117 | <%= @delivery.end_location.name %>
118 | <%= @delivery.end_location.street %>
119 | <% else %>
120 | no end location has been specified
121 | <% end %>
122 |
123 |
124 |
125 |
126 | <% if @delivery.start_end_distance && @delivery.start_end_distance > 0 %>
127 |
Distance
128 |
129 | Travel distance:
130 |
131 | <% end %>
132 |
133 |
134 |
135 |
Time
136 | <% if @delivery.fee %>
137 | Due Date: <%= @delivery.fee.delivery_due.strftime("%l:%M%P %Z %d-%b-%Y") %>
138 | <% if @delivery.fee.delivery_due >= Time.now %>
139 | Due In: <%= distance_of_time_in_words_to_now(@delivery.fee.delivery_due) %>
140 | <% else %>
141 | Overdue by: <%= distance_of_time_in_words_to_now(@delivery.fee.delivery_due) %>
142 | <% end %>
143 | <% end %>
144 |
145 |
146 | <% if @delivery.available_for_delivery_by(current_user) %>
147 | <%= form_for @delivery, :url => confirm_delivery_path(@delivery), :html => {:method => :put} do |f| %>
148 | <%= f.submit 'I can make this delivery' %>
149 | <% end %>
150 | <% end %>
151 |
152 |
153 |
154 |
174 |
175 |
--------------------------------------------------------------------------------
/app/views/deliveries/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :header do %>
2 |
5 | <% end %>
6 |
7 | Delivery Request #<%= @delivery.id %>
8 |
9 | <%= form_for(@delivery) do |f| %>
10 |
11 |
12 | Item
13 | Description <%= text_field_tag "package[description]",
14 | @delivery.package ? @delivery.package.description : "", :size => 50,
15 | :autofocus => "" %>
16 |
17 |
30 |
31 |
32 |
33 | Pick-up Address
34 |
35 |
36 | Person or Business Name
37 | <%= text_field_tag "from[name]",
38 | @delivery.start_location ? @delivery.start_location.name : "",
39 | :size => 20, :placeholder => "Corner Store" %>
40 | Address
41 | <%= text_field_tag "from[address]",
42 | @delivery.start_location ? @delivery.start_location.street : "",
43 | :size => 40, :placeholder => "900 Main St, Portland, Or" %>
44 |
45 |
46 | <%= hidden_field_tag "from[latitude]", @delivery.start_location ? @delivery.start_location.latitude : "" %>
47 | <%= hidden_field_tag "from[longitude]", @delivery.start_location ? @delivery.start_location.longitude : "" %>
48 |
49 |
50 |
51 |
52 | Drop-off Address
53 |
54 |
55 | Person or Business Name
56 | <%= text_field_tag "to[name]",
57 | @delivery.end_location ? @delivery.end_location.name : "",
58 | :size => 20, :placeholder => "Hungry Citizen" %>
59 | Address
60 | <%= text_field_tag "to[address]",
61 | @delivery.end_location ? @delivery.end_location.street : "",
62 | :size => 40, :placeholder => "1200 Thurston St, Portland, Or" %>
63 |
64 |
65 | <%= hidden_field_tag "to[latitude]", @delivery.end_location ? @delivery.end_location.latitude : ""%>
66 | <%= hidden_field_tag "to[longitude]", @delivery.end_location ? @delivery.end_location.longitude : ""%>
67 |
68 |
69 |
70 |
71 | Time
72 | Delivery should be completed by
73 | <% if @delivery.fee
74 | due_time = @delivery.fee.delivery_due.in_time_zone
75 | else
76 | due_time = Time.zone.now
77 | end %>
78 | <%= datetime_select("fee","delivery_due", :default => due_time, :ampm => true) %>
79 | <%= Time.zone.name.sub(/\(.*\)/,'') %>
80 |
81 |
86 |
87 |
88 |
89 | Price / Bounty
90 | If the delivery person will be purchasing the item, give the retail price.
91 | Retail Price $<%= text_field_tag "package[display_price]",
92 | @delivery.package ? @delivery.package.display_price : "", :size => 2 %>
93 |
94 | The higher the bounty, the more likely it will be completed.
95 | Bounty Amount $<%= text_field_tag "fee[display_price]",
96 | @delivery.fee ? @delivery.fee.display_price : "0.00", :size => 4 %>
97 |
98 |
99 |
100 | Payment
101 | I agree to pay the retail price (if any) plus the bounty amount
102 |
103 | to the delivery person upon delivery using
104 | <% if @delivery.fee %>
105 | <% @delivery.fee.errors.full_messages.each do |msg| %>
106 | <%= msg %>
107 | <% end %>
108 | <% end %>
109 |
110 | <%= radio_button_tag "fee[payment_method]", "cash", @delivery.fee ? @delivery.fee.payment_method == "cash" : false %> Cash
111 | <%= radio_button_tag "fee[payment_method]", "visa", @delivery.fee ? @delivery.fee.payment_method == "visa" : false %> VISA
112 |
113 |
114 |
115 | <%= hidden_field_tag "delivery[start_end_distance]", ""%>
116 |
117 |
118 | <%= f.submit "Save Details" %>
119 |
120 | <% end %>
121 |
122 |
123 | <%= button_to "Cancel Listing", delivery_path(@delivery), :confirm => "Delete this delivery listing?", :method => :delete %>
124 |
125 |
126 |
--------------------------------------------------------------------------------
/app/assets/images/seal.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
23 |
41 |
43 |
44 |
46 | image/svg+xml
47 |
49 |
50 |
51 |
52 |
53 |
58 |
71 |
74 |
84 |
94 |
100 |
106 |
112 |
118 |
124 |
125 | EveryoneDelivers
136 |
137 |
138 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/main.scss:
--------------------------------------------------------------------------------
1 | $backbackground: #454141;
2 | $background: #545151;
3 | $color1: #5b8207;
4 | $color2: #9CC445;
5 | $listingcolor1: #bebebe;
6 |
7 | body {
8 | background-color: $backbackground;
9 | margin-top: 0px;
10 | }
11 |
12 | .container {
13 | font-family: arial;
14 | padding-top: 2px;
15 | margin-left: 10px;
16 | margin-right: 10px;
17 | background: $background;
18 | color: white;
19 | border-radius: 9px;
20 | }
21 |
22 | .container a {
23 | text-decoration: none;
24 | color: #41c30b;
25 | }
26 |
27 | .container a:hover {
28 | color: #51d31b;
29 | text-decoration: underline;
30 | }
31 |
32 | .header {
33 | background: $color1;
34 | margin: 5px;
35 | padding: 5px;
36 | border-radius: 9px;
37 | color: white;
38 | }
39 |
40 | .header .logo img{
41 | border: 0;
42 | vertical-align: -50%;
43 | }
44 |
45 | .header .logo .logotext {
46 | font-size: 120%
47 | }
48 |
49 | .header .logo .logotext a{
50 | color: white
51 | }
52 |
53 | .header a {
54 | color: $color2;
55 | font-family: sans-serif;
56 | }
57 |
58 | .header a:hover {
59 | color: white;
60 | font-family: sans-serif;
61 | text-decoration: underline;
62 | }
63 |
64 | .header ul {
65 | margin:0px;
66 | padding:0px;
67 | display:inline;
68 | list-style-type:none;
69 | float: left
70 | }
71 |
72 | .header li {
73 | display:inline;
74 | /* border-right:1px solid #333333; */
75 | margin:0px;
76 | padding:0px;
77 | }
78 |
79 | div.header #sub {
80 | padding: 5px;
81 | float: right;
82 | }
83 |
84 | .header .username {
85 | color: white;
86 | }
87 |
88 |
89 | #logotext {
90 | font-size: 150%;
91 | }
92 |
93 |
94 | .dark {
95 | background-color: #656161;
96 | }
97 |
98 | .light {
99 | background-color: $backbackground;
100 | }
101 |
102 | .error {
103 | color: red;
104 | font-size: 110%;
105 | }
106 |
107 | .flashmsgs {
108 | margin-top: 0.6em;
109 | text-align: center;
110 | }
111 |
112 | .clockedinbutton {
113 | float: left;
114 | text-align: center;
115 | margin-top: 5%
116 | }
117 |
118 | .clockedin {
119 | background: $color2;
120 | }
121 |
122 | .clockedout {
123 | margin-left: 10;
124 | background-color: $color1;
125 | }
126 |
127 | .clockedinbox {
128 | float: right;
129 | color: white;
130 | margin-right: 3%;
131 | }
132 |
133 | .clockedinpeople {
134 | background: #5B8207;
135 | float:left;
136 | border-radius: 9px 9px 0 0;
137 | }
138 |
139 | .clockedinpeople p {
140 | margin-top: 0.5em;
141 | margin-bottom: 0px;
142 | margin-left: 0.3em;
143 | margin-right: 0.3em;
144 | border-bottom-style: solid;
145 | text-align: center
146 | }
147 |
148 | .clockedinpeople ul {
149 | list-style: none;
150 | padding-left: 5%;
151 | margin-top: 0px;
152 | margin-bottom: 5%;
153 | }
154 |
155 | .clockedinpeople .username {
156 | font-size: 16pt;
157 | }
158 |
159 | .clockedinpeople li a {
160 | }
161 |
162 | .clockedinpeople li a:hover {
163 | text-decoration: underline;
164 | }
165 |
166 | .clockedintime {
167 | font-size: 80%;
168 | }
169 |
170 | form.edit_delivery {
171 | color: white;
172 | text-align: center;
173 | width: 80%;
174 | margin-left: auto;
175 | margin-right: auto;
176 | }
177 |
178 | #slogan {
179 | margin-top: 0px;
180 | margin-left: 15px
181 | }
182 |
183 | #splash {
184 | text-align: center;
185 | }
186 |
187 | #splashwhy {
188 | width: 40%;
189 | margin-left: auto;
190 | margin-right: auto;
191 | margin-bottom: 0px;
192 | }
193 |
194 | #splash h3 {
195 | color: orange;
196 | font-size: 120%;
197 | }
198 |
199 | #splashrow {
200 | overflow: auto;
201 | }
202 |
203 | #splashleft {
204 | float: left;
205 | width: 25%;
206 | margin-left: 25%;
207 | }
208 | #splashleft p{
209 | border-right-style: solid;
210 | }
211 |
212 | #splashright {
213 | float: left;
214 | width: 25%;
215 | margin-right: 25%;
216 | }
217 |
218 | .menubar {
219 | margin-top: 0.6em;
220 | padding: 8px;
221 | background: $color2;
222 | color: #D8E3C1;
223 | overflow: auto;
224 | clear: right;
225 | }
226 |
227 | .menubar a {
228 | text-decoration: underline;
229 | color: white;
230 | }
231 |
232 | .menubar a:hover {
233 | color: #33527A;
234 | text-decoration: underline;
235 | }
236 |
237 | .menubar ul {
238 | margin-left: auto;
239 | margin-right: auto;
240 | margin-top: 0px;
241 | margin-bottom: 0px;
242 | padding:0px;
243 | display:inline;
244 | list-style-type:none;
245 | float: left;
246 | }
247 |
248 | .menubar li {
249 | display:inline;
250 | margin:5px;
251 | padding:1px;
252 | }
253 |
254 | .menubar li a {
255 | }
256 |
257 | .menubar input {
258 | border: 0;
259 | }
260 |
261 | .menubar form#new_delivery {
262 | float: left;
263 | }
264 |
265 | #content {
266 | margin-top: 10px;
267 | overflow: auto;
268 | }
269 |
270 | .listbox {
271 | overflow: auto;
272 | }
273 |
274 | .deliverylist {
275 | margin-top: 0px;
276 | margin-bottom: 10px;
277 | margin-left: 10px;
278 | list-style-type: none;
279 | padding-left: 0px;
280 | -moz-border-radius: 5px;
281 | -webkit-border-radius: 5px;
282 | }
283 |
284 | .deliverylist li {
285 | padding: 4px;
286 | }
287 |
288 | .deliverytimes {
289 | float: left;
290 | }
291 |
292 | .deliveryitem {
293 | border-radius: 6px;
294 | }
295 |
296 | .packagename {
297 | font-size: 140%;
298 | font-weight: bold;
299 | background: #689ca7;
300 | border-radius: 9px 9px 0 0;
301 | color: white;
302 | text-align: center;
303 | }
304 |
305 | .packagename a {
306 | color: white;
307 | }
308 |
309 | .packagename a:hover {
310 | color: white;
311 | }
312 |
313 | .deliveryitem div.overdue {
314 | background: #526d73;
315 | }
316 |
317 | .deliverypackageinfo {
318 | float: left;
319 | text-align: left;
320 | background: #a4c1c5;
321 | color: black;
322 | border-bottom-right-radius: 1.1em;
323 | padding: 1%;
324 | -moz-border-radius-bottomright: 1.1em;
325 | -webkit-border-bottom-right-radius: 1.1em;
326 | -o-border-bottom-right-radius: 1.1em;
327 | -ms-border-bottom-right-radius: 1.1em;
328 | }
329 |
330 | .deliverypackageinfo .bountytitle {
331 | font-size: 70%;
332 | text-align: center;
333 | }
334 |
335 | .deliverypackageinfo .deliveryfee {
336 | font-size: 110%;
337 | font-weight: bold;
338 | font-size: 150%;
339 | }
340 |
341 | .deliverylistinguser {
342 | font-size: 80%;
343 | }
344 |
345 | .deliverypackageprice a {
346 | color: #8D9D73;
347 | }
348 |
349 | .deliverypackageprice a:hover {
350 | color: green;
351 | }
352 |
353 | .deliverydetail {
354 | width: 80%;
355 | margin-left: auto;
356 | margin-right: auto;
357 | }
358 |
359 | .deliverydetail h4 {
360 | margin-top: 0px;
361 | margin-bottom: 0px;
362 | text-align: center;
363 | }
364 |
365 | .deliverydetail .addressparts h4 {
366 | text-align: left;
367 | }
368 |
369 | .deliverydetail p {
370 | margin-top: 0px;
371 | margin-bottom: 1em;
372 | }
373 |
374 | .deliverydetail .map {
375 | float:left;
376 | margin-right: 40px
377 | }
378 |
379 | .deliverydetail .info {
380 | float:left;
381 | margin-right: 2em;
382 | }
383 |
384 | .deliverydetail .comments {
385 | clear:left
386 | }
387 |
388 | .deliveryconfirm {
389 | width: 80%;
390 | margin-left: auto;
391 | margin-right: auto;
392 | }
393 |
394 | .deliveryconfirm .map {
395 | float: right;
396 | }
397 |
398 | .googlestaticmap {
399 | margin-left: auto;
400 | margin-right: auto;
401 | overflow: auto;
402 | }
403 |
404 | .googlestaticmap img {
405 | }
406 |
407 | .googlestaticmap .direction {
408 | font-weight: bold;
409 | font-size: 100%;
410 | margin-bottom: 5%;
411 | }
412 |
413 | .mapaddr {
414 | margin-left: 10%;
415 | margin-right: 10%
416 | }
417 |
418 | .mapaddr .address {
419 | }
420 |
421 | .mapaddr .map {
422 | float: left;
423 | text-align: center;
424 | width: 100px;
425 | }
426 |
427 | .deliveryitem {
428 | text-align: center;
429 | }
430 |
431 | .deliveryitem .duedate {
432 | float: right;
433 | font-size: 70%;
434 | color: white;
435 | margin-right: 0.5em
436 | }
437 |
438 | .deliveryitem .duedate a{
439 | color: orange;
440 | }
441 | .deliveryitem .duedate a:hover{
442 | color: #FF7A38;
443 | }
444 |
445 | .deliverypackagefromto {
446 | margin-top: 0.3em;
447 | }
448 |
449 | .deliverypackagefromto .halffromto {
450 | width: 50%;
451 | float: left;
452 | }
453 |
454 | #footer {
455 | margin-top: 10px;
456 | text-align: center;
457 | font-size: 80%;
458 | }
459 |
460 | #geomsg {
461 | margin-right: 20px;
462 | color: $color2;
463 | }
464 |
465 | .centered_50percent {
466 | margin-left: auto;
467 | margin-right: auto;
468 | width: 50%;
469 | }
470 |
471 | .textaligncenter {
472 | text-align: center;
473 | }
474 |
475 | #openidprovidertable {
476 | font-size: 130%;
477 | }
478 |
479 | .openidproviderbox {
480 | }
481 |
482 | .openidproviderbox img {
483 | border: 0;
484 | background: white;
485 | -moz-border-radius: 5px;
486 | -webkit-border-radius: 5px;
487 | }
488 |
489 | .biglogin {
490 | font-size: 110%;
491 | }
492 |
493 | #edituser form {
494 | width: 50%;
495 | }
496 |
497 | #edituser label {
498 | width: 5em;
499 | font-size: 150%;
500 | }
501 |
502 | .fieldWithErrors {
503 | color: yellow;
504 | }
505 |
506 | #usershow {
507 | width: 90%;
508 | margin-left: auto;
509 | margin-right: auto;
510 | }
511 |
512 | #usermenu ul {
513 | background: $backbackground;
514 | }
515 |
516 | #usermenu li {
517 | display: inline;
518 | margin-right: 5em;
519 | }
520 |
521 | #sampledelivery {
522 | width: 80%;
523 | margin-right: auto;
524 | margin-left: auto;
525 | list-style: none;
526 | margin-top: 1em;
527 | }
528 |
529 | .payment_methods {
530 | list-style-type: none;
531 | display: inline;
532 | padding-left: 0px;
533 | }
534 |
535 | .clockinschedule {
536 | width:80%;
537 | margin-left: auto;
538 | margin-right: auto
539 | }
540 |
541 | #gmapmsg .street{
542 | background: $color1;
543 | padding: 0.2em;
544 | }
545 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | == Welcome to Rails
2 |
3 | Rails is a web-application framework that includes everything needed to create
4 | database-backed web applications according to the Model-View-Control pattern.
5 |
6 | This pattern splits the view (also called the presentation) into "dumb"
7 | templates that are primarily responsible for inserting pre-built data in between
8 | HTML tags. The model contains the "smart" domain objects (such as Account,
9 | Product, Person, Post) that holds all the business logic and knows how to
10 | persist themselves to a database. The controller handles the incoming requests
11 | (such as Save New Account, Update Product, Show Post) by manipulating the model
12 | and directing data to the view.
13 |
14 | In Rails, the model is handled by what's called an object-relational mapping
15 | layer entitled Active Record. This layer allows you to present the data from
16 | database rows as objects and embellish these data objects with business logic
17 | methods. You can read more about Active Record in
18 | link:files/vendor/rails/activerecord/README.html.
19 |
20 | The controller and view are handled by the Action Pack, which handles both
21 | layers by its two parts: Action View and Action Controller. These two layers
22 | are bundled in a single package due to their heavy interdependence. This is
23 | unlike the relationship between the Active Record and Action Pack that is much
24 | more separate. Each of these packages can be used independently outside of
25 | Rails. You can read more about Action Pack in
26 | link:files/vendor/rails/actionpack/README.html.
27 |
28 |
29 | == Getting Started
30 |
31 | 1. At the command prompt, create a new Rails application:
32 | rails new myapp (where myapp is the application name)
33 |
34 | 2. Change directory to myapp and start the web server:
35 | cd myapp; rails server (run with --help for options)
36 |
37 | 3. Go to http://localhost:3000/ and you'll see:
38 | "Welcome aboard: You're riding Ruby on Rails!"
39 |
40 | 4. Follow the guidelines to start developing your application. You can find
41 | the following resources handy:
42 |
43 | * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
44 | * Ruby on Rails Tutorial Book: http://www.railstutorial.org/
45 |
46 |
47 | == Debugging Rails
48 |
49 | Sometimes your application goes wrong. Fortunately there are a lot of tools that
50 | will help you debug it and get it back on the rails.
51 |
52 | First area to check is the application log files. Have "tail -f" commands
53 | running on the server.log and development.log. Rails will automatically display
54 | debugging and runtime information to these files. Debugging info will also be
55 | shown in the browser on requests from 127.0.0.1.
56 |
57 | You can also log your own messages directly into the log file from your code
58 | using the Ruby logger class from inside your controllers. Example:
59 |
60 | class WeblogController < ActionController::Base
61 | def destroy
62 | @weblog = Weblog.find(params[:id])
63 | @weblog.destroy
64 | logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
65 | end
66 | end
67 |
68 | The result will be a message in your log file along the lines of:
69 |
70 | Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
71 |
72 | More information on how to use the logger is at http://www.ruby-doc.org/core/
73 |
74 | Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
75 | several books available online as well:
76 |
77 | * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
78 | * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
79 |
80 | These two books will bring you up to speed on the Ruby language and also on
81 | programming in general.
82 |
83 |
84 | == Debugger
85 |
86 | Debugger support is available through the debugger command when you start your
87 | Mongrel or WEBrick server with --debugger. This means that you can break out of
88 | execution at any point in the code, investigate and change the model, and then,
89 | resume execution! You need to install ruby-debug to run the server in debugging
90 | mode. With gems, use sudo gem install ruby-debug . Example:
91 |
92 | class WeblogController < ActionController::Base
93 | def index
94 | @posts = Post.all
95 | debugger
96 | end
97 | end
98 |
99 | So the controller will accept the action, run the first line, then present you
100 | with a IRB prompt in the server window. Here you can do things like:
101 |
102 | >> @posts.inspect
103 | => "[#nil, "body"=>nil, "id"=>"1"}>,
105 | #"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
107 | >> @posts.first.title = "hello from a debugger"
108 | => "hello from a debugger"
109 |
110 | ...and even better, you can examine how your runtime objects actually work:
111 |
112 | >> f = @posts.first
113 | => #nil, "body"=>nil, "id"=>"1"}>
114 | >> f.
115 | Display all 152 possibilities? (y or n)
116 |
117 | Finally, when you're ready to resume execution, you can enter "cont".
118 |
119 |
120 | == Console
121 |
122 | The console is a Ruby shell, which allows you to interact with your
123 | application's domain model. Here you'll have all parts of the application
124 | configured, just like it is when the application is running. You can inspect
125 | domain models, change values, and save to the database. Starting the script
126 | without arguments will launch it in the development environment.
127 |
128 | To start the console, run rails console from the application
129 | directory.
130 |
131 | Options:
132 |
133 | * Passing the -s, --sandbox argument will rollback any modifications
134 | made to the database.
135 | * Passing an environment name as an argument will load the corresponding
136 | environment. Example: rails console production .
137 |
138 | To reload your controllers and models after launching the console run
139 | reload!
140 |
141 | More information about irb can be found at:
142 | link:http://www.rubycentral.org/pickaxe/irb.html
143 |
144 |
145 | == dbconsole
146 |
147 | You can go to the command line of your database directly through rails
148 | dbconsole . You would be connected to the database with the credentials
149 | defined in database.yml. Starting the script without arguments will connect you
150 | to the development database. Passing an argument will connect you to a different
151 | database, like rails dbconsole production . Currently works for MySQL,
152 | PostgreSQL and SQLite 3.
153 |
154 | == Description of Contents
155 |
156 | The default directory structure of a generated Ruby on Rails application:
157 |
158 | |-- app
159 | | |-- assets
160 | | |-- images
161 | | |-- javascripts
162 | | `-- stylesheets
163 | | |-- controllers
164 | | |-- helpers
165 | | |-- mailers
166 | | |-- models
167 | | `-- views
168 | | `-- layouts
169 | |-- config
170 | | |-- environments
171 | | |-- initializers
172 | | `-- locales
173 | |-- db
174 | |-- doc
175 | |-- lib
176 | | `-- tasks
177 | |-- log
178 | |-- public
179 | |-- script
180 | |-- test
181 | | |-- fixtures
182 | | |-- functional
183 | | |-- integration
184 | | |-- performance
185 | | `-- unit
186 | |-- tmp
187 | | |-- cache
188 | | |-- pids
189 | | |-- sessions
190 | | `-- sockets
191 | `-- vendor
192 | |-- assets
193 | `-- stylesheets
194 | `-- plugins
195 |
196 | app
197 | Holds all the code that's specific to this particular application.
198 |
199 | app/assets
200 | Contains subdirectories for images, stylesheets, and JavaScript files.
201 |
202 | app/controllers
203 | Holds controllers that should be named like weblogs_controller.rb for
204 | automated URL mapping. All controllers should descend from
205 | ApplicationController which itself descends from ActionController::Base.
206 |
207 | app/models
208 | Holds models that should be named like post.rb. Models descend from
209 | ActiveRecord::Base by default.
210 |
211 | app/views
212 | Holds the template files for the view that should be named like
213 | weblogs/index.html.erb for the WeblogsController#index action. All views use
214 | eRuby syntax by default.
215 |
216 | app/views/layouts
217 | Holds the template files for layouts to be used with views. This models the
218 | common header/footer method of wrapping views. In your views, define a layout
219 | using the layout :default and create a file named default.html.erb.
220 | Inside default.html.erb, call <% yield %> to render the view using this
221 | layout.
222 |
223 | app/helpers
224 | Holds view helpers that should be named like weblogs_helper.rb. These are
225 | generated for you automatically when using generators for controllers.
226 | Helpers can be used to wrap functionality for your views into methods.
227 |
228 | config
229 | Configuration files for the Rails environment, the routing map, the database,
230 | and other dependencies.
231 |
232 | db
233 | Contains the database schema in schema.rb. db/migrate contains all the
234 | sequence of Migrations for your schema.
235 |
236 | doc
237 | This directory is where your application documentation will be stored when
238 | generated using rake doc:app
239 |
240 | lib
241 | Application specific libraries. Basically, any kind of custom code that
242 | doesn't belong under controllers, models, or helpers. This directory is in
243 | the load path.
244 |
245 | public
246 | The directory available for the web server. Also contains the dispatchers and the
247 | default HTML files. This should be set as the DOCUMENT_ROOT of your web
248 | server.
249 |
250 | script
251 | Helper scripts for automation and generation.
252 |
253 | test
254 | Unit and functional tests along with fixtures. When using the rails generate
255 | command, template test files will be generated for you and placed in this
256 | directory.
257 |
258 | vendor
259 | External libraries that the application depends on. Also includes the plugins
260 | subdirectory. If the app has frozen rails, those gems also go here, under
261 | vendor/rails/. This directory is in the load path.
262 |
--------------------------------------------------------------------------------
/config/initializers/devise.rb:
--------------------------------------------------------------------------------
1 | # Use this hook to configure devise mailer, warden hooks and so forth. The first
2 | # four configuration values can also be set straight in your models.
3 | Devise.setup do |config|
4 | # ==> Mailer Configuration
5 | # Configure the e-mail address which will be shown in Devise::Mailer,
6 | # note that it will be overwritten if you use your own mailer class with default "from" parameter.
7 | config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
8 |
9 | # Configure the class responsible to send e-mails.
10 | # config.mailer = "Devise::Mailer"
11 |
12 | # ==> ORM configuration
13 | # Load and configure the ORM. Supports :active_record (default) and
14 | # :mongoid (bson_ext recommended) by default. Other ORMs may be
15 | # available as additional gems.
16 | require 'devise/orm/active_record'
17 |
18 | # ==> Configuration for any authentication mechanism
19 | # Configure which keys are used when authenticating a user. The default is
20 | # just :email. You can configure it to use [:username, :subdomain], so for
21 | # authenticating a user, both parameters are required. Remember that those
22 | # parameters are used only when authenticating and not when retrieving from
23 | # session. If you need permissions, you should implement that in a before filter.
24 | # You can also supply a hash where the value is a boolean determining whether
25 | # or not authentication should be aborted when the value is not present.
26 | # config.authentication_keys = [ :email ]
27 |
28 | # Configure parameters from the request object used for authentication. Each entry
29 | # given should be a request method and it will automatically be passed to the
30 | # find_for_authentication method and considered in your model lookup. For instance,
31 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
32 | # The same considerations mentioned for authentication_keys also apply to request_keys.
33 | # config.request_keys = []
34 |
35 | # Configure which authentication keys should be case-insensitive.
36 | # These keys will be downcased upon creating or modifying a user and when used
37 | # to authenticate or find a user. Default is :email.
38 | config.case_insensitive_keys = [ :email ]
39 |
40 | # Configure which authentication keys should have whitespace stripped.
41 | # These keys will have whitespace before and after removed upon creating or
42 | # modifying a user and when used to authenticate or find a user. Default is :email.
43 | config.strip_whitespace_keys = [ :email ]
44 |
45 | # Tell if authentication through request.params is enabled. True by default.
46 | # config.params_authenticatable = true
47 |
48 | # Tell if authentication through HTTP Basic Auth is enabled. False by default.
49 | # config.http_authenticatable = false
50 |
51 | # If http headers should be returned for AJAX requests. True by default.
52 | # config.http_authenticatable_on_xhr = true
53 |
54 | # The realm used in Http Basic Authentication. "Application" by default.
55 | # config.http_authentication_realm = "Application"
56 |
57 | # It will change confirmation, password recovery and other workflows
58 | # to behave the same regardless if the e-mail provided was right or wrong.
59 | # Does not affect registerable.
60 | # config.paranoid = true
61 |
62 | # ==> Configuration for :database_authenticatable
63 | # For bcrypt, this is the cost for hashing the password and defaults to 10. If
64 | # using other encryptors, it sets how many times you want the password re-encrypted.
65 | #
66 | # Limiting the stretches to just one in testing will increase the performance of
67 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
68 | # a value less than 10 in other environments.
69 | config.stretches = Rails.env.test? ? 1 : 10
70 |
71 | # Setup a pepper to generate the encrypted password.
72 | # config.pepper = "579e13091633e07ec9c46c50e3dabfd213f01049393b5860757bdc119b069583b8ec7e230062c939fbd54e40bc54b23955e24df492b131d7045334dc2ac1a45f"
73 |
74 | # ==> Configuration for :confirmable
75 | # The time you want to give your user to confirm his account. During this time
76 | # he will be able to access your application without confirming. Default is 0.days
77 | # When confirm_within is zero, the user won't be able to sign in without confirming.
78 | # You can use this to let your user access some features of your application
79 | # without confirming the account, but blocking it after a certain period
80 | # (ie 2 days).
81 | # config.confirm_within = 2.days
82 |
83 | # Defines which key will be used when confirming an account
84 | # config.confirmation_keys = [ :email ]
85 |
86 | # ==> Configuration for :rememberable
87 | # The time the user will be remembered without asking for credentials again.
88 | # config.remember_for = 2.weeks
89 |
90 | # If true, a valid remember token can be re-used between multiple browsers.
91 | # config.remember_across_browsers = true
92 |
93 | # If true, extends the user's remember period when remembered via cookie.
94 | # config.extend_remember_period = false
95 |
96 | # If true, uses the password salt as remember token. This should be turned
97 | # to false if you are not using database authenticatable.
98 | config.use_salt_as_remember_token = true
99 |
100 | # Options to be passed to the created cookie. For instance, you can set
101 | # :secure => true in order to force SSL only cookies.
102 | # config.cookie_options = {}
103 |
104 | # ==> Configuration for :validatable
105 | # Range for password length. Default is 6..128.
106 | # config.password_length = 6..128
107 |
108 | # Email regex used to validate email formats. It simply asserts that
109 | # an one (and only one) @ exists in the given string. This is mainly
110 | # to give user feedback and not to assert the e-mail validity.
111 | # config.email_regexp = /\A[^@]+@[^@]+\z/
112 |
113 | # ==> Configuration for :timeoutable
114 | # The time you want to timeout the user session without activity. After this
115 | # time the user will be asked for credentials again. Default is 30 minutes.
116 | # config.timeout_in = 30.minutes
117 |
118 | # ==> Configuration for :lockable
119 | # Defines which strategy will be used to lock an account.
120 | # :failed_attempts = Locks an account after a number of failed attempts to sign in.
121 | # :none = No lock strategy. You should handle locking by yourself.
122 | # config.lock_strategy = :failed_attempts
123 |
124 | # Defines which key will be used when locking and unlocking an account
125 | # config.unlock_keys = [ :email ]
126 |
127 | # Defines which strategy will be used to unlock an account.
128 | # :email = Sends an unlock link to the user email
129 | # :time = Re-enables login after a certain amount of time (see :unlock_in below)
130 | # :both = Enables both strategies
131 | # :none = No unlock strategy. You should handle unlocking by yourself.
132 | # config.unlock_strategy = :both
133 |
134 | # Number of authentication tries before locking an account if lock_strategy
135 | # is failed attempts.
136 | # config.maximum_attempts = 20
137 |
138 | # Time interval to unlock the account if :time is enabled as unlock_strategy.
139 | # config.unlock_in = 1.hour
140 |
141 | # ==> Configuration for :recoverable
142 | #
143 | # Defines which key will be used when recovering the password for an account
144 | # config.reset_password_keys = [ :email ]
145 |
146 | # Time interval you can reset your password with a reset password key.
147 | # Don't put a too small interval or your users won't have the time to
148 | # change their passwords.
149 | config.reset_password_within = 2.hours
150 |
151 | # ==> Configuration for :encryptable
152 | # Allow you to use another encryption algorithm besides bcrypt (default). You can use
153 | # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
154 | # :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
155 | # and :restful_authentication_sha1 (then you should set stretches to 10, and copy
156 | # REST_AUTH_SITE_KEY to pepper)
157 | # config.encryptor = :sha512
158 |
159 | # ==> Configuration for :token_authenticatable
160 | # Defines name of the authentication token params key
161 | # config.token_authentication_key = :auth_token
162 |
163 | # If true, authentication through token does not store user in session and needs
164 | # to be supplied on each request. Useful if you are using the token as API token.
165 | # config.stateless_token = false
166 |
167 | # ==> Scopes configuration
168 | # Turn scoped views on. Before rendering "sessions/new", it will first check for
169 | # "users/sessions/new". It's turned off by default because it's slower if you
170 | # are using only default views.
171 | # config.scoped_views = false
172 |
173 | # Configure the default scope given to Warden. By default it's the first
174 | # devise role declared in your routes (usually :user).
175 | # config.default_scope = :user
176 |
177 | # Configure sign_out behavior.
178 | # Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
179 | # The default is true, which means any logout action will sign out all active scopes.
180 | # config.sign_out_all_scopes = true
181 |
182 | # ==> Navigation configuration
183 | # Lists the formats that should be treated as navigational. Formats like
184 | # :html, should redirect to the sign in page when the user does not have
185 | # access, but formats like :xml or :json, should return 401.
186 | #
187 | # If you have any extra navigational formats, like :iphone or :mobile, you
188 | # should add them to the navigational formats lists.
189 | #
190 | # The :"*/*" and "*/*" formats below is required to match Internet
191 | # Explorer requests.
192 | # config.navigational_formats = [:"*/*", "*/*", :html]
193 |
194 | # The default HTTP method used to sign out a resource. Default is :delete.
195 | config.sign_out_via = :delete
196 |
197 | # ==> OmniAuth
198 | # Add a new OmniAuth provider. Check the wiki for more information on setting
199 | # up on your models and hooks.
200 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
201 |
202 | # ==> Warden configuration
203 | # If you want to use other strategies, that are not supported by Devise, or
204 | # change the failure app, you can configure them inside the config.warden block.
205 | #
206 | # config.warden do |manager|
207 | # manager.failure_app = AnotherApp
208 | # manager.intercept_401 = false
209 | # manager.default_strategies(:scope => :user).unshift :some_external_strategy
210 | # end
211 | end
212 |
--------------------------------------------------------------------------------
157 | <% @delivery.comments.each do |comment| %> 158 |-
159 | <%= link_to_user comment.user %>:
160 | <%= comment.text %>
161 | <% if current_user == comment.user %>
162 | <%= link_to 'X', {:action => :comment_delete, :comment_id => comment.id},
163 | :method => :delete %>
164 | <% end %>
165 |
166 | <% end %>
167 |
168 | <% if user_signed_in? %> 169 | <%= form_tag({:action => :comment}, {:method => "post"}) do %> 170 | Add comment: <%= text_field_tag "comment[text]" %> <%= submit_tag "Post" %> 171 | <% end %> 172 | <% end %> 173 |