[ruby-on-rails] 보기보다는 모델에서 “number_to_currency”도우미 메서드를 사용하는 방법은 무엇입니까?

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 ‘

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



답변

모델에서의 사용이 (일반적으로) 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


답변

나는이 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


답변

@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. 먼저 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