关键字: 学习笔记 ruby on rails depot

完整的Depot应用源代码 Source Code

参考 《应用 Rails 进行敏捷 Web 开发》第一版

林芷薰 翻译
透明 审校

Database Files
数据库文件
D:\work\depot\config\database.yml

1.development:  
2.  adapter: mysql  
3.  database: depot_development  
4.  username: root  
5.  password:  
6.  host: localhost  
7.  
8.# Warning: The database defined as 'test' will be erased and  
9.# re-generated from your development database when you run 'rake'.  
10.# Do not set this db to the same as development or production.  
11.test:  
12.  adapter: mysql  
13.  database: depot_test  
14.  username: root  
15.  password:  
16.  host: localhost  
17.  
18.production:  
19.  adapter: mysql  
20.  database: depot_production  
21.  username: root  
22.  password:   
23.  host: localhost  
 

D:\work\depot\db\create.sql
 
1.drop table if exists users;  
2.drop table if exists line_items;  
3.drop table if exists orders;  
4.drop table if exists products;  
5.  
6.create table products (  
7.    id                          int                     not null auto_increment,  
8.    title                       varchar(100)    not null,  
9.    description         text                    not null,  
10.    image_url               varchar(200)    not null,  
11.    price                       decimal(10,2)   not null,  
12.    date_available  datetime            not null,  
13.    primary key(id)  
14.);  
15.  
16.create table orders (  
17.    id          int           not null auto_increment,  
18.    name              varchar(100)  not null,  
19.    email       varchar(255)  not null,  
20.    address     text          not null,  
21.    pay_type    char(10)      not null,  
22.    shipped_at  datetime      null,  
23.    primary key (id)  
24.);  
25.  
26.create table line_items (  
27.    id                          int                         not null auto_increment,  
28.    product_id          int                         not null,  
29.    order_id            int                         not null,  
30.    quantity                int                         not null default 0,  
31.    unit_price          decimal(10,2)       not null,  
32.    constraint fk_items_product foreign key (product_id) references products(id),  
33.    constraint fk_items_order foreign key (order_id) references orders(id),  
34.    primary key (id)  
35.);  
36.  
37.create table users (  
38.    id              int not null    auto_increment,  
39.    name            varchar(100)    not null,  
40.    hashed_password char(40)        null,  
41.    primary key (id)  
42.);  
43.  
44./* password = 'admin' */  
45.insert into users values(null, 'admin','d033e22ae348aeb5660fc2140aec35850c4da997');  
 

D:\work\depot\db\product_data.sql
 
1.lock tables products write;  
2.insert into products(   title, description, image_url, price, date_available ) values(  
3.                                            'Pragmatic Project Automation',  
4.                                            'A really great read!',  
5.                      'http://localhost:3000/images/svn.JPG',  
6.                      '29.95',  
7.                      '2007-12-25 05:00:00' );  
8.insert into products(   title, description, image_url, price, date_available ) values(  
9.                      'Pragmatic Version Control',  
10.                      'A really contrlooed read!',  
11.                      'http://localhost:3000/images/utc.jpg',  
12.                      '29.95',  
13.                      '2007-12-01 05:00:00');  
14.insert into products(  title, description, image_url, price, date_available ) values(  
15.                     'Pragmatic Version Control2',  
16.                     'A really contrlooed read!',  
17.                     'http://localhost:3000/images/auto.jpg',  
18.                     '29.95',  
19.                     '2007-12-01 05:00:00');  
20.unlock tables;  
 

D:\work\depot\db\product_data2.sql
 
1.lock tables products write;  
2.insert into products(   title, description, image_url, price, date_available ) values(  
3.                                            'Pragmatic Project Automation',  
4.                                            'A really great read!',  
5.                      '/images/svn.JPG',  
6.                      '29.95',  
7.                      '2007-12-25 05:00:00' );  
8.insert into products(   title, description, image_url, price, date_available ) values(  
9.                      'Pragmatic Version Control',  
10.                      'A really contrlooed read!',  
11.                      '/images/utc.jpg',  
12.                      '29.95',  
13.                      '2007-12-01 05:00:00');  
14.insert into products(  title, description, image_url, price, date_available ) values(  
15.                     'Pragmatic Version Control2',  
16.                     'A really contrlooed read!',  
17.                     '/images/auto.jpg',  
18.                     '29.95',  
19.                     '2007-12-01 05:00:00');  
20.unlock tables;  
 

控制器
D:\work\depot\app\controllers\application.rb
 
