Sử dụng trình trợ giúp trong mô hình: làm cách nào để bao gồm các phụ thuộc của trình trợ giúp?


100

Tôi đang viết một mô hình xử lý đầu vào của người dùng từ một vùng văn bản. Theo lời khuyên từ http://blog.caboo.se/articles/2008/8/25/sanifying-your-users-html-input , tôi đang dọn dẹp đầu vào trong mô hình trước khi lưu vào cơ sở dữ liệu, sử dụng before_validate gọi lại.

Các phần liên quan của mô hình của tôi trông như thế này:

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

Không cần phải nói, điều này không hoạt động. Tôi gặp lỗi sau khi thử và lưu một Bài đăng mới.

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

Rõ ràng, SanizingHelper tạo ra một phiên bản HTML :: WhiteListSanitizer, nhưng khi tôi trộn nó vào mô hình của mình, nó không thể tìm thấy HTML :: WhiteListSanitizer. Tại sao? Tôi có thể làm gì về điều này để sửa chữa nó?

Câu trả lời:


133

Chỉ cần thay đổi dòng đầu tiên như sau:

include ActionView::Helpers

điều đó sẽ làm cho nó hoạt động.

CẬP NHẬT: Để sử dụng Rails 3:

ActionController::Base.helpers.sanitize(str)

Tín dụng thuộc về câu trả lời của lornc


không thể nói nó tốt hơn bản thân mình
Tilendor

1
Cảm ơn. Tôi đã làm cho nó hoạt động bằng cách di chuyển bao gồm vào bên trong định nghĩa lớp.
O. Frabjous-Dey

1
Với điều này tôi nhận được stack level too deep. Nó nằm trong một phương thức before_save.
Automatico

42
Vui lòng không kết hợp các mối quan tâm về lớp chế độ xem với các mô hình bản ghi đang hoạt động. Đó là một thực hành khủng khiếp. Một cách tiếp cận tốt hơn nhiều là đặt một đối tượng trình vệ sinh dữ liệu đầu vào độc lập trước AR và truy xuất các thuộc tính "sạch" từ nó.
solnic

1
Đây là một giải pháp rất tồi và nên tránh như hỏa hoạn. Rails dựa trên khung công tác MVC (Model View Controller) trong đó helper nằm trong phần View, vì vậy bạn không nên kết hợp các phương thức view helper với model.
jedi

132

Điều này chỉ cung cấp cho bạn phương thức trợ giúp mà không có tác dụng phụ khi tải mọi phương thức ActionView :: Helpers vào mô hình của bạn:

ActionController::Base.helpers.sanitize(str)

6
Đối với những người chậm chạp như tôi - bạn không cần phải bao gồm bất kỳ thứ gì, chỉ cần sử dụng ActionController :: Base.helpers.sanifying ("Trên chuỗi bạn muốn vệ sinh")
Edward

Cảm ơn bạn, đã làm việc trong Rails 2.3.14 trong khi câu trả lời được chấp nhận thì không.
ChrisInEdmonton

Tôi đã thêm một phương thức vào application_helper, nhưng tôi không thể truy cập nó từ mô hình bằng ActionController :: Base.helpers.my_method (options) bằng Rails 3.0.3?
Tom Rossi

35

Điều này hoạt động tốt hơn cho tôi:

Đơn giản:

ApplicationController.helpers.my_helper_method

Nâng cao:

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

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


1
ApplicationController.master_helper_modulekhông tồn tại nữa trong Rails 3 và 4 nó xuất hiện. Đây ApplicationController.helperslà một trong những tốt đẹp mặc dù.
Samuel

Tôi đã bỏ phiếu cho điều này (tùy chọn đơn giản) vì nó phù hợp với nhu cầu của tôi - tôi chỉ cần một người trợ giúp đang sử dụng thông tin được lưu bởi bộ lọc trước trong ApplicationController, vì vậy trong trường hợp của tôi, việc đặt liên kết rõ ràng là một lời nhắc rằng có một khớp nối. [Trường hợp sử dụng là ứng dụng đa miền, gửi email qua trình thông báo mô hình với liên kết url trở lại ứng dụng - url này thay đổi tùy thuộc vào miền yêu cầu web]
iheggie

24

Để truy cập trình trợ giúp từ bộ điều khiển của riêng bạn, chỉ cần sử dụng:

OrdersController.helpers.order_number(@order)

2
Chỉ cần sử dụng ApplicationController.helpers.order_number(@order). Đó có nghĩa là order_numberđã xác định vị trí trênOrder Helper
ksugiarto

3
@rowanu Anh ấy đang nói "để truy cập (người trợ giúp từ bộ điều khiển của riêng bạn)", không phải "(để truy cập người trợ giúp) từ bộ điều khiển của riêng bạn".
Ajedi32

11

Tôi sẽ không giới thiệu bất kỳ phương pháp nào trong số này. Thay vào đó, hãy đặt nó trong không gian tên riêng của nó.

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

11

Nếu bạn muốn sử dụng my_helper_methodbên trong một mô hình, bạn có thể viết:

ApplicationController.helpers.my_helper_method
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.