Rails: gọi một hành động điều khiển khác từ một bộ điều khiển


118

Tôi cần gọi hành động tạo trong bộ điều khiển A, từ bộ điều khiển B.

Lý do là tôi cần chuyển hướng khác khi tôi đang gọi từ bộ điều khiển B.

Nó có thể được thực hiện trong Rails không?



Bạn đang nói về hành động POST hoặc GET? Nếu GET, bạn có thể chỉ cần chuyển hướng đến hành động đó. Nhưng lý do cho điều đó không rõ ràng vì bạn có thể chuyển hướng từ bộ điều khiển A đến bất kỳ url nào bạn muốn.
Voldy

Câu trả lời:


64

Bạn có thể sử dụng chuyển hướng đến hành động đó:

redirect_to your_controller_action_url

Thêm về: Hướng dẫn đường ray

Để chỉ hiển thị hành động mới:

redirect_to your_controller_action_url and return

5
Tôi xin lỗi nhưng bạn có thể cho biết sự khác biệt giữa dòng đầu tiên và dòng thứ hai là gì không? Tôi nghĩ đầu tiên sẽ thực thi các dòng mã còn lại và sau đó chuyển hướng. Đúng không?
aks

Tôi nghĩ có lẽ ví dụ cuối cùng là lỗi đánh máy và nên được renderthay thế redirect_to. Bạn nói gì, @Spyros?
Magne

1
Xin chào @spyros, redirect_tokhông cho phép sử dụng post: :methodvà điều này có thể hữu ích đặc biệt khi chuyển hướng đến một createhành động đã tồn tại của một bộ điều khiển khác như @ddayan đã hỏi ở lần đầu tiên. Tôi gặp một tình huống tương tự trong đó trong một số tình huống, tôi nên tạo một đối tượng khác. Kêu gọi người kia createhành động có thể máy sấy ..
SanjiBukai

53

Để sử dụng một bộ điều khiển từ một bộ điều khiển khác, hãy làm như sau:

def action_that_calls_one_from_another_controller
  controller_you_want = ControllerYouWant.new
  controller_you_want.request = request
  controller_you_want.response = response
  controller_you_want.action_you_want
end

18
Nếu bạn muốn lệnh gọi lại vẫn được thực hiện controller_you_wantthì bạn sẽ làmcontroller_you_want.process(:action_you_want)
Constantijn Schepens

3
Cảm ơn! Điều này rất hữu ích cho những trường hợp bạn không muốn chuyển hướng, bạn chỉ cần một giải pháp nhanh chóng để áp dụng một hành động từ bộ điều khiển này sang bộ điều khiển khác. Chuyển hướng thực sự là một cái gì đó khác biệt. Ngoài ra: render status: :ok, json: JSON.parse(controller.render(:action_you_want).first)dường như làm việc để trở về JSON từ bộ điều khiển khác
Yourpalal

1
Câu trả lời tuyệt vời, đúng những gì tôi đang tìm kiếm. Một câu hỏi - định dạng yêu cầu các tham số cần thực hiện ở đây? Tôi giả sử rằng họ đang tồn tại controller_you_want.requestnhưng không thể làm cho việc kích hoạt này chuyển một phiên bản băm hoặc tham số.
SRack

Tôi không chắc bạn đang hỏi gì @SRack. Các paramstrở nên có sẵn để controller_you_wantbằng cách thiết lập requesttrong dòng thứ 3. Đó có phải là những gì bạn đang hỏi?
Sammy Larbi,

1
cố gắng trong đường ray 5, cho rendering nó phải đượcrender html: controller_you_want.process(:action_you_want)
Nazar kuliyev

41

Logic bạn trình bày không phải là MVC, sau đó không phải là Rails, tương thích.

  • Bộ điều khiển hiển thị một chế độ xem hoặc chuyển hướng

  • Một phương thức thực thi mã

Từ những cân nhắc này, tôi khuyên bạn nên tạo các phương thức trong bộ điều khiển và gọi chúng từ hành động của bạn.

Thí dụ:

 def index
   get_variable
 end

 private

 def get_variable
   @var = Var.all
 end

Điều đó nói rằng bạn có thể làm chính xác như vậy thông qua các bộ điều khiển khác nhau và triệu hồi một phương thức từ bộ điều khiển A khi bạn đang ở trong bộ điều khiển B.

Từ vựng là vô cùng quan trọng đó là lý do tại sao tôi nhấn mạnh nhiều.


Tôi biết mình không nên làm điều đó, nhưng đây không phải là một phần trong ứng dụng của tôi, nó chỉ để thử nghiệm và đánh giá ứng dụng của tôi.
ddayan

9
Yêu thích nó .. tách phương thức ra khỏi kết xuất và sau đó gọi phương thức riêng lẻ nếu cần. Chỉ một câu hỏi .. làm thế nào get_variablebây giờ có thể được gọi từ một bộ điều khiển khác?
FloatingRock

1
@FloatingRock chỉ nhận thấy câu hỏi của bạn / nhận xét: bạn có một vài lựa chọn: có thể được định nghĩa trong tổ tiên chung hoặc bạn có thể bao gồm chung mixin
apneadiving

thích câu trả lời, không chắc chắn về đoạn câu ở cuối
Gerard Simpson

30

Bạn có thể sử dụng url_forđể lấy URL cho bộ điều khiển và hành động, sau đó sử dụng redirect_tođể truy cập URL đó.

redirect_to url_for(:controller => :controller_name, :action => :action_name)

