سؤال

أنا أعمل على أساسي جدا نظام عربة التسوق.

لدي جدول items يحتوي العمود price من نوع integer.

أواجه مشكلة في عرض السعر القيمة في آرائي عن الأسعار التي تشمل كلا من اليورو سنتا.أنا في عداد المفقودين شيء واضح بقدر التعامل مع العملة في القضبان الإطار المعنية ؟

هل كانت مفيدة؟

المحلول

وأنت ربما تريد استخدام نوع DECIMAL في قاعدة البيانات. في الترحيل، أن تفعل شيئا من هذا القبيل:

# precision is the total number of digits
# scale is the number of digits to the right of the decimal point
add_column :items, :price, :decimal, :precision => 8, :scale => 2

في القضبان، يتم إرجاع نوع :decimal كما BigDecimal، وهو عظيم لحساب السعر.

إذا كنت تصر على استخدام الأعداد الصحيحة، سيكون لديك لتحويل يدويا من وإلى BigDecimals في كل مكان، والتي من المحتمل أن تصبح مجرد ألم.

وكما أشار مكل، لطباعة الأسعار، والاستخدام:

number_to_currency(price, :unit => "€")
#=> €1,234.01

نصائح أخرى

وهنا غرامة بسيطة نهج روافع composed_of (جزء من ActiveRecord باستخدام ValueObject نمط) والمال جوهرة

سوف تحتاج

  • على المال جوهرة (الإصدار 4.1.0)
  • نموذج على سبيل المثال Product
  • وهو integer عمود في النموذج الخاص بك (قاعدة البيانات) ، على سبيل المثال :price

أكتب هذا في product.rb ملف:

class Product > ActiveRecord::Base

  composed_of :price,
              :class_name => 'Money',
              :mapping => %w(price cents),
              :converter => Proc.new { |value| Money.new(value) }
  # ...

ما ستحصل عليه:

  • دون أي تغييرات إضافية, جميع النماذج الخاصة بك سوف تظهر الدولارات والسنتات, ولكن التمثيل الداخلي لا يزال مجرد سنتات.أشكال يقبل القيم مثل "$12,034.95" وتحويله بالنسبة لك.ليس هناك حاجة لإضافة المزيد معالجات أو سمات النموذج الخاص بك أو المساعدين في الرأي.
  • product.price = "$12.00" يحول تلقائيا إلى المال فئة
  • product.price.to_s يعرض عشري تنسيق رقم ("1234.00")
  • product.price.format يعرض بشكل صحيح تنسيق سلسلة العملة
  • إذا كنت بحاجة إلى إرسال سنتا (إلى بوابة الدفع التي يريد بنسات), product.price.cents.to_s
  • تحويل العملات مجانا

والممارسة الشائعة للتعامل مع العملة هو استخدام نوع عشري. هنا مثال بسيط من "الشبكة العالمية للتنمية رشيق مع القضبان"

add_column :products, :price, :decimal, :precision => 8, :scale => 2 

وهذا سوف يسمح لك للتعامل مع الاسعار من -999،999.99 إلى 999،999.99
قد تحتاج أيضا لتشمل التحقق من الصحة في البنود الخاصة بك مثل

def validate 
  errors.add(:price, "should be at least 0.01") if price.nil? || price < 0.01 
end 

وإلى التعقل، تحقق القيم الخاصة بك.

المال القضبان جوهرة . ومن لطيف يتعامل مع المال والعملات في النموذج الخاص بك وأيضا لديه مجموعة من المساعدين لتهيئة الأسعار الخاصة بك.

إذا كنت تستخدم بوستجرس (وبما أننا في عام 2017 الآن) قد ترغب في إعطاء العمود :money من نوع المحاولة.

add_column :products, :price, :money, default: 0

باستخدام الظاهري سمات (رابط المنقحة(المدفوعة) Railscast) يمكنك تخزين الخاص بك price_in_cents في صحيح عمود إضافة السمة الافتراضية price_in_dollars في المنتج الخاص بك نموذج باعتبارها جالبة واضعة.

# Add a price_in_cents integer column
$ rails g migration add_price_in_cents_to_products price_in_cents:integer

# Use virtual attributes in your Product model
# app/models/product.rb

def price_in_dollars
  price_in_cents.to_d/100 if price_in_cents
end

def price_in_dollars=(dollars)
  self.price_in_cents = dollars.to_d*100 if dollars.present?
end

المصدر: RailsCasts #016: الظاهري سمات: الظاهري الصفات هي وسيلة نظيفة إضافة حقول النموذج التي لا خريطة مباشرة إلى قاعدة البيانات.أنا هنا تظهر كيفية التعامل مع التصديقات, جمعيات, وأكثر من ذلك.

صحيحة .

وعلى الرغم من BigDecimal موجود من الناحية الفنية 1.5 سوف لا تزال تعطي لك تعويم النقي في روبي.

