การใช้ตัวช่วยในโมเดล: ฉันจะรวมการพึ่งพาตัวช่วยได้อย่างไร


104

ฉันกำลังเขียนแบบจำลองที่จัดการการป้อนข้อมูลของผู้ใช้จากพื้นที่ข้อความ ทำตามคำแนะนำจากhttp://blog.caboo.se/articles/2008/8/25/sanitize-your-users-html-inputฉันกำลังล้างอินพุตในโมเดลก่อนบันทึกลงในฐานข้อมูลโดยใช้ before_validate โทรกลับ.

ส่วนที่เกี่ยวข้องของแบบจำลองของฉันมีลักษณะดังนี้:

include ActionView::Helpers::SanitizeHelper

class Post < ActiveRecord::Base {
  before_validation :clean_input

  ...

  protected

  def clean_input
    self.input = sanitize(self.input, :tags => %w(b i u))
  end
end

ไม่จำเป็นต้องพูดมันไม่ได้ผล ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อพยายามบันทึกโพสต์ใหม่

undefined method `white_list_sanitizer' for #<Class:0xdeadbeef>

เห็นได้ชัดว่า SanitizeHelper สร้างอินสแตนซ์ของ HTML :: WhiteListSanitizer แต่เมื่อฉันผสมลงในโมเดลของฉันมันไม่พบ HTML :: WhiteListSanitizer ทำไม? ฉันจะทำอย่างไรเพื่อแก้ไขปัญหานี้

คำตอบ:


136

เพียงแค่เปลี่ยนบรรทัดแรกดังนี้:

include ActionView::Helpers

ที่จะทำให้มันใช้งานได้

UPDATE:สำหรับ Rails 3 ใช้:

ActionController::Base.helpers.sanitize(str)

เครดิตไปที่คำตอบของ lornc


ไม่สามารถพูดได้ว่ามันดีกว่าตัวเอง
Tilendor

1
ขอบคุณ. ฉันทำให้มันทำงานได้โดยการย้ายการรวมไปไว้ในนิยามคลาส
O. Frabjous-Dey

1
stack level too deepด้วยความที่ผมได้รับนี้ อยู่ในเมธอด before_save
Automatico

42
โปรดอย่าผสมความกังวลเกี่ยวกับเลเยอร์การดูกับโมเดลบันทึกที่ใช้งานอยู่ นั่นเป็นการฝึกที่แย่มาก แนวทางที่ดีกว่ามากคือวางออบเจ็กต์เจลทำความสะอาดข้อมูลอินพุตแบบสแตนด์อโลนไว้ด้านหน้า AR และดึงแอตทริบิวต์ "สะอาด" จากมัน
solnic

1
นี่เป็นวิธีแก้ปัญหาที่แย่มากและควรหลีกเลี่ยงเช่นไฟ Rails ใช้เฟรมเวิร์ก MVC (Model View Controller) ซึ่งตัวช่วยมาในส่วน View ดังนั้นคุณไม่ควรผสมวิธีการดูตัวช่วยกับโมเดล
jedi

135

สิ่งนี้ให้วิธีช่วยเหลือแก่คุณโดยไม่มีผลข้างเคียงจากการโหลดทุกเมธอด ActionView :: Helpers ลงในโมเดลของคุณ:

ActionController::Base.helpers.sanitize(str)

6
สำหรับคนช้าอย่างฉันคุณไม่จำเป็นต้องใส่อะไรเลยเพียงใช้ ActionController :: Base.helpers.sanitize ("บนสตริงที่คุณต้องการฆ่าเชื้อ")
Edward

ขอบคุณทำงานใน Rails 2.3.14 ในขณะที่คำตอบที่ยอมรับไม่ได้
ChrisInEdmonton

ฉันเพิ่มวิธีการลงใน application_helper แต่ฉันไม่สามารถเข้าถึงได้จากโมเดลโดยใช้ ActionController :: Base.helpers.my_method (ตัวเลือก) โดยใช้ Rails 3.0.3?
Tom Rossi

36

สิ่งนี้ใช้ได้ดีกว่าสำหรับฉัน:

ง่าย:

ApplicationController.helpers.my_helper_method

ล่วงหน้า:

class HelperProxy < ActionView::Base
  include ApplicationController.master_helper_module

  def current_user
    #let helpers act like we're a guest
    nil
  end       

  def self.instance
    @instance ||= new
  end
end

ที่มา: http://makandracards.com/makandra/1307-how-to-use-helper-methods-inside-a-model


1
ApplicationController.master_helper_moduleไม่ได้อยู่ใด ๆ เพิ่มเติมในรางที่ 3 และ 4 ก็จะปรากฏขึ้น ApplicationController.helpersเป็นคนดีคนหนึ่งว่า
ซามูเอล

ฉันโหวตให้สิ่งนี้ (ตัวเลือกง่ายๆ) เพราะตรงกับความต้องการของฉัน - ฉันต้องการตัวช่วยเพียงคนเดียวที่ใช้ข้อมูลที่บันทึกไว้ก่อนตัวกรองใน ApplicationController ดังนั้นในกรณีของฉันที่ทำให้การเชื่อมโยงอย่างชัดเจนเป็นการเตือนว่ามีการเชื่อมต่อ [กรณีการใช้งานคือแอปหลายโดเมนซึ่งจะส่งอีเมลผ่านตัวแจ้งรุ่นที่มีลิงก์ url กลับไปที่แอป - URL นี้จะเปลี่ยนไปตามโดเมนของคำขอทางเว็บ]
iheggie

25

ในการเข้าถึงตัวช่วยจากคอนโทรลเลอร์ของคุณเองเพียงใช้:

OrdersController.helpers.order_number(@order)

2
เพียงแค่ใช้ApplicationController.helpers.order_number(@order). นั่นหมายความว่าorder_numberค้นหาเมื่อOrder Helper
ksugiarto

3
@rowanu เขากำลังพูดว่า "เข้าถึง (ตัวช่วยจากตัวควบคุมของคุณเอง)" ไม่ใช่ "(เพื่อเข้าถึงตัวช่วย) จากตัวควบคุมของคุณเอง"
Ajedi32


11

ฉันจะไม่แนะนำวิธีการเหล่านี้ ให้วางไว้ในเนมสเปซของตัวเองแทน

class Post < ActiveRecord::Base
  def clean_input
    self.input = Helpers.sanitize(self.input, :tags => %w(b i u))
  end

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