在更新模型对象生成总计之前更新价格字段的rails方法是什么?

问题描述 投票:0回答:1

我有一个订单,其中包含产品选择器和附加选项的布尔滑块。 我想在保存到数据库之前计算总价。 我在模型中使用 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)


ruby-on-rails before-save
1个回答
0
投票
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
    就足够了。

考虑使用 rubocoprubocop-rails 来指导您。

© www.soinside.com 2019 - 2024. All rights reserved.