关键字: 学习笔记 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.}
以上代码 完全参考书本 考虑到 第一版的 代码下载官方网站已经没有提供了,所以特意贴出来,为今后无论是自己还是别人如果看的书是第一版的,免得输入累。
完整的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.}
以上代码 完全参考书本 考虑到 第一版的 代码下载官方网站已经没有提供了,所以特意贴出来,为今后无论是自己还是别人如果看的书是第一版的,免得输入累。