我有一个订单,其中包含产品选择器和附加选项的布尔滑块。 我想在保存到数据库之前计算总价。 我在模型中使用 before_save :set_total 操作,但我无法更改价格字段的值。 模型值是只读的吗? 如果是这样,我应该将模型对象“set_total”放在哪里来影响价格值? 我认为使用保存后 :set_total 和更新 olineorders set Price = #{tot Price};
并不明智我的模型文件提取:
class Olineorder < ApplicationRecord
before_save :set_total
(other stuff in here)
private
def set_total
puts "\n\ndef set_total"
puts "\tprice: #{price.inspect}\t#{Olineorder.inspect}\t\n"
@a = Price.find_by_sql("select pr.product_id, pr.price as theprice, p.name from prices as pr, products as p where pr.product_id == p.id;")
@b = Hash.new
@a.each do |f|
@b[f.name] = f.theprice.to_f
# puts f.name, f.theprice
end
totprice = @b["#{selection}"]
totprice += @b["Certificate"] if cert == true
totprice += @b["Biographical Skectch"] if bio == true
totprice += @b["Photograph"] if pic == true
self.price = printf('$%.2f',totprice)
==>Note: I al so tried: price = .... with same result. <===
puts "\n\tprice: #{price.inspect} -- total price -- #{totprice}\t#{Olineorder.inspect}\t\n"
puts "\ndef_set_toal ---<<< END\n"
end
```
Below is the logging output in the development.log
------------------ Output in log file ---------------
Started POST "/olineorders" for ::1 at 2024-10-14 18:04:10 -0700
Processing by OlineordersController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "olineorder"=>{--REDACTED---, "selection"=>"Worker's Brick", "cert"=>"true", "bio"=>"true", "pic"=>"true", "brick1"=>"", "brick2"=>"", "brick3"=>"", "price"=>"0.00", "comments"=>"", "block"=>"", "log"=>"0", "status"=>""}, "commit"=>"Create Olineorder"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = ? ORDER BY "users"."id" ASC LIMIT ? [["remember_token", "[FILTERED]"], ["LIMIT", 1]]
↳ app/controllers/application_controller.rb:14:in `ck_for_accs_level'
Product Load (0.1ms) select id, name from products;
↳ app/controllers/olineorders_controller.rb:113:in `set_product_list'
def set_total
price: "0.00" Olineorder(id: integer, last_name: string, first_name: string, address1: string, address2: string, city: string, state: string, zip: string, phone: string, email: string, selection: string, cert: boolean, bio: boolean, pic: boolean, comments: string, block: string, log: string, brick1: string, brick2: string, brick3: string, status: string, price: string, created_at: datetime, updated_at: datetime)
TRANSACTION (0.0ms) begin transaction
↳ app/models/olineorder.rb:35:in `set_total'
Price Load (0.4ms) select pr.product_id, pr.price as theprice, p.name from prices as pr, products as p where pr.product_id == p.id;
↳ app/models/olineorder.rb:35:in `set_total'
$135.00
price: nil -- total price -- 135.0 Olineorder(id: integer--redacted---, price: string, created_at: datetime, updated_at: datetime)
def_set_toal ---<<< END
Olineorder Create (0.1ms) INSERT INTO "olineorders" (---redacted---- "price", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING "id" [---REDACTED---, ["price", "0.00"], ["created_at", "2024-10-15 01:04:11.142454"], ["updated_at", "2024-10-15 01:04:11.142454"]]
↳ app/controllers/olineorders_controller.rb:41:in `block in create'
TRANSACTION (0.6ms) commit transaction
↳ app/controllers/olineorders_controller.rb:41:in `block in create'
Redirected to http://localhost:3000/olineorders/17
Completed 302 Found in 41ms (ActiveRecord: 2.8ms (4 queries, 0 cached) | GC: 1.0ms)
Started GET "/olineorders/17" for ::1 at 2024-10-14 18:04:11 -0700
Processing by OlineordersController#show as HTML
Parameters: {"id"=>"17"}
Olineorder Load (0.1ms) SELECT "olineorders".* FROM "olineorders" WHERE "olineorders"."id" = ? LIMIT ? [["id", 17], ["LIMIT", 1]]
↳ app/controllers/olineorders_controller.rb:109:in `set_olineorder'
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = ? ORDER BY "users"."id" ASC LIMIT ? [["remember_token", "[FILTERED]"], ["LIMIT", 1]]
↳ app/controllers/application_controller.rb:14:in `ck_for_accs_level'
Product Load (0.0ms) select id, name from products;
↳ app/controllers/olineorders_controller.rb:113:in `set_product_list'
Rendering layout layouts/application.html.erb
Rendering olineorders/show.html.erb within layouts/application
Rendered olineorders/_olineorder.html.erb (Duration: 0.3ms | GC: 0.0ms)
Rendered olineorders/show.html.erb within layouts/application (Duration: 1.7ms | GC: 0.0ms)
Rendered layouts/_pg_links.html.erb (Duration: 0.4ms | GC: 0.0ms)
Rendered layout layouts/application.html.erb (Duration: 3.3ms | GC: 0.1ms)
Completed 200 OK in 9ms (Views: 5.0ms | ActiveRecord: 0.2ms (3 queries, 0 cached) | GC: 0.2ms)
self.price = printf('$%.2f',totprice)
printf
用于打印并返回 nil
,因此会执行 self.price = nil
。你想要sprintf
。
如果
price
是一个数字,您可能不想在其中添加 $
。通常避免向数据库中的数字添加格式,这会使它们更难以使用。在这种情况下,请使用 Numeric#round
。
self.price = totprice.round(2)
@a
和 @b
是对象上将持续存在的实例变量。您可能不希望这样,并且您可能会意外覆盖其他实例变量,例如 @price
。如果您只需要在方法中使用局部变量,请使用 a
和 b
...但不要使用 a
和 b
,请使用描述性名称。如果您想了解 Ruby 中的实例变量,请参阅阅读本文。if cert == true
。 if cert
就足够了。考虑使用 rubocop 和 rubocop-rails 来指导您。