5

Tôi đang nâng cấp plugin Rails của mình làm công cụ hoạt động với bản phát hành 3.0RC1 mới nhất và tôi đang gặp khó khăn trong việc tìm ra cách tốt nhất (và chính xác nhất) để mở rộng ActionController. Tôi đã thấy this post bởi DHH và this question ở đây trên SO, nhưng câu hỏi của tôi là nhiều hơn về cách gọi đúng mã trong số ActionController.Rails 3.0 Engine - Thực hiện mã trong ActionController

Ví dụ, tôi cần phải gọi sau đây trong điều khiển động cơ của tôi:

class ApplicationController < ActionController::Base 
    helper :all 

    before_filter :require_one_user 
    after_filter :store_location 

    private 
    def require_one_user 
     # Code goes here 
    end 

    def store_location 
     # Code goes here 
    end 
end 

Tôi biết làm thế nào để đúng cách bao gồm hai chức năng riêng tư của tôi, nhưng tôi không thể tìm thấy một cách để có được nó để gọi đúng helper, before_filterafter_filter.

Tôi sẽ đánh giá cao một số liên kết hoặc cách để thực hiện công việc này. Tôi đã thử đặt tên cho bộ điều khiển của mình là một cái gì đó khác ngoài số ApplicationController và có số thực ApplicationController mở rộng nó, nhưng điều đó dường như không hoạt động. Tôi thực sự thích giải pháp nào giúp cuộc sống của người sử dụng động cơ trở nên dễ dàng nhất có thể. Lý tưởng nhất, họ sẽ không phải mở rộng lớp học của tôi, nhưng họ sẽ có tất cả các chức năng được xây dựng vào riêng của họ ApplicationController.

Trả lời

10

Bạn cũng có thể muốn xem xét các bộ khởi tạo bên trong phân lớp động cơ của bạn, do đó bạn không phải bao gồm người trợ giúp xem bên trong lớp điều khiển của bạn. Và điều này sẽ cho phép bạn kiểm soát thứ tự tải của các mô-đun này.

Dưới đây là những gì tôi đã được sử dụng:

 

module MyEngine 
    class Engine < Rails::Engine 
    initializer 'my_engine.helper' do |app| 
     ActionView::Base.send :include, MyEngineHelper 
    end 

    initializer 'my_engine.controller' do |app| 
     ActiveSupport.on_load(:action_controller) do 
     include MyEngineActionControllerExtension 
     end 
    end 
    end 
end 
 

Ngoài ra, một lựa chọn cho phần mở rộng điều khiển hành động đang sử dụng một mô-đun mixin. Điều này sẽ cho phép bạn sử dụng before_filter, after_filter, vv ..

 

module MyEngineActionControllerExtension 
    def self.included(base) 
    base.send(:include, InstanceMethods) 
    base.before_filter :my_method_1 
    base.after_filter :my_method_2 
    end 

    module InstanceMethods 
    #........... 
    end 
end 
 

Một điều khác ... nếu bạn tạo đường ray mặc định thư mục ở cấp cao nhất của đá quý của bạn, bạn không cần phải lo lắng về việc yêu cầu những người giúp việc hoặc bộ điều khiển. Phân lớp động cơ của bạn có quyền truy cập vào chúng. Vì vậy, tôi thêm bộ điều khiển ứng dụng và tiện ích trợ giúp ứng dụng của mình tại đây:

 
/myengine/app/helpers/myengine_application_helper_extension.rb 
/myengine/app/controllers/my_engine_action_controller_extension.rb 

Tôi thích thiết lập này vì nó trông giống như application_controller và application_helper trong ứng dụng đường ray của bạn.Một lần nữa, đây chỉ là sở thích cá nhân, nhưng tôi cố gắng giữ bất kỳ thứ gì có liên quan trực tiếp, chẳng hạn như bộ điều khiển, người trợ giúp và mô hình bên trong/my_engine/app và bất kỳ thứ gì có liên quan đến plugin nói chung bên trong/my_engine/lib

Xem hướng dẫn này của Jose Valim để biết thêm thông tin về bộ khởi tạo: https://gist.github.com/e139fa787aa882c0aa9c (engine_name không được dùng nữa, nhưng hầu hết tài liệu này có vẻ cập nhật)

+0

+1 và được chấp nhận - Cảm ơn bạn! Tôi đánh giá cao việc bạn dành thời gian mặc dù tôi đã "tự mình trả lời". Nó là tốt đẹp để xem một giải pháp thanh lịch hơn. Oh, và chào mừng bạn đến Stack Overflow :-) –

3

Vì vậy, cuối cùng tôi đã tìm ra giải pháp và tôi hy vọng nó sẽ giúp người khác.

Bạn cần tạo tệp trong thư mục lib của mình vì bạn thực sự sẽ mở rộng lớp. Tôi đã làm myplugin/lib/extensions/action_controller_base.rb.

Sau đó, bên trong tệp myplugin/lib/myplugin.rb của bạn, làm như sau:

require 'extensions/action_controller_base.rb' 

Bên trong myplugin/lib/extensions/action_controller_base.rb đặt như sau:

require 'action_controller' # Make sure ActionController::Base is defined 

ActionController::Base.class_eval { 
    private 
    def my_method_1 
     # Code Goes Here 
    end 

    def my_method_2 
     # Code Goes Here 
    end 
} 

ActionController::Base.instance_eval { 
    helper_method :my_method_1, :my_method_2 

    before_filter :my_method_1 
    after_filter :my_method_2 
} 

Nếu bạn cần phải có cái nhìn những người giúp đỡ, tạo chúng trong myplugin/lib/helpers thư mục (hoặc bất kỳ thứ gì bên trong lib, tên "người trợ giúp" cũng không quan trọng) và thêm thông tin sau vào cuối của myplugin/lib/extensions/action_controller_base.rb:

require 'helpers/helper_file_1' 
require 'helpers/helper_file_2' 

ActionView::Base.send :include, MyHelper1 
ActionView::Base.send :include, MyHelper2 
Các vấn đề liên quan