Как использовать вспомогательный метод "число в валюте" в модели, а не в представлении?
Я хотел бы использовать to_dollar метод в моей модели такой:
module JobsHelper
def to_dollar(amount)
if amount < 0
number_to_currency(amount.abs, :precision => 0, :format => "-%u%n")
else
number_to_currency(amount, :precision => 0)
end
end
end
class Job < ActiveRecord::Base
include JobsHelper
def details
return "Only " + to_dollar(part_amount_received) +
" out of " + to_dollar(price) + " received."
end
end
к сожалению,number_to_currency метод здесь не распознается:
неопределенный метод 'number_to_currency' для #
любые идеи как заставить его работать?
10 ответов:
он недоступен, потому что его использование в модели (как правило) нарушает MVC (и, похоже, в вашем случае). Вы берете данные и манипулируете ими для презентации. Это, по определению, относится к представлению, а не к модели.
вот некоторые решения:
используйте презентатор или объект модели представления для посредничества между моделью и представлением. Это почти определенно требует больше первоначальной работы, чем другие решения, но почти всегда лучший дизайн. Использование помощников в presenter / view-model не нарушает MVC, поскольку они находятся в слое представления, заменяя традиционные пользовательские помощники Rails и логические представления.
явно
include ActionView::Helpers::NumberHelperinJobsHelperвместо того, чтобы зависеть от рельсов, чтобы волшебным образом загрузить его для вас. Это все еще не здорово, так как вы не должны обращаться к помощнику из модели.нарушить MVC & SRP. Смотрите fguillen это как это сделать. Я не буду повторять это здесь, потому что я не согласен с этим. Тем более, что я не согласен с загрязнением вашей модели методами представления, как в Сэм.
если вы думаете, "но мне очень нужно это писать
to_csv&to_pdfметоды в моей модели!- тогда вся ваша посылка неверна-в конце концов, у вас нетto_htmlметод, не так ли? И все же ваш объект очень часто отображается как HTML. Подумайте о создании нового класса для создания вашего вывод вместо того, чтобы сделать вашу модель данных знать, что такое CSV (потому что это не должно).Что касается использования помощников для ошибок проверки ActiveModel в модели, ну, мне жаль, но ActiveModel / Rails завинтил нас всех там, заставляя сообщения об ошибках реализовываться на уровне данных, а не возвращать семантический идея ошибки, которая будет реализована позже -вздох. Вы можете обойти это, но это в основном означает, что вы не используете ActiveModel:: ошибок больше нет. Я сделал это, это хорошо работает.
в стороне, вот полезный способ включить помощников в presenter / view-model, не загрязняя его набор методов (потому что это можно сделать, например
MyPresenterOrViewModel.new.link_to(...)нет смысла):class MyPresenterOrViewModel def some_field helper.number_to_currency(amount, :precision => 0) end private def helper @helper ||= Class.new do include ActionView::Helpers::NumberHelper end.new end end
Я согласен со всеми вами, что это может нарушить шаблон MVC, но всегда есть причины нарушить шаблон, в моем случае мне нужны эти методы форматирования валюты до используйте их в шаблоне фильтра (жидкость в моем случае).
в конце я узнал, что могу получить доступ к этим методы форматирования валюты используя такие вещи, как это:
ActionController::Base.helpers.number_to_currency
Я знаю, что этот поток очень старый, но кто-то может искать решение этой проблемы в Rails 4. Разработчики добавили ActiveSupport:: NumberHelper, который можно использовать без доступа к модулям/классам, связанным с представлением, используя:
ActiveSupport::NumberHelper.number_to_currency(amount, precision: 0)
необходимо также включить ActionView:: Helpers:: NumberHelper
class Job < ActiveRecord::Base include ActionView::Helpers::NumberHelper include JobsHelper def details return "Only " + to_dollar(part_amount_received) + " out of " + to_dollar(price) + " received." end end
Piggybacking от
@fguillenответ, я хотел переопределитьnumber_to_currencyметод в моемApplicationHelperмодуль, так что если значение было0илиblankчто он будет выводить тире вместо этого.вот мой код на случай, если вы, ребята, найдете что-то подобное полезным:
module ApplicationHelper def number_to_currency(value) if value == 0 or value.blank? raw "–" else ActionController::Base.helpers.number_to_currency(value) end end end
путь@fguillen хорош, хотя вот немного более чистый подход, особенно учитывая, что вопрос делает две ссылки на
to_dollar. Сначала я продемонстрирую использование кода Райана Бейтса (http://railscasts.com/episodes/132-helpers-outside-views).def description "This category has #{helpers.pluralize(products.count, 'product')}." end def helpers ActionController::Base.helpers endобратите внимание на звонок
helpers.pluralize. Это возможно благодаря определению метода (def helpers), которая просто возвращаетActionController::Base.helpers. Поэтомуhelpers.pluralizeсокращенноActionController::Base.helpers.pluralize. Теперь вы можете использоватьhelpers.pluralizeнесколько раз, без повторения длинных путей модуля.поэтому я полагаю, что ответ на этот конкретный вопрос может быть:
class Job < ActiveRecord::Base include JobsHelper def details return "Only " + helpers.to_dollar(part_amount_received) + " out of " + helpers.to_dollar(price) + " received." end def helpers ActionView::Helpers::NumberHelper end end
это не очень хорошая практика, но она работает для меня!
для импорта включите ActionView::Helpers:: NumberHelper в контроллере. Например:
class ProveedorController < ApplicationController include ActionView::Helpers::NumberHelper # layout 'example' # GET /proveedores/filtro # GET /proveedores/filtro.json def filtro @proveedores = Proveedor.all respond_to do |format| format.html # filtro.html.erb format.json { render json: @proveedores } end end def valuacion_cartera @total_valuacion = 0 facturas.each { |fac| @total_valuacion = @total_valuacion + fac.SumaDeImporte } @total = number_to_currency(@total_valuacion, :unit => "$ ") p '*'*80 p @total_valuacion end endнадеюсь, что это поможет вам!
очень удивлен, что ни один человек не говорил об использовании декоратора. Их цель-решить проблему, с которой вы столкнулись, и многое другое.
https://github.com/drapergem/draper
EDIT: похоже, что принятый ответ в основном предлагал сделать что-то вроде этого. Но да, вы хотите использовать декораторов. Вот отличный учебник серии, чтобы помочь вам понять еще:
https://gorails.com/episodes/decorators-from-scratch?autoplay=1
С. П. - @excid3 я принимаю бесплатное членство месяцев ЛОЛ
вспомогательные методы обычно используются для просмотра файлов. Не рекомендуется использовать эти методы в классе модели. Но если вы хотите использовать, то ответ Сэма в порядке. Или я предлагаю вам написать свой собственный метод.
Comments