DRYing Vues in Rails (number_to_currency)
-
05-07-2019 - |
Question
J'ai un code similaire à:
number_to_currency (line_item.price,: unit = & g;; £ ")
jonglant avec mes vues dans divers modèles. Étant donné que mon application ne traite qu'en livres sterling (£), ne dois-je pas la déplacer dans chacun de mes modèles afin que line_item.price
renvoie la chaîne telle qu'elle devrait être (c'est-à-dire number_to_currency (line_item.price ,: unit = > & £;)
et line_item.price
sont identiques. Je pense que, pour ce faire, je devrais:
def price
number_to_currency(self.price, :unit => "£")
end
mais cela ne fonctionne pas. Si prix
est déjà défini dans le modèle, Rails signale alors «niveau de pile trop important», lorsque je modifie prix déf.
en montant déf.
, puis il se plaint que number_to_currency
ne soit pas défini?
La solution
number_to_currency est un assistant de vue, il n'est donc pas disponible dans les modèles.
Vous pouvez enregistrer certains traits de clavier en définissant votre propre assistant dans application_helper.rb (afin qu'il soit disponible pour toutes les vues). P.ex.
def quid(price)
number_to_currency(price, :unit => "£")
end
Appelez-le ensuite dans les vues:
quid(line_item.price)
Autres conseils
Si vous souhaitez modifier la valeur par défaut pour l'ensemble de votre application, vous pouvez modifier config / locales / en.yml
Le mien ressemble à ceci:
# 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
Tout sauf l’unité est optionnel et reviendra à la valeur par défaut, mais je le mets donc je sais quelles valeurs je peux changer. vous pouvez également utiliser le & # 163; signe au lieu de & amp; pound;.
La raison de l'erreur de niveau de pile trop profond est que lorsque vous dites self.price
dans la méthode price
, vous créez une infinie appel récursif à votre méthode de tarification car vous avez maintenant remplacé la méthode d’accesseur normale. Pour éviter cela, vous devez accéder à la valeur du champ price à l'aide des attributs hash. par exemple. quelque chose comme:
def price
number_to_currency(attributes['price'], :unit => "£")
end
à l'exception du fait que number_to_currency
n'est pas disponible dans le code du modèle pour la raison que Larry K a décrite.
Voici mon approche de ce problème.
# /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
vous pouvez le faire dans vos modèles (et vous ne polluerez pas votre modèle avec des méthodes que vous n'utiliserez pas)
class Album < ActiveRecord::Base
include AppName::CurrencyHelper
def price
currency_to_number(amount)
end
end
alors, pour que tous vos points de vue soient mis à jour, incluez le module dans l'un de vos aides à l'application
module ApplicationHelper
# change default currency formatting to pounds..
include AppName::CurrencyHelper
end
Partout où vous utilisez l'assistant de numéro à devise, celui-ci sera formaté avec un symbole dièse, mais vous disposez également de toute la flexibilité de la méthode des rails d'origine afin que vous puissiez transmettre les options comme auparavant.
number_to_currency(amount, :unit => '
le reconvertira en un symbole dollar.
)
le reconvertira en un symbole dollar.
L’autre réponse concernant la création d’une autre méthode d’aide (prix) afin de simplifier la répétition est probablement la meilleure approche.
# /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
alors vous devriez pouvoir le faire dans la classe de modèle:
def price
helper = YourNamespace::Helper.instance
helper.number_to_currency(read_attribute('price'), :unit => "£")
end
À compter de Rails 3
Comme Larry K le décrit mais avec cette modification:
def quid(price)
number_to_currency(price, :unit => "£")
end