diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..d591965 --- /dev/null +++ b/Gemfile @@ -0,0 +1,31 @@ +source 'http://rubygems.org' + +gem 'rails', '3.0.0.beta3' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'sqlite3-ruby', :require => 'sqlite3' +gem 'nifty-generators' +gem 'authlogic', :git => 'git://github.com/odorcicd/authlogic.git', :branch => 'rails3' +gem 'formtastic', :git => "git://github.com/justinfrench/formtastic.git", :branch => 'rails3' +gem 'cancan' +gem 'activemerchant', :git => 'http://github.com/merbjedi/active_merchant.git', :branch => 'rails3' + +# Use unicorn as the web server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# Bundle the extra gems: +# gem 'bj' +# gem 'nokogiri', '1.4.1' +# gem 'sqlite3-ruby', :require => 'sqlite3' +# gem 'aws-s3', :require => 'aws/s3' + +# Bundle gems for certain environments: +# gem 'rspec', :group => :test +# group :test do +# gem 'webrat' +# end diff --git a/README b/README new file mode 100644 index 0000000..ded8570 --- /dev/null +++ b/README @@ -0,0 +1,244 @@ +== Welcome to Rails + +Rails is a web-application framework that includes everything needed to create +database-backed web applications according to the Model-View-Control pattern. + +This pattern splits the view (also called the presentation) into "dumb" templates +that are primarily responsible for inserting pre-built data in between HTML tags. +The model contains the "smart" domain objects (such as Account, Product, Person, +Post) that holds all the business logic and knows how to persist themselves to +a database. The controller handles the incoming requests (such as Save New Account, +Update Product, Show Post) by manipulating the model and directing data to the view. + +In Rails, the model is handled by what's called an object-relational mapping +layer entitled Active Record. This layer allows you to present the data from +database rows as objects and embellish these data objects with business logic +methods. You can read more about Active Record in +link:files/vendor/rails/activerecord/README.html. + +The controller and view are handled by the Action Pack, which handles both +layers by its two parts: Action View and Action Controller. These two layers +are bundled in a single package due to their heavy interdependence. This is +unlike the relationship between the Active Record and Action Pack that is much +more separate. Each of these packages can be used independently outside of +Rails. You can read more about Action Pack in +link:files/vendor/rails/actionpack/README.html. + + +== Getting Started + +1. At the command prompt, start a new Rails application using the rails command + and your application name. Ex: rails myapp +2. Change directory into myapp and start the web server: rails server (run with --help for options) +3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!" +4. Follow the guidelines to start developing your application + + +== Web Servers + +By default, Rails will try to use Mongrel if it's installed when started with rails server, otherwise +Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails +with a variety of other web servers. + +Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is +suitable for development and deployment of Rails applications. If you have Ruby Gems installed, +getting up and running with mongrel is as easy as: gem install mongrel. +More info at: http://mongrel.rubyforge.org + +Say other Ruby web servers like Thin and Ebb or regular web servers like Apache or LiteSpeed or +Lighttpd or IIS. The Ruby web servers are run through Rack and the latter can either be setup to use +FCGI or proxy to a pack of Mongrels/Thin/Ebb servers. + +== Apache .htaccess example for FCGI/CGI + +# General Apache options +AddHandler fastcgi-script .fcgi +AddHandler cgi-script .cgi +Options +FollowSymLinks +ExecCGI + +# If you don't want Rails to look in certain directories, +# use the following rewrite rules so that Apache won't rewrite certain requests +# +# Example: +# RewriteCond %{REQUEST_URI} ^/notrails.* +# RewriteRule .* - [L] + +# Redirect all requests not available on the filesystem to Rails +# By default the cgi dispatcher is used which is very slow +# +# For better performance replace the dispatcher with the fastcgi one +# +# Example: +# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L] +RewriteEngine On + +# If your Rails application is accessed via an Alias directive, +# then you MUST also set the RewriteBase in this htaccess file. +# +# Example: +# Alias /myrailsapp /path/to/myrailsapp/public +# RewriteBase /myrailsapp + +RewriteRule ^$ index.html [QSA] +RewriteRule ^([^.]+)$ $1.html [QSA] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^(.*)$ dispatch.cgi [QSA,L] + +# In case Rails experiences terminal errors +# Instead of displaying this message you can supply a file here which will be rendered instead +# +# Example: +# ErrorDocument 500 /500.html + +ErrorDocument 500 "

Application error

