ما هي أفضل طريقة التعامل مع العملات/المال ؟
-
06-07-2019 - |
سؤال
أنا أعمل على أساسي جدا نظام عربة التسوق.
لدي جدول 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
، وهو عظيم لحساب السعر.
إذا كنت تصر على استخدام الأعداد الصحيحة، سيكون لديك لتحويل يدويا من وإلى BigDecimal
s في كل مكان، والتي من المحتمل أن تصبح مجرد ألم.
وكما أشار مكل، لطباعة الأسعار، والاستخدام:
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