Rails - วิธีใช้ตัวช่วยภายในคอนโทรลเลอร์


207

ในขณะที่ฉันรู้ว่าคุณควรจะใช้ผู้ช่วยในมุมมองฉันต้องการผู้ช่วยในตัวควบคุมของฉันขณะที่ฉันสร้างวัตถุ JSON เพื่อกลับไป

มันเป็นเช่นนี้เล็กน้อย:

def xxxxx

   @comments = Array.new

   @c_comments.each do |comment|
   @comments << {
     :id => comment.id,
     :content => html_format(comment.content)
   }
   end

   render :json => @comments
end

ฉันจะเข้าถึงhtml_formatผู้ช่วยของฉันได้อย่างไร


2
คุณอาจต้องการพิจารณาคำตอบของ @ grosser มันสมบูรณ์กว่านี้มาก
tokland

ฉันรู้ว่ามันเก่า แต่ ... เกิดอะไรขึ้นกับคลาสทับทิมธรรมดา? : p
Tarek

คำตอบ:


205

หมายเหตุ:สิ่งนี้ถูกเขียนและยอมรับใน Rails 2 วัน ทุกวันนี้คำตอบของพ่อค้าก็เป็นไปได้

ตัวเลือกที่ 1:วิธีที่ง่ายที่สุดอาจรวมโมดูลตัวช่วยของคุณในตัวควบคุมของคุณ:

class MyController < ApplicationController
  include MyHelper

  def xxxx
    @comments = []
    Comment.find_each do |comment|
      @comments << {:id => comment.id, :html => html_format(comment.content)}
    end
  end
end

ตัวเลือกที่ 2:หรือคุณสามารถประกาศเมธอดตัวช่วยเป็นฟังก์ชันคลาสและใช้วิธีดังนี้:

MyHelper.html_format(comment.content)

หากคุณต้องการที่จะใช้มันเป็นทั้งฟังก์ชั่นอินสแตนซ์และฟังก์ชั่นคลาสคุณสามารถประกาศทั้งสองรุ่นในผู้ช่วยของคุณ:

module MyHelper
  def self.html_format(str)
    process(str)
  end

  def html_format(str)
    MyHelper.html_format(str)
  end
end

หวังว่านี่จะช่วยได้!


ขอบคุณ แต่ฉันสับสนเล็กน้อย ตอนนี้ผู้ช่วยของฉันอยู่ใน /app/helpers/application_helper.rb ... และคุณแนะนำให้ฉันย้ายผู้ช่วยไปที่ ApplicationController หรือไม่?
AnApprentice

ฉันเพิ่ม 'include ApplicationHelper' ไปยัง application_controller ของฉัน แต่ข้อผิดพลาดนั้นด้วย 'NoMethodError (วิธีที่ไม่ได้กำหนด `html_format' สำหรับ ApplicationHelper: โมดูล): '
AnApprentice

1
@AnApprentice ดูเหมือนว่าคุณจะคิดออก แต่ฉัน tweaked คำตอบของฉันเล็กน้อยหวังว่าจะทำให้สิ่งต่าง ๆ ชัดเจนขึ้น ในรุ่นแรกคุณสามารถใช้html_format- คุณต้องการเพียงแค่MyHelper.html_formatในวินาที
Xavier Holt

4
link_toนี้จะไม่ทำงานเมื่อวิธีการช่วยเหลือที่คุณต้องการที่จะใช้ให้ใช้วิธีการเช่นมุมมอง ผู้ควบคุมไม่มีสิทธิ์เข้าถึงวิธีการเหล่านี้และผู้ช่วยส่วนใหญ่ของฉันใช้วิธีการเหล่านี้ นอกจากนี้การรวมตัวช่วยเข้าในตัวควบคุมจะเปิดเผยวิธีการของผู้ช่วยทั้งหมดเนื่องจากการกระทำที่สาธารณชนสามารถเข้าถึงได้ซึ่งไม่ดี view_contextเป็นวิธีที่จะไปใน Rails 3
GregT

@GregT - ไม่เคยเห็นคำตอบของคนที่เคยพูดมาก่อนเพราะมันเข้ามาในความจริง แต่ฉันก็ชอบมันเหมือนกัน เขาเพิ่งได้ upvote ของฉัน
Xavier Holt

304