Rails application failed to start properly" + + +== Debugging Rails + +Sometimes your application goes wrong. Fortunately there are a lot of tools that +will help you debug it and get it back on the rails. + +First area to check is the application log files. Have "tail -f" commands running +on the server.log and development.log. Rails will automatically display debugging +and runtime information to these files. Debugging info will also be shown in the +browser on requests from 127.0.0.1. + +You can also log your own messages directly into the log file from your code using +the Ruby logger class from inside your controllers. Example: + + class WeblogController < ActionController::Base + def destroy + @weblog = Weblog.find(params[:id]) + @weblog.destroy + logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") + end + end + +The result will be a message in your log file along the lines of: + + Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1 + +More information on how to use the logger is at http://www.ruby-doc.org/core/ + +Also, Ruby documentation can be found at http://www.ruby-lang.org/ including: + +* The Learning Ruby (Pickaxe) Book: http://www.ruby-doc.org/docs/ProgrammingRuby/ +* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) + +These two online (and free) books will bring you up to speed on the Ruby language +and also on programming in general. + + +== Debugger + +Debugger support is available through the debugger command when you start your Mongrel or +Webrick server with --debugger. This means that you can break out of execution at any point +in the code, investigate and change the model, AND then resume execution! +You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug' +Example: + + class WeblogController < ActionController::Base + def index + @posts = Post.find(:all) + debugger + end + end + +So the controller will accept the action, run the first line, then present you +with a IRB prompt in the server window. Here you can do things like: + + >> @posts.inspect + => "[#nil, \"body\"=>nil, \"id\"=>\"1\"}>, + #\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]" + >> @posts.first.title = "hello from a debugger" + => "hello from a debugger" + +...and even better is that you can examine how your runtime objects actually work: + + >> f = @posts.first + => #nil, "body"=>nil, "id"=>"1"}> + >> f. + Display all 152 possibilities? (y or n) + +Finally, when you're ready to resume execution, you enter "cont" + + +== Console + +You can interact with the domain model by starting the console through rails console. +Here you'll have all parts of the application configured, just like it is when the +application is running. You can inspect domain models, change values, and save to the +database. Starting the script without arguments will launch it in the development environment. +Passing an argument will specify a different environment, like rails console production. + +To reload your controllers and models after launching the console run reload! + +== dbconsole + +You can go to the command line of your database directly through rails dbconsole. +You would be connected to the database with the credentials defined in database.yml. +Starting the script without arguments will connect you to the development database. Passing an +argument will connect you to a different database, like rails dbconsole production. +Currently works for mysql, postgresql and sqlite. + +== Description of Contents + +app + Holds all the code that's specific to this particular application. + +app/controllers + Holds controllers that should be named like weblogs_controller.rb for + automated URL mapping. All controllers should descend from ApplicationController + which itself descends from ActionController::Base. + +app/models + Holds models that should be named like post.rb. + Most models will descend from ActiveRecord::Base. + +app/views + Holds the template files for the view that should be named like + weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby + syntax. + +app/views/layouts + Holds the template files for layouts to be used with views. This models the common + header/footer method of wrapping views. In your views, define a layout using the + layout :default and create a file named default.html.erb. Inside default.html.erb, + call <% yield %> to render the view using this layout. + +app/helpers + Holds view helpers that should be named like weblogs_helper.rb. These are generated + for you automatically when using rails generate for controllers. Helpers can be used to + wrap functionality for your views into methods. + +config + Configuration files for the Rails environment, the routing map, the database, and other dependencies. + +db + Contains the database schema in schema.rb. db/migrate contains all + the sequence of Migrations for your schema. + +doc + This directory is where your application documentation will be stored when generated + using rake doc:app + +lib + Application specific libraries. Basically, any kind of custom code that doesn't + belong under controllers, models, or helpers. This directory is in the load path. + +public + The directory available for the web server. Contains subdirectories for images, stylesheets, + and javascripts. Also contains the dispatchers and the default HTML files. This should be + set as the DOCUMENT_ROOT of your web server. + +script + Helper scripts for automation and generation. + +test + Unit and functional tests along with fixtures. When using the rails generate command, template + test files will be generated for you and placed in this directory. + +vendor + External libraries that the application depends on. Also includes the plugins subdirectory. + If the app has frozen rails, those gems also go here, under vendor/rails/. + This directory is in the load path. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..9cb2046 --- /dev/null +++ b/Rakefile @@ -0,0 +1,10 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +Rails::Application.load_tasks diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000..9901113 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,22 @@ +class ApplicationController < ActionController::Base + helper_method :current_user_session, :current_user + + protect_from_forgery + layout 'application' + + rescue_from CanCan::AccessDenied do |exception| + flash[:error] = "Access denied." + redirect_to root_url + end + + private + def current_user_session + return @current_user_session if defined?(@current_user_session) + @current_user_session = UserSession.find + end + + def current_user + return @current_user if defined?(@current_user) + @current_user = current_user_session && current_user_session.user + end +end diff --git a/app/controllers/charities_controller.rb b/app/controllers/charities_controller.rb new file mode 100644 index 0000000..1ee828c --- /dev/null +++ b/app/controllers/charities_controller.rb @@ -0,0 +1,40 @@ +class CharitiesController < ApplicationController + load_and_authorize_resource + + def index + @charities = Charity.all + end + + def show + end + + def new + end + + def create + if @charity.save + flash[:notice] = "Successfully created charity." + redirect_to charities_path + else + render :action => 'new' + end + end + + def edit + end + + def update + if @charity.update_attributes(params[:charity]) + flash[:notice] = "Successfully updated charity." + redirect_to @charity + else + render :action => 'edit' + end + end + + def destroy + @charity.destroy + flash[:notice] = "Successfully destroyed charity." + redirect_to charities_url + end +end diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb new file mode 100644 index 0000000..e6bf34e --- /dev/null +++ b/app/controllers/companies_controller.rb @@ -0,0 +1,40 @@ +class CompaniesController < ApplicationController + load_and_authorize_resource + + def index + @companies = Company.all + end + + def show + end + + def new + end + + def create + if @company.save + flash[:notice] = "Successfully created company." + redirect_to companies_url + else + render :action => 'new' + end + end + + def edit + end + + def update + if @company.update_attributes(params[:company]) + flash[:notice] = "Successfully updated company." + redirect_to companies_url + else + render :action => 'edit' + end + end + + def destroy + @company.destroy + flash[:notice] = "Successfully removed company." + redirect_to companies_url + end +end diff --git a/app/controllers/deals_controller.rb b/app/controllers/deals_controller.rb new file mode 100644 index 0000000..b35d99f --- /dev/null +++ b/app/controllers/deals_controller.rb @@ -0,0 +1,46 @@ +class DealsController < ApplicationController + load_and_authorize_resource + + def index + if params[:city_name] + city = City.where(:name => params[:city_name].capitalize) + + @deals = Deal.where('city_id = ?', city) + else + @deals = Deal.all + end + end + + def show + end + + def new + end + + def create + if @deal.save + flash[:notice] = "Successfully created deal." + redirect_to deals_path + else + render :action => 'new' + end + end + + def edit + end + + def update + if @deal.update_attributes(params[:deal]) + flash[:notice] = "Successfully updated deal." + redirect_to @deal + else + render :action => 'edit' + end + end + + def destroy + @deal.destroy + flash[:notice] = "Successfully destroyed deal." + redirect_to deals_url + end +end diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb new file mode 100644 index 0000000..9bd8901 --- /dev/null +++ b/app/controllers/static_controller.rb @@ -0,0 +1,8 @@ +class StaticController < ApplicationController + def index + render :layout => 'welcome' + end + + def dashboard + end +end diff --git a/app/controllers/user_sessions_controller.rb b/app/controllers/user_sessions_controller.rb new file mode 100644 index 0000000..4a8bf54 --- /dev/null +++ b/app/controllers/user_sessions_controller.rb @@ -0,0 +1,26 @@ +class UserSessionsController < ApplicationController + def new + @user_session = UserSession.new + end + + def create + @user_session = UserSession.new(params[:user_session]) + if @user_session.save + flash[:notice] = "Successfully Logged In." + if current_user.role == 'admin' + redirect_to admin_url + else + redirect_to root_url + end + else + render :action => 'new' + end + end + + def destroy + @user_session = UserSession.find + @user_session.destroy + flash[:notice] = "Successfully Logged Out." + redirect_to root_url + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000..3969929 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,51 @@ +class UsersController < ApplicationController + load_and_authorize_resource + + def index + if params[:city_name] + city = City.where(:name => params[:city_name].capitalize) + + @users = User.where("city_id = ?", city) + else + @users = User.all + end + end + + def new + end + + def create + if @user.save + flash[:notice] = "Registration Successful." + if current_user.role == 'admin' + redirect_to users_path + else + redirect_to login_path + end + else + render :action => 'new' + end + end + + def edit + end + + def update + if @user.update_attributes(params[:user]) + flash[:notice] = "Successfully updated user." + if current_user.role == 'admin' + redirect_to users_path + else + redirect_to root_url + end + else + render :action => 'edit' + end + end + + def destroy + @user.destroy + flash[:notice] = "Successfully removed user." + redirect_to users_url + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/app/helpers/charities_helper.rb b/app/helpers/charities_helper.rb new file mode 100644 index 0000000..c2cd1a9 --- /dev/null +++ b/app/helpers/charities_helper.rb @@ -0,0 +1,2 @@ +module CharitiesHelper +end diff --git a/app/helpers/cities_helper.rb b/app/helpers/cities_helper.rb new file mode 100644 index 0000000..dce779d --- /dev/null +++ b/app/helpers/cities_helper.rb @@ -0,0 +1,2 @@ +module CitiesHelper +end diff --git a/app/helpers/companies_helper.rb b/app/helpers/companies_helper.rb new file mode 100644 index 0000000..099b151 --- /dev/null +++ b/app/helpers/companies_helper.rb @@ -0,0 +1,2 @@ +module CompaniesHelper +end diff --git a/app/helpers/deals_helper.rb b/app/helpers/deals_helper.rb new file mode 100644 index 0000000..06e9e16 --- /dev/null +++ b/app/helpers/deals_helper.rb @@ -0,0 +1,2 @@ +module DealsHelper +end diff --git a/app/helpers/error_messages_helper.rb b/app/helpers/error_messages_helper.rb new file mode 100644 index 0000000..9257573 --- /dev/null +++ b/app/helpers/error_messages_helper.rb @@ -0,0 +1,23 @@ +module ErrorMessagesHelper + # Render error messages for the given objects. The :message and :header_message options are allowed. + def error_messages_for(*objects) + options = objects.extract_options! + options[:header_message] ||= "Invalid Fields" + options[:message] ||= "Correct the following errors and try again." + messages = objects.compact.map { |o| o.errors.full_messages }.flatten + unless messages.empty? + content_tag(:div, :class => "error_messages") do + list_items = messages.map { |msg| content_tag(:li, msg) } + content_tag(:h2, options[:header_message]) + content_tag(:p, options[:message]) + content_tag(:ul, list_items.join.html_safe) + end + end + end + + module FormBuilderAdditions + def error_messages(options = {}) + @template.error_messages_for(@object, options) + end + end +end + +ActionView::Helpers::FormBuilder.send(:include, ErrorMessagesHelper::FormBuilderAdditions) diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb new file mode 100644 index 0000000..7c5ce50 --- /dev/null +++ b/app/helpers/layout_helper.rb @@ -0,0 +1,22 @@ +# These helper methods can be called in your template to set variables to be used in the layout +# This module should be included in all views globally, +# to do so you may need to add this line to your ApplicationController +# helper :layout +module LayoutHelper + def title(page_title, show_title = true) + content_for(:title) { page_title.to_s } + @show_title = show_title + end + + def show_title? + @show_title + end + + def stylesheet(*args) + content_for(:head) { stylesheet_link_tag(*args) } + end + + def javascript(*args) + content_for(:head) { javascript_include_tag(*args) } + end +end diff --git a/app/helpers/static_helper.rb b/app/helpers/static_helper.rb new file mode 100644 index 0000000..8cfc9af --- /dev/null +++ b/app/helpers/static_helper.rb @@ -0,0 +1,2 @@ +module StaticHelper +end diff --git a/app/helpers/user_session_helper.rb b/app/helpers/user_session_helper.rb new file mode 100644 index 0000000..99f0a96 --- /dev/null +++ b/app/helpers/user_session_helper.rb @@ -0,0 +1,2 @@ +module UserSessionHelper +end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb new file mode 100644 index 0000000..2310a24 --- /dev/null +++ b/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +end diff --git a/app/models/ability.rb b/app/models/ability.rb new file mode 100644 index 0000000..bf1ee1e --- /dev/null +++ b/app/models/ability.rb @@ -0,0 +1,21 @@ +class Ability + include CanCan::Ability + + def initialize(user) + user ||= User.new #for non-logged in visitors + + if user.role == "admin" + can :manage, :all + else + if user.role == "metro" + can :read, :all + else + can :create, User + can [:show, :edit, :update], User do |current_user| + user.id == current_user.id || user.role == "admin" + end + end + end + + end +end \ No newline at end of file diff --git a/app/models/charity.rb b/app/models/charity.rb new file mode 100644 index 0000000..b82af1c --- /dev/null +++ b/app/models/charity.rb @@ -0,0 +1,3 @@ +class Charity < ActiveRecord::Base + attr_accessible :name, :description +end diff --git a/app/models/city.rb b/app/models/city.rb new file mode 100644 index 0000000..81b800f --- /dev/null +++ b/app/models/city.rb @@ -0,0 +1,4 @@ +class City < ActiveRecord::Base + attr_accessible :name, :state_id + belongs_to :state +end diff --git a/app/models/company.rb b/app/models/company.rb new file mode 100644 index 0000000..fc614ce --- /dev/null +++ b/app/models/company.rb @@ -0,0 +1,5 @@ +class Company < ActiveRecord::Base + attr_accessible :name, :phone, :address, :city_id, :zip_code, :website + belongs_to :city + belongs_to :deal +end diff --git a/app/models/deal.rb b/app/models/deal.rb new file mode 100644 index 0000000..cb4d552 --- /dev/null +++ b/app/models/deal.rb @@ -0,0 +1,5 @@ +class Deal < ActiveRecord::Base + attr_accessible :name, :description, :regular_price, :initial_discount, :max_discount, :max_threshold, :deal_date, :city_id, :company_id + belongs_to :company + belongs_to :city +end diff --git a/app/models/state.rb b/app/models/state.rb new file mode 100644 index 0000000..bd66835 --- /dev/null +++ b/app/models/state.rb @@ -0,0 +1,4 @@ +class State < ActiveRecord::Base + attr_accessible :name, :abbreviation + has_many :cities +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..80dd437 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,8 @@ +class User < ActiveRecord::Base + acts_as_authentic + + attr_accessible :username, :email, :password, :password_confirmation, :city_id, :role + belongs_to :city + + ROLES = %w[admin metro] +end diff --git a/app/models/user_session.rb b/app/models/user_session.rb new file mode 100644 index 0000000..8c19d19 --- /dev/null +++ b/app/models/user_session.rb @@ -0,0 +1,2 @@ +class UserSession < Authlogic::Session::Base +end \ No newline at end of file diff --git a/app/views/charities/_form.html.erb b/app/views/charities/_form.html.erb new file mode 100644 index 0000000..7ce99eb --- /dev/null +++ b/app/views/charities/_form.html.erb @@ -0,0 +1,7 @@ +<%= semantic_form_for( @charity, :html => { :class => "normal_form" } ) do |f| %> + <%= f.inputs do %> + <%= f.input :name %> + <%= f.input :description, :input_html => { :size => '40x6' } %> + <% end %> + <%= image_submit_tag 'submit.png', :class => 'signup' %> +<% end %> diff --git a/app/views/charities/edit.html.erb b/app/views/charities/edit.html.erb new file mode 100644 index 0000000..67e162d --- /dev/null +++ b/app/views/charities/edit.html.erb @@ -0,0 +1,7 @@ +<% title "Edit Charity" %> + +<%= render 'form' %> + + diff --git a/app/views/charities/index.html.erb b/app/views/charities/index.html.erb new file mode 100644 index 0000000..c98bf8a --- /dev/null +++ b/app/views/charities/index.html.erb @@ -0,0 +1,17 @@ +<% title "Charities" %> + + + + + + + <% for charity in @charities %> + + + + + + <% end %> +
NameDescription
<%= link_to charity.name, edit_charity_path(charity) %><%= charity.description %><%= link_to "Delete", charity, :confirm => 'Are you sure?', :method => :delete %>
+ +

