Menggunakan helper dalam model: bagaimana cara menyertakan dependensi helper?

100

Saya sedang menulis model yang menangani input pengguna dari area teks. Mengikuti saran dari http://blog.caboo.se/articles/2008/8/25/sanitize-your-users-html-input , saya membersihkan input dalam model sebelum menyimpan ke database, menggunakan before_validate panggilan balik.

Bagian yang relevan dari model saya terlihat seperti ini:

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

Tak perlu dikatakan, ini tidak berhasil. Saya mendapatkan error berikut saat mencoba dan menyimpan Postingan baru.

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

Rupanya, SanitizeHelper membuat sebuah instance dari HTML :: WhiteListSanitizer, tetapi ketika saya mencampurnya ke dalam model saya, ia tidak dapat menemukan HTML :: WhiteListSanitizer. Mengapa? Apa yang dapat saya lakukan untuk memperbaikinya?

O. Frabjous-Dey
sumber

Jawaban:

133

Ubah saja baris pertama sebagai berikut:

include ActionView::Helpers

itu akan membuatnya berhasil.

UPDATE: Untuk penggunaan Rails 3:

ActionController::Base.helpers.sanitize(str)

Kredit pergi ke jawaban lornc ini

Alfreddd
sumber
tidak bisa mengatakannya lebih baik sendiri
Tilendor
1
Terima kasih. Saya membuatnya bekerja dengan memindahkan include ke dalam definisi kelas.
O. Frabjous-Dey
1
Dengan ini saya dapatkan stack level too deep. Ini ada dalam metode before_save.
Automatico
42
Harap jangan mencampur masalah lapisan tampilan dengan model rekaman aktif. Itu praktik yang buruk. Pendekatan yang jauh lebih baik adalah dengan meletakkan objek pembersih data masukan mandiri di depan AR dan mengambil atribut "bersih" darinya.
solnic
1
Ini adalah solusi yang sangat buruk dan harus dihindari seperti api. Rails didasarkan pada kerangka kerja MVC (Model View Controller) di mana helper hadir di bagian View sehingga Anda tidak boleh mencampur metode view helper dengan model.
jedi
132

Ini memberi Anda metode helper tanpa efek samping dari memuat setiap metode ActionView :: Helpers ke dalam model Anda:

ActionController::Base.helpers.sanitize(str)
lornc
sumber
6
Untuk orang lambat seperti saya - Anda tidak perlu menyertakan apa pun, cukup gunakan ActionController :: Base.helpers.sanitize ("Pada string yang ingin Anda bersihkan")
Edward
Terima kasih, bekerja di Rails 2.3.14 sedangkan jawaban yang diterima tidak.
ChrisInEdmonton
Saya menambahkan metode ke application_helper, tetapi saya tidak dapat mengaksesnya dari model menggunakan ActionController :: Base.helpers.my_method (options) menggunakan Rails 3.0.3?
Tom Rossi
35

Ini bekerja lebih baik untuk saya:

Sederhana:

ApplicationController.helpers.my_helper_method

Muka:

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

Sumber: http://makandracards.com/makandra/1307-how-to-use-helper-methods-inside-a-model

skozz
sumber
1
Tidak ApplicationController.master_helper_moduleada lagi di Rails 3 dan 4 tampaknya. Tapi ApplicationController.helpersitu bagus.
Samuel
Saya memilih ini (opsi sederhana) karena sesuai dengan kebutuhan saya - saya hanya memerlukan satu helper yang menggunakan informasi yang disimpan oleh filter sebelumnya di ApplicationController, jadi dalam kasus saya membuat asosiasi eksplisit adalah pengingat bahwa ada kopling. [Kasus penggunaan adalah aplikasi multi domain, yang mengeluarkan email melalui model notifier dengan tautan url kembali ke aplikasi - url ini berubah tergantung pada domain permintaan web]
iheggie
24

Untuk mengakses pembantu dari pengontrol Anda sendiri, cukup gunakan:

OrdersController.helpers.order_number(@order)
Tarmo
sumber
2
Hanya menggunakan ApplicationController.helpers.order_number(@order). Itu berarti lokasi order_numberitu berada padaOrder Helper
ksugiarto
3
@rowanu Dia mengatakan "untuk mengakses (pembantu dari pengontrol Anda sendiri)", bukan "(untuk mengakses pembantu) dari pengontrol Anda sendiri".
Ajedi32
11

Saya tidak akan merekomendasikan salah satu metode ini. Sebagai gantinya, taruh di dalam namespace-nya sendiri.

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
axsuul
sumber
11

Jika Anda ingin menggunakan bagian my_helper_methoddalam model, Anda dapat menulis:

ApplicationController.helpers.my_helper_method
Atchyut Nagabhairava
sumber