1.class ApplicationController < ActionController::Base  
2.    model :cart  
3.    model :line_item  
4.      
5.  # Pick a unique cookie name to distinguish our session data from others'  
6.  session :session_key => '_depot_session_id'  
7.  
8.  private  
9.  def redirect_to_index(msg = nil)  
10.    flash[:notice] = msg if msg  
11.    redirect_to(:action => 'index')  
12.  end  
13.    
14.  def authorize  
15.    unless session[:user_id]  
16.        flash[:notice] = "Please log in"  
17.        redirect_to(:controller => "login", :action => "login")  
18.    end  
19.  end  
20.    
21.end  
 

D:\work\depot\app\controllers\admin_controller.rb
 
1.class AdminController < ApplicationController      
2.    before_filter :authorize  
3.  
4.  # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)  
5.  verify :method => :post, :only => [ :destroy, :create, :update ],  
6.         :redirect_to => { :action => :list }  
7.           
8.  def index  
9.    list  
10.    render :action => 'list'  
11.  end  
12.    
13.  def list  
14.    @product_pages, @products = paginate :products, :per_page => 10  
15.  end  
16.  
17.  def show  
18.    @product = Product.find(params[:id])  
19.  end  
20.  
21.  def new  
22.    @product = Product.new  
23.  end  
24.  
25.  def create  
26.    @product = Product.new(params[:product])  
27.    if @product.save  
28.      flash[:notice] = 'Product was successfully created.'  
29.      redirect_to :action => 'list'  
30.    else  
31.      render :action => 'new'  
32.    end  
33.  end  
34.  
35.  def edit  
36.    @product = Product.find(params[:id])  
37.  end  
38.  
39.  def update  
40.    @product = Product.find(params[:id])  
41.    if @product.update_attributes(params[:product])  
42.      flash[:notice] = 'Product was successfully updated.'  
43.      redirect_to :action => 'show', :id => @product  
44.    else  
45.      render :action => 'edit'  
46.    end  
47.  end  
48.  
49.  def destroy  
50.    Product.find(params[:id]).destroy  
51.    redirect_to :action => 'list'  
52.  end  
53.    
54.  def ship  
55.    count = 0  
56.    if things_to_ship = params[:to_be_shipped]  
57.        count = do_shipping(things_to_ship)  
58.        if count > 0  
59.            count_text = pluralize(count, "order")  
60.            flash.now[:notice] = "#{count_text} marked as shipped"  
61.        end  
62.    end  
63.    @penging_orders = Order.pending_shipping  
64.  end  
65.    
66.  private  
67.  def do_shipping(things_to_ship)  
68.    count = 0  
69.    things_to_ship.each do |order_id, do_it|  
70.        if do_it == "yes"  
71.            order = Order.find(order_id)  
72.            order.mark_as_shipped  
73.            order.save  
74.            count += 1  
75.        end  
76.    end  
77.    count  
78.  end  
79.    
80.  def pluralize(count, noun)  
81.    case count  
82.    when 0: "No #{noun.pluralize}"  
83.    when 1: "One #{noun}"  
84.    else "#{count} #{noun.pluralize}"  
85.    end  
86.  end  
87.    
88.end  
 

D:\work\depot\app\controllers\login_controller.rb
 
1.class LoginController < ApplicationController  
2.    layout "admin"    
3.    before_filter :authorize, :except => :login  
4.      
5.    def index  
6.    @total_orders = Order.count  
7.    @pending_orders = Order.count_pending  
8.  end  
9.    
10.  def login  
11.    if request.get?  
12.        session[:user_id] = nil  
13.        @user = User.new  
14.    else  
15.        @user = User.new(params[:user])  
16.        logged_in_user = @user.try_to_login  
17.        if logged_in_user  
18.            session[:user_id] = logged_in_user.id  
19.            redirect_to(:action => "index")  
20.        else  
21.            flash[:notice] = "Invalid user/password conbination"  
22.        end  
23.    end  
24.  end  
25.      
26.  def add_user  
27.    if request.get?  
28.        @user = User.new  
29.    else  
30.        @user = User.new(params[:user])  
31.        if @user.save  
32.            redirect_to_index("User #{@user.name} created")  
33.        end  
34.    end  
35.  end  
36.    
37.  def delete_user  
38.    id = params[:id]  
39.    if id && user = User.find(id)  
40.        begin  
41.            user.destroy  
42.            flash[:notice] = "User #{user.name} deleted"  
43.        rescue  
44.            flash[:notice] = "Can't delete that user"  
45.        end  
46.    end  
47.    redirect_to(:action => :list_users)  
48.  end  
49.  
50.  def list_users  
51.    @all_users = User.find(:all)  
52.  end  
53.    
54.  def logout  
55.    session[:user_id] = nil  
56.    flash[:notice] = "Logged out"  
57.    redirect_to(:action => "login")  
58.  end  
59.  
60.end  
 


