DRYing Views в Rails (number_to_currency)
-
05-07-2019 - |
Вопрос
У меня есть код, похожий на:
number_to_currency (line_item.price,: unit = > " & # 163; ")
засорять мои взгляды в разных моделях. Поскольку мое приложение работает только в фунтах стерлингов (& # 163;), я не должен перемещать это в каждую из моих моделей, чтобы line_item.price
возвращал строку в том виде, в каком она должна быть (т.е. number_to_currency ( line_item.price,: unit = > " & # 163; ")
и line_item.price
одинаковы. Я думаю, что для этого мне нужно: р>
def price
number_to_currency(self.price, :unit => "£")
end
но это не работает. Если цена
уже определена в модели, то Rails сообщает о «слишком большом уровне стека», когда я изменяю def price
на def amount
, тогда он жалуется, что number_to_currency
не определено?
Решение
number_to_currency - помощник вида, поэтому он недоступен в моделях.
Вы можете сохранить некоторые нажатия клавиш, определив свой собственный помощник в application_helper.rb (чтобы он был доступен для всех представлений). Например,
def quid(price)
number_to_currency(price, :unit => "£")
end
Тогда назовите это в представлениях:
quid(line_item.price)
Другие советы
Если вы хотите изменить настройки по умолчанию для всего приложения, вы можете отредактировать config / locales / en.yml
Шахта выглядит так:
# Sample localization file for English. Add more files in this directory for other locales.
# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
"en":
number:
currency:
format:
format: "%u%n"
unit: "£"
# These three are to override number.format and are optional
separator: "."
delimiter: ","
precision: 2
Все, кроме единицы, является необязательным и будет иметь значение по умолчанию, но я вставил его, чтобы знать, какие значения я могу изменить. Вы также можете использовать & # 163; знак вместо & amp; фунт;.
Причина ошибки слишком большой уровень стека заключается в том, что когда вы говорите self.price
в методе price
, вы создаете бесконечное число рекурсивный вызов вашего метода цены, поскольку вы переопределили обычный метод доступа. Чтобы избежать этого, вам нужно получить доступ к значению поля цены, используя хэш атрибутов. например что-то вроде:
def price
number_to_currency(attributes['price'], :unit => "£")
end
за исключением того факта, что number_to_currency
недоступен в коде модели по причине, описанной Ларри К.
Вот мой подход к этой проблеме.
# /RAILS_ROOT/lib/app_name/currency_helper.rb
module AppName
module CurrencyHelper
include ActionView::Helpers::NumberHelper
def number_to_currency_with_pound(amount, options = {})
options.reverse_merge!({ :unit => '£' })
number_to_currency_without_pound(amount, options)
end
alias_method_chain :number_to_currency, :pound
end
end
в ваших моделях вы можете сделать это (и вы не будете загрязнять вашу модель методами, которые вы не собираетесь использовать)
class Album < ActiveRecord::Base
include AppName::CurrencyHelper
def price
currency_to_number(amount)
end
end
чтобы ваши представления обновлялись, включите модуль в одного из помощников вашего приложения
module ApplicationHelper
# change default currency formatting to pounds..
include AppName::CurrencyHelper
end
Теперь везде, где вы используете число, чтобы поменять валюту, оно будет отформатировано с символом фунта, но у вас также есть вся гибкость оригинального метода rails, поэтому вы можете передавать опции, как вы делали раньше.
number_to_currency(amount, :unit => '
преобразует его обратно в символ доллара.
)
преобразует его обратно в символ доллара.
Другой ответ, касающийся создания другого вспомогательного метода quid (price) для упрощения повторения, вероятно, является наилучшим подходом ... однако ... если вы действительно хотите получить доступ к помощникам вида в модели, вы можете сделать что-то вроде:
# /RAILS_ROOT/lib/your_namespace/helper.rb
#
# Need to access helpers in the model?
# YourNamespace::Helper.instance.helper_method_name
module YourNamespace
class Helper
include Singleton
include ActionView::Helpers
end
end
тогда вы сможете сделать это в классе модели:
def price
helper = YourNamespace::Helper.instance
helper.number_to_currency(read_attribute('price'), :unit => "£")
end
Начиная с Rails 3
Как описывает Ларри К, но с этим редактированием:
def quid(price)
number_to_currency(price, :unit => "£")
end