<%= link_to "New Charity", new_charity_path %>

diff --git a/app/views/charities/new.html.erb b/app/views/charities/new.html.erb new file mode 100644 index 0000000..ecdb69b --- /dev/null +++ b/app/views/charities/new.html.erb @@ -0,0 +1,5 @@ +<% title "New Charity" %> + +<%= render 'form' %> + + diff --git a/app/views/charities/show.html.erb b/app/views/charities/show.html.erb new file mode 100644 index 0000000..d1e8e63 --- /dev/null +++ b/app/views/charities/show.html.erb @@ -0,0 +1,16 @@ +<% title "Charity" %> + +

+ Name: + <%= @charity.name %> +

+

+ Description: + <%= @charity.description %> +

+ +

+ <%= link_to "Edit", edit_charity_path(@charity) %> | + <%= link_to "Destroy", @charity, :confirm => 'Are you sure?', :method => :delete %> | + <%= link_to "View All", charities_path %> +

diff --git a/app/views/companies/_form.html.erb b/app/views/companies/_form.html.erb new file mode 100644 index 0000000..7159bc0 --- /dev/null +++ b/app/views/companies/_form.html.erb @@ -0,0 +1,11 @@ +<%= semantic_form_for( @company, :html => { :class => 'normal_form' } ) do |f| %> + <%= f.inputs do %> + <%= f.input :name %> + <%= f.input :address %> + <%= f.input :city, :collection => @cities, :group_by => :state, :include_blank => false %> + <%= f.input :zip_code %> + <%= f.input :phone %> + <%= f.input :website %> + <% end %> + <%= image_submit_tag 'submit.png', :class => 'signup' %> +<% end %> diff --git a/app/views/companies/edit.html.erb b/app/views/companies/edit.html.erb new file mode 100644 index 0000000..48bfa54 --- /dev/null +++ b/app/views/companies/edit.html.erb @@ -0,0 +1,7 @@ +<% title "Edit Company" %> + +<%= render 'form' %> + + diff --git a/app/views/companies/index.html.erb b/app/views/companies/index.html.erb new file mode 100644 index 0000000..a4f85ab --- /dev/null +++ b/app/views/companies/index.html.erb @@ -0,0 +1,19 @@ +<% title "Companies" %> + + + + + + + + <% for company in @companies %> + + + + + + + <% end %> +
CompanyCityState
<%= link_to company.name, edit_company_path(company) %><%= company.city.name %><%= company.city.state.abbreviation %><%= link_to "Delete", company, :confirm => 'Are you sure?', :method => :delete %>
+ + diff --git a/app/views/companies/new.html.erb b/app/views/companies/new.html.erb new file mode 100644 index 0000000..6650abd --- /dev/null +++ b/app/views/companies/new.html.erb @@ -0,0 +1,5 @@ +<% title "New Company" %> + +<%= render 'form' %> + + diff --git a/app/views/companies/show.html.erb b/app/views/companies/show.html.erb new file mode 100644 index 0000000..c0a40d9 --- /dev/null +++ b/app/views/companies/show.html.erb @@ -0,0 +1,22 @@ +<% title "Company" %> + +
+

