देखने के बजाय मॉडल में "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विधि यहाँ मान्यता प्राप्त नहीं है:

# <नौकरी: 0x311eb00> के लिए अपरिभाषित विधि `संख्या_तो_सहयोग '

किसी भी विचार यह कैसे काम करने के लिए?

जवाबों:


103

यह उपलब्ध नहीं है क्योंकि एक मॉडल (आमतौर पर) में इसका उपयोग एमवीसी का उल्लंघन करता है (और यह आपके मामले में लगता है)। आप डेटा ले रहे हैं और इसे प्रस्तुति के लिए जोड़ तोड़ रहे हैं। यह, परिभाषा के अनुसार, मॉडल में नहीं है।

यहां कुछ उपाय दिए गए हैं:

  • मॉडल और दृश्य के बीच मध्यस्थता करने के लिए एक प्रस्तोता या दृश्य मॉडल ऑब्जेक्ट का उपयोग करें। यह लगभग निश्चित रूप से अन्य समाधानों की तुलना में अधिक प्रारंभिक कार्य की आवश्यकता है, लेकिन लगभग हमेशा एक बेहतर डिजाइन है। प्रस्तुतकर्ता / दृश्य-मॉडल में सहायकों का उपयोग करना MVC का उल्लंघन नहीं करता है, क्योंकि वे पारंपरिक कस्टम रेल सहायकों और तर्क से भरे विचारों की जगह, दृश्य परत में रहते हैं।

  • स्पष्ट रूप include ActionView::Helpers::NumberHelperसे JobsHelperरेल के आधार पर इसके बजाय स्पष्ट रूप से इसे आपके लिए लोड करने के लिए। यह अभी भी बहुत अच्छा नहीं है, क्योंकि आपको किसी मॉडल से सहायक तक नहीं पहुंचना चाहिए।

  • MVC और SRP का उल्लंघन करें । ऐसा करने के लिए fguillen का जवाब देखें । मैं इसे यहाँ नहीं सुनाऊँगा क्योंकि मैं इससे सहमत नहीं हूँ। फिर भी, हालांकि, क्या मैं सैम के जवाब में प्रस्तुति के तरीकों के साथ आपके मॉडल को प्रदूषित करने से असहमत हूं ।

अगर आपको लगता है कि "लेकिन मुझे अपने मॉडल में मेरे to_csvऔर to_pdfतरीके लिखने के लिए वास्तव में इसकी आवश्यकता है !", तो आपका पूरा आधार गलत है - आखिरकार, आपके पास कोई to_htmlतरीका नहीं है , क्या आप? और फिर भी आपकी वस्तु बहुत बार HTML के रूप में प्रदान की जाती है। अपने डेटा मॉडल को बनाने के बजाय अपने आउटपुट को उत्पन्न करने के लिए एक नया वर्ग बनाने पर विचार करें कि CSV क्या है ( क्योंकि यह नहीं होना चाहिए )।

मॉडल में ActiveModel सत्यापन त्रुटियों के लिए सहायकों का उपयोग करने के लिए, ठीक है, मुझे क्षमा करें, लेकिन ActiveModel / रेल्स ने हम सभी को डेटा लेयर में महसूस करने के लिए त्रुटि संदेश भेजने के बजाय, शब्दार्थ वापस करने के लिए मजबूर किया है। एक त्रुटि विचार को वापस करने के। बाद में एहसास हुआ- आहें । आप इसे प्राप्त कर सकते हैं, लेकिन इसका मूल अर्थ है ActiveModel का उपयोग न करना :: त्रुटियां। मैंने इसे किया है, यह अच्छी तरह से काम करता है।