إذا شخص ما يستخدم تكملة الهجرة من شأنه أن تبدو شيئا مثل:

add_column :products, :price, "decimal(8,2)"

وبطريقة أو بأخرى تكملة يتجاهل: الدقة و: مقياس

و(تتمة الإصدار: تتمة (3.39.0، 3.38.0))

وأنا استخدامه على هذا النحو:

number_to_currency(amount, unit: '€', precision: 2, format: "%u %n")

وبطبيعة الحال أن رمز العملة، والدقة، وشكل وهلم جرا يعتمد على كل عملة.

ويمكنك تمرير بعض الخيارات لnumber_to_currency (أ القضبان القياسية 4 رأي المساعد):

number_to_currency(12.0, :precision => 2)
# => "$12.00"

كما أرسلت بواسطة ديلان Markow

واجهات برمجة التطبيقات الأساسية بلدي كانت جميع استخدام سنتا لتمثيل المال، وأنا لم أكن أريد لتغيير ذلك. ولا كنت أعمل مع كميات كبيرة من المال. لذلك أنا فقط وضعت هذا في أسلوب مساعد:

sprintf("%03d", amount).insert(-3, ".")

وهذا يحول عدد صحيح إلى سلسلة مع لا يقل عن ثلاثة أرقام (إضافة أصفار بادئة إذا لزم الأمر)، ثم إدراج العلامة العشرية قبل آخر رقمين، أبدا باستخدام Float. من هناك يمكنك إضافة أي شيء رموز العملة مناسبة لحالة استخدامك.

وانها <م> بالتأكيد سريعة وقذرة، ولكن في بعض الأحيان أن ما يرام!

كود بسيط روبي & القضبان

<%= number_to_currency(1234567890.50) %>

OUT PUT => $1,234,567,890.50

فقط القليل من التحديث و تماسك جميع الإجابات لبعض الطامحين الصغار/للمبتدئين في RoR التنمية التي سوف تأتي بالتأكيد هنا بعض التفسيرات.

العمل مع المال

استخدام :decimal تخزين المال في ديسيبل ، كما @molf اقترح (و ما تستخدم الشركة بمثابة المعيار الذهبي عند العمل مع المال).

# precision is the total number of digits
# scale is the number of digits to the right of the decimal point
add_column :items, :price, :decimal, precision: 8, scale: 2

بعض النقاط:

  • :decimal سوف تستخدم BigDecimal الذي يحل الكثير من القضايا.

  • precision و scale يجب أن يتم تعديلها ، اعتمادا على ما كنت تمثل

    • إذا كنت تعمل مع استقبال وإرسال المدفوعات ، precision: 8 و scale: 2 يعطيك 999,999.99 كما أعلى مبلغ ، التي على ما يرام في 90% من الحالات.

    • إذا كنت بحاجة إلى تمثل قيمة من عقار أو سيارة نادرة, يجب عليك استخدام أعلى precision.

    • إذا كنت تعمل مع الإحداثيات (خطوط الطول والعرض) ، سوف تحتاج بالتأكيد أعلى scale.

كيفية إنشاء ملف الهجرة

لتوليد الهجرة مع محتوى أعلاه, تشغيل في الطرفية:

bin/rails g migration AddPriceToItems price:decimal{8-2}

أو

bin/rails g migration AddPriceToItems 'price:decimal{5,2}'

كما هو موضح في هذا بلوق ما بعد.

العملة التنسيق

قبلة اضافية المكتبات وداعا واستخدام المدمج في المساعدين.استخدام number_to_currency كما @molf و @facundofarias المقترحة.

للعب مع number_to_currency مساعد في القضبان تحكم إرسال دعوة إلى ActiveSupport's NumberHelper فئة من أجل الوصول إلى المساعد.

على سبيل المثال:

ActiveSupport::NumberHelper.number_to_currency(2_500_000.61, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")

يعطي الإخراج التالي

2500000,61€

التحقق من الأخرى options من number_to_currency المساعد.

حيث وضعه

يمكنك وضعه في تطبيق المساعد واستخدامها داخل وجهات النظر على أي مبلغ.

module ApplicationHelper    
  def format_currency(amount)
    number_to_currency(amount, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

أو يمكنك وضعه في Item نموذج كمثال الطريقة نسميها حيث تحتاج إلى تنسيق السعر (في وجهات النظر أو المساعدين).

class Item < ActiveRecord::Base
  def format_price
    number_to_currency(price, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

و مثال كيف يمكنني استخدام number_to_currency داخل contrroler (لاحظ negative_format الخيار يستخدم لتمثيل المبالغ المستردة)

def refund_information
  amount_formatted = 
    ActionController::Base.helpers.number_to_currency(@refund.amount, negative_format: '(%u%n)')
  {
    # ...
    amount_formatted: amount_formatted,
    # ...
  }
end
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top