보기보다는 모델에서 "number_to_currency"도우미 메서드를 사용하는 방법은 무엇입니까?


93

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방법은 여기서 인식되지 않습니다.

# <Job : 0x311eb00>에 대한 정의되지 않은 메소드`number_to_currency '

작동하는 방법에 대한 아이디어가 있습니까?

답변:


103

모델에서의 사용이 (일반적으로) MVC를 위반하기 때문에 사용할 수 없습니다 (귀하의 경우에는 그렇게 보입니다). 데이터를 가져 와서 프레젠테이션을 위해 조작하고 있습니다. 이것은 정의상 모델이 아니라 뷰에 속합니다.

다음은 몇 가지 해결책입니다.

  • 발표자 또는보기 모델 개체를 사용하여 모델과보기를 중재합니다. 이것은 거의 확실히 다른 솔루션보다 더 많은 초기 작업이 필요하지만 거의 항상 더 나은 디자인입니다. 프레젠터 / 뷰 모델에서 헬퍼를 사용하는 것은 뷰 레이어에 상주하기 때문에 MVC를 위반하지 않으며, 전통적인 커스텀 Rails 헬퍼와 로직으로 채워진 뷰를 대체합니다.

  • Rails에 의존하는 대신 명시 적 include ActionView::Helpers::NumberHelper으로 JobsHelper마법처럼로드했습니다. 모델에서 도우미에 액세스하면 안되므로 여전히 좋지 않습니다.

  • MVC 및 SRP를 위반합니다 . 이를 수행하는 방법 은 fguillen의 답변 을 참조하십시오 . 나는 그것에 동의하지 않기 때문에 여기에서 그것을 반향하지 않을 것입니다. 그럼에도 불구하고 Sam의 답변 에서와 같이 프레젠테이션 방법으로 모델을 오염시키는 데 동의하지 않습니다 .

"하지만 내 모델에 내 to_csv& to_pdf메소드 를 작성하려면 이것이 정말 필요합니다 !" 라고 생각하면 전체 전제가 잘못된 것입니다. 결국 to_html메소드가 없습니까? 그러나 객체는 종종 HTML로 렌더링됩니다. 데이터 모델이 CSV가 무엇인지 알 수 있도록하는 대신 출력을 생성하기위한 새 클래스를 만드는 것이 좋습니다 .

모델에서 ActiveModel 유효성 검사 오류에 헬퍼를 사용하는 것과 관련하여 죄송합니다. ActiveModel / Rails는 오류의 의미 론적 아이디어 를 반환하는 대신 데이터 계층에서 오류 메시지를 강제로 구현하여 우리를 모두 망쳤습니다 . 나중에 깨달음- 한숨 . 이 문제를 해결할 수 있지만 기본적으로 더 이상 ActiveModel :: Errors를 사용하지 않음을 의미합니다. 해봤는데 잘 작동합니다.

여기에 메쏘드 세트를 오염시키지 않고 프레젠터 / 뷰-모델에 헬퍼를 포함시키는 유용한 방법이 있습니다 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

5
일반적으로이 규칙을 따르지만 모델에 정의 된 유효성 검사 오류 메시지의 형식을 지정하기 위해 뷰 도우미가 필요할 때 위반합니다.
Florent2 2011 년

43
이것은 좋은 조언이지만 문제를 해결하지 못하기 때문에 잘못된 대답입니다.
Jaryl 2012-06-29

21
예를 들어 csv 보고서를 작성하고 뷰를 볼 수없는 클래스의 to_csv 메서드에서 이와 같은 것을 사용해야하는 경우와 같이 이것이 좋은 대답이 아닌 경우가 있습니다. 프로그래밍 이상을 돋보이게하는 것이 항상 도움이되는 것은 아닙니다.
nitecoder 2012

1
네, nitecoder가 말한 것. 나는 같은 문제에 직면하고 있습니다. PDF 보고서를 생성 중이며 전화 번호 형식을 멋지게 지정하고 싶습니다.
James Adam

3
@maurice "이거 하나만"에서 부풀어 오른 모델에 이르기까지 미끄러운 경사입니다. Rails의 앱 도우미는 정크 서랍이며 발표자 / 뷰 모델은 관리하기가 더 쉽습니다. 나는 보고서에 대한 데이터 를 생성하고 그 데이터 의 (html | pdf | csv | etc.) 를 생성하는 것을 내가 한 사람과 HTML 사람 쇼 페이지보다 더 이상 단일 책임으로 보지 않는다.
Andrew Marshall