+ <%= link_to @company.name, edit_company_path(@company) %> +

+

+ <%= @company.phone %> +

+

+ <%= @company.address %>
+ <%= @company.city.name %>, <%= @company.city.state.abbreviation %> <%= @company.zip_code %> +

+

+ <%= link_to @company.website, @company.website, :target => "blank" %> +

+
+ + diff --git a/app/views/deals/_form.html.erb b/app/views/deals/_form.html.erb new file mode 100644 index 0000000..2d158aa --- /dev/null +++ b/app/views/deals/_form.html.erb @@ -0,0 +1,18 @@ +<%= semantic_form_for( @deal, :html => { :class => "normal_form"} ) do |f| %> + <%= f.inputs do %> + <%= f.input :name %> + <%= f.input :description %> + <%= f.input :company, :collection => @companies %> + <%= f.input :city, :collection => @cities, :group_by => :state %> + <%= f.input :regular_price %> + <%= f.input :initial_discount %> + <%= f.input :max_discount %> + <%= f.input :max_threshold %> + <%= f.input :deal_date, :as => :string %> + <% if current_user.role == 'admin' %> + <%= f.input :approved %> + <% end %> + <% end %> + + <%= image_submit_tag 'submit.png', :class => 'signup' %> +<% end %> diff --git a/app/views/deals/edit.html.erb b/app/views/deals/edit.html.erb new file mode 100644 index 0000000..4f744d5 --- /dev/null +++ b/app/views/deals/edit.html.erb @@ -0,0 +1,7 @@ +<% title "Edit Deal" %> + +<%= render 'form' %> + + diff --git a/app/views/deals/index.html.erb b/app/views/deals/index.html.erb new file mode 100644 index 0000000..f38ab87 --- /dev/null +++ b/app/views/deals/index.html.erb @@ -0,0 +1,25 @@ +<% title "Deals" %> + + + + + + + + + + + <% for deal in @deals %> + + + + + + + + + + <% end %> +
NameDescriptionRegular PriceInitial DiscountMax DiscountMax Threshold
<%= link_to deal.name, edit_deal_path(deal) %><%= deal.description %>$<%= deal.regular_price %><%= deal.initial_discount %>%<%= deal.max_discount %>%<%= deal.max_threshold %> buys<%= link_to "Delete", deal, :confirm => 'Are you sure?', :method => :delete %>
+ + diff --git a/app/views/deals/new.html.erb b/app/views/deals/new.html.erb new file mode 100644 index 0000000..794e766 --- /dev/null +++ b/app/views/deals/new.html.erb @@ -0,0 +1,5 @@ +<% title "New Deal" %> + +<%= render 'form' %> + + diff --git a/app/views/deals/show.html.erb b/app/views/deals/show.html.erb new file mode 100644 index 0000000..763108f --- /dev/null +++ b/app/views/deals/show.html.erb @@ -0,0 +1,32 @@ +<% title "Deal" %> + +