1
cái kia dường như không hoạt động với tôi, cái này có vẻ tốt hơn, nhưng làm thế nào để chúng ta chuyển các tham số?
msanjay

3
@msanjay bạn có thể chuyển chúng dưới dạng các tham số khác cho url_for. Ví dụ redirect_to url_for(:controller => :controller_name, :action => :action_name, :param1 => :val1, :param2 => :val2)sẽ dẫn đến kết quả /contorller_name/action_name?param1=val1&param2=val2. Xem tài liệu
Ariel Allon

nếu tôi cố gắng chuyển hướng_ đến một bộ điều khiển gốc như "MyOtherController", từ một bộ điều khiển như "Module :: MyController" .. nó sẽ giải quyết để gọi "mô-đun / MyOtherController" .. bất kỳ ý tưởng nào tôi có thể gọi bộ điều khiển gốc?
ggez44

12

Đây là cách thực hành không tốt khi gọi một hành động của bộ điều khiển khác.

Bạn nên

  1. sao chép hành động này trong bộ điều khiển B của bạn hoặc
  2. bọc nó dưới dạng một phương thức mô hình, phương thức này sẽ được chia sẻ cho tất cả các bộ điều khiển hoặc
  3. bạn có thể mở rộng hành động này trong bộ điều khiển A.

Ý kiến ​​cá nhân của tôi:

  1. Cách tiếp cận đầu tiên không phải là KHÔ nhưng vẫn tốt hơn là kêu gọi một hành động khác.
  2. Cách tiếp cận thứ hai là tốt và linh hoạt.
  3. Cách tiếp cận thứ ba là điều tôi đã từng làm thường xuyên. Vì vậy, tôi sẽ chỉ ra một ví dụ nhỏ.

    def create
      @my_obj = MyModel.new(params[:my_model])
      if @my_obj.save
        redirect_to params[:redirect_to] || some_default_path
       end
    end

Vì vậy, bạn có thể gửi cho tham số hành động này redirect_to, có thể là bất kỳ đường dẫn nào bạn muốn.


Xin chào, đối với giải pháp B quấn như một phương pháp mô hình, làm thế nào để quấn lại nếu không có mô hình nào cả? Chúng tôi đang làm việc trên một công cụ tìm kiếm và muốn gọi lượt xem tìm kiếm trong công cụ tìm kiếm từ các công cụ khác. Không có mô hình dữ liệu nào cho hành động tìm kiếm.
user938363

@ user938363 - Có thể có cả hai hành động hiển thị cùng một chế độ xem (ngay cả khi các hành động đó nằm trong các bộ điều khiển khác nhau). Bản thân lời gọi "render" sẽ được sao chép nhưng bản thân nó chỉ là một dòng trùng lặp - không quá tệ. Nếu bạn có nhiều logic chuẩn bị băm tham số để chuyển cho lệnh gọi kết xuất, thì bạn có thể tránh sao chép nó bằng cách chuyển nó vào tệp của chính nó (có thể là một mô hình trong /modelshoặc một lớp hoặc mô-đun thông thường trong /lib). Vấn đề duy nhất là nếu bộ điều khiển của bạn giao tiếp với chế độ xem thông qua các biến cá thể - bạn sẽ phải sửa lỗi trùng lặp đó theo cách khác.
antinome

Điều gì sẽ xảy ra nếu bạn có một UserController tạo Người dùng mới (đăng ký) và khi thành công, bạn muốn gọi một SessionsController và xác thực người dùng? Trong trường hợp này, bạn bằng cách này hay cách khác gọi SessionsController. Bất kỳ suy nghĩ về điều này?
dipole_moment

Tại sao nó là một thực hành xấu? câu trả lời của Sammy Lambi có vấn đề gì?
vasilakisfil

7

Có lẽ logic có thể được trích xuất thành một người trợ giúp? người trợ giúp có sẵn cho tất cả các lớp và không chuyển quyền kiểm soát. Bạn có thể kiểm tra bên trong nó, có lẽ là tên bộ điều khiển, để xem nó được gọi như thế nào.


6

Thành phần để giải cứu!

Với lý do, thay vì gọi các hành động trên các bộ điều khiển, người ta nên thiết kế bộ điều khiển để tách các phần được chia sẻ và tùy chỉnh của mã. Điều này sẽ giúp tránh cả hai - trùng lặp mã và phá vỡ mô hình MVC.

Mặc dù có thể được thực hiện trong một số cách khác nhau, sử dụng mối quan tâm ( thành phần ) là một thực hành tốt.

# controllers/a_controller.rb
class AController < ApplicationController
  include Createable

  private def redirect_url
    'one/url'
  end
end

# controllers/b_controller.rb
class BController < ApplicationController
  include Createable

  private def redirect_url
    'another/url'
  end
end

# controllers/concerns/createable.rb
module Createable
  def create
    do_usefull_things
    redirect_to redirect_url
  end
end

Hy vọng rằng sẽ giúp.


2

Bạn có thể gọi một hành động khác bên trong một hành động như sau:

redirect_to action: 'action_name'

class MyController < ApplicationController
  def action1
   redirect_to action: 'action2'
  end

  def action2
  end
end

-6

Tách các chức năng này khỏi bộ điều khiển và đưa chúng vào tệp mô hình. Sau đó, bao gồm tệp mô hình trong bộ điều khiển của bạn.


Đề xuất tồi. Sẽ lộn xộn trách nhiệm, chỉ để có MVC. Vấn đề với các cuộc gọi phiên / cookie trong mô hình, vv
Ain Tohvri
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.