एक तरफ के रूप में, यहां प्रस्तुतकर्ता / दृश्य-मॉडल में सहायकों को इसके तरीकों के सेट को प्रदूषित किए बिना शामिल करने का एक उपयोगी तरीका है (क्योंकि ऐसा करने में सक्षम होने का 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
मैं आमतौर पर इस नियम का पालन करता हूं, लेकिन जब मुझे मॉडल में परिभाषित सत्यापन त्रुटि संदेश को प्रारूपित करने के लिए व्यू हेल्पर की आवश्यकता होती है, तो इसे तोड़ देता हूं।
फ्लोरेंट

43
यह अच्छी सलाह है, लेकिन यह एक बुरा जवाब है क्योंकि यह सवाल हल नहीं करता है।
जरील

21
ऐसे मामले हैं जहां यह एक महान जवाब नहीं है, उदाहरण के लिए अभी जहां मैं एक सीएसवी रिपोर्ट खरीद रहा हूं और एक कक्षा में एक to_csv विधि में कुछ इस तरह का उपयोग करने की आवश्यकता है जो कभी भी एक दृश्य नहीं देखेगा। बस प्रोग्रामिंग आदर्शों को अंकुरित करना हमेशा मददगार नहीं होता है।
नाइट्रोडर

1
हाँ, नाइट्रोकोडर ने क्या कहा। मैं एक ही मुद्दे में चल रहा हूँ। मैं पीडीएफ रिपोर्ट तैयार कर रहा हूं और बस एक फोन नंबर को अच्छी तरह से प्रारूपित करना चाहता हूं।
जेम्स एडम

3
@ मौरिस यह फूला हुआ मॉडल "अच्छी तरह से सिर्फ एक चीज" से एक फिसलन ढलान है। रेल में ऐप मदद करने वाले एक जंक-ड्रावर हैं, प्रस्तुतकर्ता / दृश्य-मॉडल को प्रबंधित करना आसान है। मैं किसी रिपोर्ट के लिए डेटा बनाना और html (html | pdf | csv; आदि) को एक जिम्मेदारी के रूप में उस डेटा को नहीं देखता , जो मैं किसी भी व्यक्ति के लिए करता हूं, जैसे, एक व्यक्ति और एक HTML व्यक्ति शो पेज।
एंड्रयू मार्शल

185

मैं आप सभी से सहमत हूं कि यह एमवीसी पैटर्न को तोड़ सकता है लेकिन एक पैटर्न को तोड़ने के हमेशा कारण होते हैं, मेरे मामले में मुझे इन मुद्रा फ़ॉर्मेटर के तरीकों की आवश्यकता थी उन्हें टेम्पलेट फिल्टर ( मेरे मामले में तरल ) में उपयोग लिए

अंत में मुझे पता चला कि मैं इस तरह की चीजों का उपयोग करके इन मुद्रा फ़ॉर्मेटर विधियों तक पहुंच सकता हूं :

ActionController::Base.helpers.number_to_currency

6
यह अच्छा है, हालांकि इसे करने का थोड़ा साफ तरीका है। देखें http://railscasts.com/episodes/132-helpers-outside-views
user664833

4
RailsCasts में Yay टिप्पणी ट्रैक: 2013 में रेल 3 में, एक कंट्रोलर में व्यू हेल्पर का उपयोग view_context.number_to_currency (राशि)
olleolleolle

3
क्या आपने "धन" रत्न के उपयोग के बारे में सोचा है? जैसा कि मनी ऑब्जेक्ट एक प्रारूप () विधि प्रदान करता है, और आप इसे मॉडल, नियंत्रक या दृश्य में लागू कर सकते हैं।
ज़ैक ज़ू

71

मुझे पता है कि यह धागा बहुत पुराना है, लेकिन कोई व्यक्ति इस समस्या का हल 4+ में देख सकता है। डेवलपर्स ने ActiveSupport :: नंबर हेल्पर को जोड़ा, जिसका उपयोग दृश्य संबंधित मॉड्यूल / कक्षाओं तक पहुंचने के बिना किया जा सकता है:

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

यह दृष्टिकोण मेरे लिए तब काम आया जब मैं number_to_percentageरेल्स कंसोल के व्यवहार के साथ प्रयोग करना चाहता था । धन्यवाद!
जॉन श्नाइडर

27

आपको ActionView :: हेल्पर्स :: 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
धन्यवाद, अच्छा लग रहा है, लेकिन मुझे दूसरों से सहमत होना होगा जो कहते हैं कि मैं एमवीसी का उल्लंघन करता हूं। मैं detailsसहायक में रखूँगा ।
मीशा मोरोस्को

1
यदि आप फ्लोरेंट 2 की तरह हैं तो सहायक और इसे एक सत्यापन संदेश के हिस्से के रूप में रखने की आवश्यकता है। धन्यवाद सैम।
रयानजैम

इसने मेरे लिए काम किया। मुझे नहीं लगता कि यह हमेशा एमवीसी (या किसी भी सिद्धांत) का पालन करने के लिए समझ में आता है अगर एक समाधान जो उस सिद्धांत का उल्लंघन करता है वह स्पष्ट रूप से उस से बेहतर है जो इसका पालन करता है।
जेसन स्विट

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। मैं पहली बार रयान बेट्स कोड ( 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 :: हेल्पर्स :: नंबर हेल्पर कंट्रोलर में शामिल हैं। उदाहरण के लिए:

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

हेल्पर के तरीकों का इस्तेमाल आमतौर पर व्यू फाइल के लिए किया जाता है। मॉडल क्लास में इन विधियों का उपयोग करना एक अच्छा अभ्यास नहीं है। लेकिन अगर आप उपयोग करना चाहते हैं तो सैम का जवाब ठीक है। या मेरा सुझाव है कि आप अपनी खुद की कस्टम विधि लिख सकते हैं।


2
यह कोई उत्तर नहीं है।
बोनिफेसियो 2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.