คุณสามารถใช้ได้

  • helpers.<helper>ในRails 5+ (หรือActionController::Base.helpers.<helper>)
  • view_context.<helper>( Rails 4 & 3 ) (คำเตือน: นี่เป็นอินสแตนซ์มุมมองใหม่ต่อการโทร)
  • @template.<helper>( ราง 2 )
  • รวมผู้ช่วยในชั้นเรียนเดี่ยวแล้ว singleton.helper
  • include ผู้ช่วยในตัวควบคุม (คำเตือน: จะทำให้วิธีการช่วยเหลือทั้งหมดเป็นการกระทำของตัวควบคุม)

56
คำตอบนี้ดียิ่งขึ้น! ใน Rails 3 การโทรview_context.helper_functionแบบง่าย ๆ และใช้งานได้ดี ActionController::Base.helpers.helper_functionเป็นสิ่งที่ดีอย่างเท่าเทียมกัน
trisweb

29
view_context= อัจฉริยะ
n_i_c_k

5
คำเตือน: view_contextอย่าใช้ มันจะยกตัวอย่างอินสแตนซ์ของมุมมองใหม่ต่อการโทร ...
58

7
ActionController::Base.helpers.helper_functionดูเหมือนจะไม่ทำงาน ฉันได้รับNoMethodError - undefined method spell_date_and_time' for #<ActionView::Base:0x007fede56102d0>:เมื่อพยายามโทรActionController::Base.helpers.spell_date_and_time()ด้วยวิธีการควบคุม การโทรview_context.spell_date_and_time()ใช้งานได้อย่างไรก็ตาม
Catfish

37
ราง 5: ใช้helpers.helper_functionในคอนโทรลเลอร์ของคุณ ( github.com/rails/rails/pull/24866 )
Markus

80

ใน Rails 5 ใช้helpers.helper_functionในคอนโทรลเลอร์ของคุณ

ตัวอย่าง:

def update
  # ...
  redirect_to root_url, notice: "Updated #{helpers.pluralize(count, 'record')}"
end

ที่มา: จากความคิดเห็นโดย @Markus กับคำตอบที่แตกต่างกัน ฉันรู้สึกว่าคำตอบของเขาสมควรได้รับคำตอบเพราะเป็นคำตอบที่สะอาดและง่ายที่สุด

การอ้างอิง: https://github.com/rails/rails/pull/24866


6
รู้สึกแปลก ๆ ว่าในคอนโซลคุณจะโทรหาhelperเอกพจน์และในตัวควบคุมมันเป็นพหูพจน์
คนแปลกหน้าเพื่อน

10

ปัญหาของฉันแก้ไขด้วยตัวเลือก 1 อาจเป็นวิธีที่ง่ายที่สุดคือการรวมโมดูลตัวช่วยในตัวควบคุมของคุณ:

class ApplicationController < ActionController::Base
  include ApplicationHelper

...

1
ข้อเสียเฉพาะที่เพิ่มการดำเนินการของตัวควบคุมด้วยชื่อของฟังก์ชั่นตัวช่วย แต่ TBH ผมทำได้เช่นกัน :)
เฟลิกซ์

9

โดยทั่วไปถ้าผู้ช่วยที่จะนำมาใช้ใน (แค่) ควบคุม, class ApplicationControllerฉันชอบที่จะประกาศว่ามันเป็นวิธีการเช่นของ


5
เป็นวิธีการป้องกัน
Benjamin Crouzier

3

ใน Rails 5+ คุณสามารถใช้ฟังก์ชั่นตามตัวอย่างด้านล่าง:

module ApplicationHelper
  # format datetime in the format #2018-12-01 12:12 PM
  def datetime_format(datetime = nil)
    if datetime
      datetime.strftime('%Y-%m-%d %H:%M %p')
    else
      'NA'
    end
  end
end

class ExamplesController < ApplicationController
  def index
    current_datetime = helpers.datetime_format DateTime.now
    raise current_datetime.inspect
  end
end

เอาท์พุท

"2018-12-10 01:01 AM"

0
class MyController < ApplicationController
    # include your helper
    include MyHelper
    # or Rails helper
    include ActionView::Helpers::NumberHelper

    def my_action
      price = number_to_currency(10000)
    end
end

ใน Rails 5+ เพียงใช้ผู้ช่วยเหลือ ( helpers.number_to_currency (10,000) )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.