D:\work\depot\app\controllers\store_controller.rb
 
1.class StoreController < ApplicationController  
2.  
3.    before_filter :find_cart, :except => :index  
4.  
5.  def index  
6.    @products = Product.salable_items  
7.  end  
8.    
9.  def add_to_cart  
10.    product = Product.find(params[:id])  
11.    @cart.add_product(product)  
12.    redirect_to(:action => 'display_cart')  
13.  rescue  
14.    logger.error("Attempt to access invalid product #{params[:id]}")  
15.    redirect_to_index('Invalid product')  
16.  end  
17.  
18.  def display_cart  
19.    @items = @cart.items  
20.    if @items.empty?  
21.        redirect_to_index('Your cart is currently empty')  
22.    end  
23.    if params[:context] == :checkout  
24.        render(:layout => false)  
25.    end  
26.  end  
27.    
28.    def empty_cart  
29.        @cart.empty!  
30.        redirect_to_index('Your cart is now empty')  
31.    end  
32.    
33.  def checkout  
34.    @items = @cart.items  
35.    if @items.empty?  
36.        redirect_to_index("There's nothing in your cart!")  
37.    else  
38.        @order = Order.new  
39.    end  
40.  end  
41.    
42.  def save_order  
43.    @order = Order.new(params[:order])  
44.    @order.line_items << @cart.items  
45.    if @order.save  
46.        @cart.empty!  
47.        redirect_to_index('Thank you for your order.')  
48.    else  
49.        render(:action => 'checkout')  
50.    end  
51.  end  
52.    
53.  private    
54.  def find_cart  
55.    @cart = (session[:cart] ||= Cart.new)  
56.  end  
57.    
58.end  
 

模型
D:\work\depot\app\models\cart.rb
 
1.class Cart  
2.    attr_reader :items  
3.    attr_reader :total_price  
4.    def initialize  
5.        empty!  
6.    end  
7.      
8.    def empty!  
9.        @items = []  
10.        @total_price = 0.0  
11.    end  
12.      
13.    def add_product(product)  
14.        item = @items.find {|i| i.product_id == product.id}  
15.        if item  
16.            item.quantity += 1  
17.        else  
18.            item = LineItem.for_product(product)  
19.            @items << item  
20.        end  
21.        @total_price += product.price  
22.    end  
23.end  
 

D:\work\depot\app\models\line_item.rb
 
1.class LineItem < ActiveRecord::Base  
2.    belongs_to :product  
3.    belongs_to :order  
4.    def self.for_product(product)  
5.        item = self.new  
6.        item.quantity = 1  
7.        item.product = product  
8.        item.unit_price = product.price  
9.        item  
10.    end  
11.end  
 

D:\work\depot\app\models\order.rb
 
1.class Order < ActiveRecord::Base  
2.    has_many :line_items  
3.      
4.    PAYMENT_TYPES = [  
5.        [ "Check",                  "check"],  
6.        [ "Credit Card",        "cc"],  
7.        [ "Purchas Order",  "po"]  
8.    ].freeze  # freeze to make this array constant  
9.      
10.    validates_presence_of :name, :email, :address, :pay_type  
11.      
12.    def self.pending_shipping  
13.        find(:all, :conditions => "shipped_at is null")  
14.    end  
15.      
16.    def self.count_pending  
17.        count("shipped_at is null")  
18.    end  
19.      
20.    def mark_as_shipped  
21.        self.shipped_at = Time.now  
22.    end  
23.          
24.end  
 



D:\work\depot\app\models\product.rb
 
1.class Product < ActiveRecord::Base  
2.    validates_presence_of   :title, :description, :image_url  
3.    validates_numericality_of :price  
4.    validates_uniqueness_of :title  
5.    validates_format_of :image_url,  
6.                        :with    => %r{^http:.+\.(gif|jpg|png)$}i,  
7.                        :message => "must be a URL for a GIF, JPG, or PNG image"  
8.  
9.    def self.salable_items  
10.        find(:all,  
11.                 :conditions        =>   "date_available <= now()",  
12.                 :order                 => "date_available desc")  
13.    end   
14.      
15.    protected  
16.    def validate  
17.        errors.add(:price, "should be positive") unless price.nil? || price >= 0.01  
18.    end  
19.  
20.end  
 


D:\work\depot\app\models\user.rb
 