185

나는이 MVC 패턴을 깨는 될 수 있지만 패턴을 깰 이유는 내가이 필요한 내 경우에는, 항상 있다는 것을 여러분 모두 동의 방법 포맷터 통화를 하는 템플릿 필터에서 사용 ( 액체 내 경우).

결국 나는 다음 과 같은 것을 사용하여 이러한 통화 포맷터 메서드에 액세스 할 수 있음을 알았습니다 .

ActionController::Base.helpers.number_to_currency

6
약간 더 깨끗한 방법이 있지만 이것은 좋습니다. http://railscasts.com/episodes/132-helpers-outside-views
user664833을

4
RailsCasts에서 야호 코멘트 트랙 :에서 레일은 2013 년, 컨트롤러에서보기 도우미를 사용하는 것은 view_context.number_to_currency (양)과 같이 이루어집니다 3
olleolleolle

3
"돈"보석 사용에 대해 생각해 보셨습니까? money 객체는 format () 메서드를 제공하므로 모델, 컨트롤러 또는 뷰에서 호출 할 수 있습니다.
Zack Xu

71

이 스레드가 매우 오래되었다는 것을 알고 있지만 누군가가 Rails 4+에서이 문제에 대한 해결책을 찾을 수 있습니다. 개발자는 다음을 사용하여 뷰 관련 모듈 / 클래스에 액세스하지 않고도 사용할 수있는 ActiveSupport :: NumberHelper를 추가했습니다.

ActiveSupport::NumberHelper.number_to_currency(amount, precision: 0)

이 접근 방식 number_to_percentage은 Rails 콘솔에서의 동작을 실험하고 싶을 때 효과적이었습니다. 감사!
Jon Schneider

27

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

2
고마워요, 괜찮아 보이지만 MVC를 위반한다고 말하는 다른 사람들과 동의해야합니다. details헬퍼를 넣을 게요 .
Misha Moroshko 2011 년

1
Florent2와 같고 유효성 검사 메시지의 일부로 입력해야하는 경우 유용합니다. 고마워 샘.
RyanJM

이것은 나를 위해 일했습니다. 원칙을 위반하는 솔루션이이를 준수하는 솔루션보다 분명히 낫다면 항상 MVC (또는 모든 원칙)를 따르는 것이 말이되지 않는다고 생각합니다.
Jason Swett 2011

2
이 방법은 권장되지 않습니다. 필요하지 않은 많은 메서드를 추가하고 네임 스페이스를 복잡하게 만들고 일부 메서드를 덮어 쓸 수 있으며 일부 도우미 모듈은 다른 도우미 모듈에 의존하므로 (여러 모듈을 포함해야 할 수 있음) 문제가 발생합니다. 더 나쁘다. 설명과 더 나은 접근 방법은 다음을 참조하십시오. http://railscasts.com/episodes/132-helpers-outside-views
user664833

6

@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


3

@fguillen의 방법은 좋지만 여기에 약간 더 깨끗한 접근 방식이 있지만 특히 질문이 to_dollar. 먼저 Ryan Bates의 코드 ( 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

2

좋은 습관은 아니지만 저에게 효과적입니다!

가져 오려면 컨트롤러에 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

도움이 되었기를 바랍니다.


2

아무도 데코레이터를 사용하는 것에 대해 이야기하지 않았다는 사실에 놀랐습니다. 그들의 목적은 당신이 직면 한 문제 등을 해결하는 것입니다.

https://github.com/drapergem/draper

편집 : 수락 된 답변이 기본적으로 이와 같은 것을 제안한 것 같습니다. 하지만 예, 데코레이터를 사용하고 싶습니다. 더 많은 것을 이해하는 데 도움이되는 훌륭한 튜토리얼 시리즈는 다음과 같습니다.

https://gorails.com/episodes/decorators-from-scratch?autoplay=1

PS-@ excid3 무료 멤버십 월 LOL을 수락합니다.



-5

도우미 메서드는 일반적으로 View 파일에 사용됩니다. Model 클래스에서 이러한 메서드를 사용하는 것은 좋지 않습니다. 그러나 사용하고 싶다면 Sam의 대답은 괜찮습니다. 또는 사용자 정의 방법을 작성할 수 있습니다.


2
이것은 대답이 아닙니다.
Bonifacio2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.