Как использовать вспомогательный метод "число в валюте" в модели, а не в представлении?



Я хотел бы использовать 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' для #




любые идеи как заставить его работать?

597   10  

10 ответов:

он недоступен, потому что его использование в модели (как правило) нарушает MVC (и, похоже, в вашем случае). Вы берете данные и манипулируете ими для презентации. Это, по определению, относится к представлению, а не к модели.

вот некоторые решения:

  • используйте презентатор или объект модели представления для посредничества между моделью и представлением. Это почти определенно требует больше первоначальной работы, чем другие решения, но почти всегда лучший дизайн. Использование помощников в presenter / view-model не нарушает MVC, поскольку они находятся в слое представления, заменяя традиционные пользовательские помощники Rails и логические представления.

  • явно include ActionView::Helpers::NumberHelper in JobsHelper вместо того, чтобы зависеть от рельсов, чтобы волшебным образом загрузить его для вас. Это все еще не здорово, так как вы не должны обращаться к помощнику из модели.

  • нарушить 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 "&ndash;"
    else
      ActionController::Base.helpers.number_to_currency(value)
    end
  end
end

можно использовать view_context.number_to_currency непосредственно от вас контроллер или модель.

путь@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

    Ничего не найдено.