1.require "digest/sha1"  
2.class User < ActiveRecord::Base  
3.    attr_accessor :password  
4.    attr_accessible :name, :password  
5.    validates_uniqueness_of :name  
6.    validates_presence_of :name, :password  
7.  
8.    def self.login(name, password)  
9.        hashed_password = hash_password(password || "")  
10.        find(:first,  
11.             :conditions => ["name = ? and hashed_password = ?",  
12.                              name, hashed_password])  
13.    end  
14.      
15.    def try_to_login  
16.        User.login(self.name, self.password)  
17.        User.find_by_name_and_hashed_password(name, "")  
18.    end  
19.      
20.    def before_create  
21.        self.hashed_password = User.hash_password(self.password)  
22.    end  
23.  
24.      
25.    before_destroy :dont_destroy_admin  
26.    def dont_destroy_admin  
27.        raise "Can't destroy admin" if self.name == 'admin'  
28.    end  
29.          
30.    def after_create  
31.        @password = nil  
32.    end   
33.  
34.    private  
35.    def self.hash_password(password)  
36.        Digest::SHA1.hexdigest(password)  
37.    end  
38.      
39.end  
 


视图
D:\work\depot\app\views\layouts\admin.rhtml
 
1.<html>  
2.<head>  
3.  <title>ADMINISTER Pragprog Books Online Store</title>  
4.  <%= stylesheet_link_tag 'scaffold', 'depot', 'admin', :media => "all" %>  
5.</head>  
6.<body>  
7.    <div ;  
41.}  
42..olitemtitle {  
43.    font-weight: bold;  
44.}  
45..ListTitle {  
46.    color: #244;  
47.    font-weight: bold;  
48.    font-size: larger;  
49.}  
50..ListActions {  
51.    font-size: x-small;  
52.    text-align: right;  
53.    padding-left: lem;  
54.}  
55..ListLine0 {  
56.    background: #e0f8f8;  
57.}  
58..ListLine1 {  
59.    background: #f8e0f8;  
60.}  
 

D:\work\depot\public\stylesheets\scaffold.css
 
1.body { background-color: #fff; color: #333; }  
2.  
3.body, p, ol, ul, td {  
4.  font-family: verdana, arial, helvetica, sans-serif;  
5.  font-size:   13px;  
6.  line-height: 18px;  
7.}  
8.  
9.pre {  
10.  background-color: #eee;  
11.  padding: 10px;  
12.  font-size: 11px;  
13.}  
14.  
15.a { color: #000; }  
16.a:visited { color: #666; }  
17.a:hover { color: #fff; background-color:#000; }  
18.  
19..fieldWithErrors {  
20.  padding: 2px;  
21.  background-color: red;  
22.  display: table;  
23.}  
24.  
25.#errorExplanation {  
26.  width: 400px;  
27.  border: 2px solid red;  
28.  padding: 7px;  
29.  padding-bottom: 12px;  
30.  margin-bottom: 20px;  
31.  background-color: #f0f0f0;  
32.}  
33.  
34.#errorExplanation h2 {  
35.  text-align: left;  
36.  font-weight: bold;  
37.  padding: 5px 5px 5px 15px;  
38.  font-size: 12px;  
39.  margin: -7px;  
40.  background-color: #c00;  
41.  color: #fff;  
42.}  
43.  
44.#errorExplanation p {  
45.  color: #333;  
46.  margin-bottom: 0;  
47.  padding: 5px;  
48.}  
49.  
50.#errorExplanation ul li {  
51.  font-size: 12px;  
52.  list-style: square;  
53.}  
54.  
55.div.uploadStatus {  
56.  margin: 5px;  
57.}  
58.  
59.div.progressBar {  
60.  margin: 5px;  
61.}  
62.  
63.div.progressBar div.border {  
64.  background-color: #fff;  
65.  border: 1px solid grey;  
66.  width: 100%;  
67.}  
68.  
69.div.progressBar div.background {  
70.  background-color: #333;  
71.  height: 18px;  
72.  width: 0%;  
73.}  
74.  
75..ListTitle {  
76.    color:              #244;  
77.    font-weight:    bold;  
78.    font-size:      larger;  
79.}  
80.  
81..ListActions {  
82.    font-size:      x-small;  
83.    text-align:     right;  
84.    padding-left:   lem;  
85.}  
86.  
87..ListLine0 {  
88.    background:     #e0f8f8;  
89.}  
90.  
91..ListLine1 {  
92.    background:     #f8b0f8;  
93.}  
 

以上代码 完全参考书本 考虑到 第一版的 代码下载官方网站已经没有提供了,所以特意贴出来,为今后无论是自己还是别人如果看的书是第一版的,免得输入累。

相关文章:

  • 2021-06-23
  • 2021-12-22
  • 2022-01-08
  • 2021-12-19
  • 2021-07-04
  • 2021-08-20
  • 2021-11-28
  • 2021-06-27
猜你喜欢
  • 2022-12-23
  • 2021-12-02
  • 2021-12-27
  • 2022-02-20
  • 2021-07-19
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案