+ Name: + <%= @deal.name %> +

+

+ Description: + <%= @deal.description %> +

+

+ Regular Price: + <%= @deal.regular_price %> +

+

+ Initial Discount: + <%= @deal.initial_discount %> +

+

+ Max Discount: + <%= @deal.max_discount %> +

+

+ Max Threshold: + <%= @deal.max_threshold %> +

+ +

+ <%= link_to "Edit", edit_deal_path(@deal) %> | + <%= link_to "Destroy", @deal, :confirm => 'Are you sure?', :method => :delete %> | + <%= link_to "View All", deals_path %> +

diff --git a/app/views/layouts/_adminlinks.html.erb b/app/views/layouts/_adminlinks.html.erb new file mode 100644 index 0000000..a219844 --- /dev/null +++ b/app/views/layouts/_adminlinks.html.erb @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb new file mode 100644 index 0000000..2ee48da --- /dev/null +++ b/app/views/layouts/_footer.html.erb @@ -0,0 +1,12 @@ +
+ +
\ No newline at end of file diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb new file mode 100644 index 0000000..bf0c2c9 --- /dev/null +++ b/app/views/layouts/_header.html.erb @@ -0,0 +1,18 @@ +
+
+ +
+ <% if current_user %> + <%= link_to current_user.username, edit_user_path(current_user) %> | <%= link_to "Sign Out", logout_path %> + <% else %> + <%= link_to "Sign Up", register_path %> or <%= link_to "Sign In", login_path %> + <% end %> +
+
+
\ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000..9b39fd6 --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,30 @@ + + + + <%= yield(:title) || "SugarSave" %> + <%= stylesheet_link_tag "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/redmond/jquery-ui.css", + 'reset', 'application2', 'flash' %> + <%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", + "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js", "application", "rails" %> + <%= csrf_meta_tag %> + <%= yield(:head) %> + + + <%= render :partial => '/layouts/header' %> +
+
+ <% flash.each do |name, msg| %> + <%= content_tag :div, msg, :id => "flash_#{name}", :class => "hideable" %> + <% end %> + + <% if current_user.try(:role) == 'admin' %> + <%= render :partial => '/layouts/adminlinks' %> + <% end %> + + <%= yield %> + +
+
+ <%= render :partial => '/layouts/footer' %> + + diff --git a/app/views/layouts/welcome.html.erb b/app/views/layouts/welcome.html.erb new file mode 100644 index 0000000..aaba72c --- /dev/null +++ b/app/views/layouts/welcome.html.erb @@ -0,0 +1,52 @@ + + + + <%= yield(:title) || "SugarSave" %> + <%= stylesheet_link_tag 'reset', 'welcome', 'flash' %> + <%= javascript_include_tag 'jquery', 'welcome' %> + <%= csrf_meta_tag %> + <%= yield(:head) %> + + +
+
+ +
+ <% if current_user %> + <%= link_to current_user.username, edit_user_path(current_user) %> | <%= link_to "Sign Out", logout_path %> + <% else %> + <%= link_to "Sign Up", register_path %> or <%= link_to "Sign In", login_path %> + <% end %> +
+
+ + <% flash.each do |name, msg| %> + <%= content_tag :div, msg, :id => "flash_#{name}", :class => "hideable" %> + <% end %> + +
+ + <%= yield %> + +
+
+
+ +
+ + diff --git a/app/views/static/dashboard.html.erb b/app/views/static/dashboard.html.erb new file mode 100644 index 0000000..c56513f --- /dev/null +++ b/app/views/static/dashboard.html.erb @@ -0,0 +1 @@ +<% title "Admin Dashboard" %> diff --git a/app/views/static/index.html.erb b/app/views/static/index.html.erb new file mode 100644 index 0000000..2d720f1 --- /dev/null +++ b/app/views/static/index.html.erb @@ -0,0 +1,17 @@ +<% title "Welcome" %> + +
+ <%= image_tag('tagline.png') %> +
+ +
+ <%= image_tag('comingsoon.png', :width => '920px') %> +
+ +
+ <%= image_tag('get-deals.png', :id => 'get-deals') %> +
+ +
+ <%= image_tag('feature-business.png', :id => 'feature-business') %> +
\ No newline at end of file diff --git a/app/views/user_sessions/new.html.erb b/app/views/user_sessions/new.html.erb new file mode 100644 index 0000000..18f5d23 --- /dev/null +++ b/app/views/user_sessions/new.html.erb @@ -0,0 +1,10 @@ +<% title "Login" %> + +<%= semantic_form_for( @user_session, :html => { :class => "pretty_form" } ) do |f| %> + <%= f.inputs do %> + <%= f.input :username %> + <%= f.input :password %> + <% end %> + + <%= image_submit_tag 'signin.png', :class => 'signup' %> +<% end %> \ No newline at end of file diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb new file mode 100644 index 0000000..aad3d48 --- /dev/null +++ b/app/views/users/edit.html.erb @@ -0,0 +1,16 @@ +<% title "Edit Your Information" %> + +<%= semantic_form_for( @user, :html => { :class => "pretty_form" } ) do |f| %> + <%= f.inputs do %> + <%= f.input :username %> + <%= f.input :email %> + <%= f.input :password %> + <%= f.input :password_confirmation %> + <%= f.input :city, :collection => @cities, :group_by => :state, :include_blank => false %> + <% if current_user.try(:role) == 'admin' %> + <%= f.input :role, :collection => User::ROLES %> + <% end %> + <% end %> + + <%= image_submit_tag 'update.png', :class => 'signup' %> +<% end %> \ No newline at end of file diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000..ebda12c --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,21 @@ +<% title "Users" %> + + + + + + + + + <% for user in @users %> + + + + + + + + <% end %> +
UsernameEmailCityRegistration Date
<%= link_to user.username, edit_user_path(user) %><%= user.email %><%= user.city.name %><%= user.created_at.strftime("%b %d, %Y") %><%= link_to "Delete", user, :confirm => 'Are you sure?', :method => :delete %>
+ + diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb new file mode 100644 index 0000000..29d4a57 --- /dev/null +++ b/app/views/users/new.html.erb @@ -0,0 +1,16 @@ +<% title "New User Registration" %> + +<%= semantic_form_for( @user, :html => { :class => "pretty_form" } ) do |f| %> + <%= f.inputs do %> + <%= f.input :username %> + <%= f.input :email %> + <%= f.input :password %> + <%= f.input :password_confirmation %> + <%= f.input :city, :collection => @cities, :group_by => :state, :include_blank => false %> + <% if current_user.try(:role) == 'admin' %> + <%= f.input :role, :collection => User::ROLES %> + <% end %> + <% end %> + + <%= image_submit_tag 'signup.png', :class => 'signup' %> +<% end %> \ No newline at end of file diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..279c6dd --- /dev/null +++ b/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Sugar::Application diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 0000000..0da7ee2 --- /dev/null +++ b/config/application.rb @@ -0,0 +1,46 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +# If you have a Gemfile, require the gems listed there, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(:default, Rails.env) if defined?(Bundler) + +module Sugar + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Add additional load paths for your own custom dirs + # config.load_paths += %W( #{config.root}/extras ) + + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + + # Activate observers that should always be running + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Configure generators values. Many other options are available, be sure to check the documentation. + # config.generators do |g| + # g.orm :active_record + # g.template_engine :erb + # g.test_framework :test_unit, :fixture => true + # end + + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = "utf-8" + + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password, :password_confirmation] + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000..712b098 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,6 @@ +require 'rubygems' +# Set up gems listed in the Gemfile. +if File.exist?(File.expand_path('../../Gemfile', __FILE__)) + require 'bundler' + Bundler.setup +end diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000..e140b49 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the rails application +require File.expand_path('../application', __FILE__) + +# Initialize the rails application +Sugar::Application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000..bc65c3f --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,33 @@ +Sugar::Application.configure do + # Settings specified here will take precedence over those in config/environment.rb + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the webserver when you make code changes. + config.cache_classes = false + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_view.debug_rjs = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = false + + # ActiveMerchant setup + # config.after_initialize do + # ActiveMerchant::Billing::Base.mode = :test + # end + # + # config.to_prepare do + # OrderTransaction.gateway = + # ActiveMerchant::Billing::AuthorizeNetGateway.new( + # :login => '8Y6gAv8p', + # :password => '326EsxLh5252W7ku', + # :test => true + # ) + # end +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000..7435bdd --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,42 @@ +Sugar::Application.configure do + # Settings specified here will take precedence over those in config/environment.rb + + # The production environment is meant for finished, "live" apps. + # Code is not reloaded between requests + config.cache_classes = true + + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Specifies the header that your server uses for sending files + config.action_dispatch.x_sendfile_header = "X-Sendfile" + + # For nginx: + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' + + # If you have no front-end server that supports something like X-Sendfile, + # just comment this out and Rails will serve the files + + # See everything in the log (default is :info) + # config.log_level = :debug + + # Use a different logger for distributed setups + # config.logger = SyslogLogger.new + + # Use a different cache store in production + # config.cache_store = :mem_cache_store + + # Disable Rails's static asset server + # In production, Apache or nginx will already do this + config.serve_static_assets = false + + # Enable serving of images, stylesheets, and javascripts from an asset server + # config.action_controller.asset_host = "http://assets.example.com" + + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + + # Enable threaded mode + # config.threadsafe! +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000..3ba3ef6 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,32 @@ +Sugar::Application.configure do + # Settings specified here will take precedence over those in config/environment.rb + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true + + # Show full error reports and disable caching + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Use SQL instead of Active Record's schema dumper when creating the test database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + # config.active_record.schema_format = :sql +end diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/formtastic.rb b/config/initializers/formtastic.rb new file mode 100644 index 0000000..9fd7eea --- /dev/null +++ b/config/initializers/formtastic.rb @@ -0,0 +1,73 @@ +# Set the default text field size when input is a string. Default is 50. +# Formtastic::SemanticFormBuilder.default_text_field_size = 50 + +# Set the default text area height when input is a text. Default is 20. +Formtastic::SemanticFormBuilder.default_text_area_height = 5 + +# Should all fields be considered "required" by default? +# Defaults to true, see ValidationReflection notes below. +# Formtastic::SemanticFormBuilder.all_fields_required_by_default = true + +# Should select fields have a blank option/prompt by default? +# Defaults to true. +Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = false + +# Set the string that will be appended to the labels/fieldsets which are required +# It accepts string or procs and the default is a localized version of +# '*'. In other words, if you configure formtastic.required +# in your locale, it will replace the abbr title properly. But if you don't want to use +# abbr tag, you can simply give a string as below +# Formtastic::SemanticFormBuilder.required_string = "(required)" + +# Set the string that will be appended to the labels/fieldsets which are optional +# Defaults to an empty string ("") and also accepts procs (see required_string above) +# Formtastic::SemanticFormBuilder.optional_string = "(optional)" + +# Set the way inline errors will be displayed. +# Defaults to :sentence, valid options are :sentence, :list and :none +Formtastic::SemanticFormBuilder.inline_errors = :sentence + +# Set the method to call on label text to transform or format it for human-friendly +# reading when formtastic is user without object. Defaults to :humanize. +# Formtastic::SemanticFormBuilder.label_str_method = :humanize + +# Set the array of methods to try calling on parent objects in :select and :radio inputs +# for the text inside each @