2009-04-30 39 views
8

Tôi muốn có thể gửi từ một hành động điều khiển sang một điều kiện khác, dựa trên sự kết hợp của các tham số truy vấn và dữ liệu trong cơ sở dữ liệu.Cách chính xác để chạy một hành động điều khiển từ một hành động điều khiển khác mà không có chuyển hướng HTTP là gì?

Những gì tôi có ngay bây giờ là cái gì đó như:

class OldController < ApplicationController 
    def old_controller_action 
    if should_use_new_controller 
     new_params = params.dup 
     new_params[:controller] = "new_controller_action" 
     redirect_to new_params 
     return 
    end 
    # rest of old and busted 
    end 
end 

class NewController < ApplicationController 
    def new_controller_action 
    # new hotness 
    end 
end 

này hoạt động tốt, nhưng mà nó tạo ra một chuyển hướng HTTP, đó là chậm. Tôi muốn có thể làm điều tương tự, nhưng trong cùng một yêu cầu HTTP.

Có cách nào để làm việc này không?

Chỉnh sửa: Tiền thưởng sẽ chuyển đến người có thể chỉ cho tôi cách làm sạch để điều khiển và hành động của họ không bị ảnh hưởng (ngoài chính mã chuyển hướng).

Trả lời

13

Thay vì gọi mã qua các hành động, hãy trích xuất mã đó thành lib/hoặc một cái gì đó và gọi mã đó từ cả hai bộ điều khiển.

# lib/foo.rb 
module Foo 
    def self.bar 
    # ... 
    end 
end 

# posts_controller 
def index 
    Foo.bar 
end 

# things_controller 
def index 
    Foo.bar 
end 
+0

Vâng, tôi cũng nghĩ về điều này, mặc dù nó không phải là một lựa chọn thú vị khủng khiếp, từ góc độ tổ chức mã. –

+1

Nó thực sự là ok vì nó tạo ra trên phương pháp gắn kết được gọi là từ hai nơi đó là dễ dàng testable –

7

Tạo một thể hiện của lớp điều khiển:

@my_other_controller = MyOtherController.new 

Sau đó gọi các phương thức trên nó:

@my_other_controller.some_method(params[:id]) 

Tôi thích ý tưởng mô-đun, nhưng điều này sẽ làm các trick.

+0

Điều này sẽ không hoạt động tốt như vậy. Thật khó để gọi phương thức 'render' trong bộ điều khiển mới này. Nếu bạn gọi render trong bộ điều khiển gốc, bạn sẽ mất tất cả các biến được đặt trong bộ điều khiển được gọi. – holli

1

tôi nghi ngờ bạn muốn lựa chọn 3, nhưng cho phép đi qua một số lựa chọn thay thế đầu tiên

Lựa chọn 1 - Đẩy logic lựa chọn điều khiển vào một helper mà chèn link ngay vào tầm nhìn của bạn. Lợi ích - bộ điều khiển vẫn sạch sẽ, Nhược điểm - nếu logic quyết định tùy thuộc vào giá trị đã gửi thì phương pháp này sẽ không hoạt động. Nếu URL đang được gọi bởi các trang web bên ngoài thì điều này sẽ không hoạt động.

Tùy chọn 2 - Đẩy logic trở lại vào mô hình của bạn. Pro's - giữ bộ điều khiển sạch sẽ. Nhược Điểm - không hoạt động tốt nếu bạn có rất nhiều sesson, params hoặc render/redirect_to tương tác.

Tùy chọn 3 - Vẫn nằm trong cùng một bộ điều khiển. Tôi nghi ngờ bạn đang cố gắng thay thế một số chức năng hiện có bằng một số chức năng mới, nhưng chỉ trong một số trường hợp. Pro's - Đơn giản và có quyền truy cập vào mọi thứ bạn cần. Nhược điểm - chỉ hoạt động nếu bạn sử dụng cùng một bộ điều khiển có nghĩa là bạn đang làm việc với cùng một thực thể như người dùng, địa điểm hoặc công ty.

Cho phép xem xét một ví dụ cho các tùy chọn 3. điều khiển liên kết của tôi có behavour hoàn toàn khác nhau cho quản trị viên hơn những người dùng khác ...

class LinksController < ApplicationController 
    #... 

    def new 
    #Check params and db values to make a choice here 
    admin? ? new_admin : new_user 
    end 

    #... 

private 

    def new_admin 
    #All of the good stuff - can use params, flash, etc 
    render :action => 'new_admin'  
    end 

    def new_user 
    #All of the good stuff - can use params, flash, etc 
    render :action => 'new_user' 
    end 

end 
0

Nếu hai bộ điều khiển đang cố gắng làm điều tương tự, có một rất tốt cơ hội này nên ở trong một mô hình.Hãy xem tốt ở thiết kế của bạn và - Tôi xin lỗi tôi không biết mức độ kinh nghiệm của bạn với MVC - tìm hiểu về kỹ thuật điều khiển mỏng:

http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model http://www.robbyonrails.com/articles/2007/06/19/put-your-controllers-on-a-diet-already http://andrzejonsoftware.blogspot.com/2008/07/mvc-how-to-write-controllers.html

Nếu vấn đề là rằng bạn cần bộ điều khiển khác để làm render, thì có lẽ tuyến đường nên đã chỉ ra ở đó để bắt đầu, và vẫn còn kỹ thuật điều khiển gầy nên tiết kiệm trong ngày.

-1

Làm điều này:

class OldController < ApplicationController 
    def old_controller_action 
    if should_use_new_controller 
     new_controller_action 
    end 
    # rest of old and busted 
    end 
end 

và bộ điều khiển mới

class NewController < OldController 
    def new_controller_action 
    # new hotness 
    end 
end 
0

Nếu giải nén mã chung giữa các bộ điều khiển vào một mô-đun không làm việc cho bạn, tôi sẽ sử dụng rack middleware. Tôi đã không nhìn thấy mã sử dụng ActiveRecord trong middleware nhưng tôi không biết lý do tại sao nó không nên có thể kể từ khi mọi người đã sử dụng Redis và muốn.

Nếu không tôi nghĩ rằng lựa chọn duy nhất của bạn sẽ khởi động lại chế biến theo yêu cầu với một cái gì đó tương tự (chưa được kiểm tra, ví dụ giả):

env['REQUEST_URI'] = new_controller_uri_with_your_params 
call(env) 

này cũng tương tự như cách kiểm tra tích hợp được thực hiện. Nhưng tôi không biết nếu tất cả mọi thứ từ call cho đến khi bạn nhấn một bộ điều khiển là idempotent và an toàn để chạy lại như thế này. Bạn có thể theo dõi qua nguồn và xem. Nhưng ngay cả khi nó là ok bây giờ, nó có thể phá vỡ trong bất kỳ phiên bản tương lai của đường ray hoặc rack.

Sử dụng phần mềm trung gian sẽ tránh điều này bằng cách cho phép bạn chặn yêu cầu trước khi nó được chạy. Bạn vẫn có thể chia sẻ mã với ứng dụng đường ray của mình bằng cách giải nén nó ra thành các mô-đun chung được bao gồm trong cả hai vị trí.

Thành thật mà nói, tôi chỉ cần làm điều đơn giản để tính toán mã điều khiển chung có thể là sạch hơn, nhưng khó mà biết được nếu không có chi tiết về tình huống của bạn nên tôi nghĩ tôi sẽ đề xuất điều này.

Các vấn đề liên quan