before_filter với các tham số


84

Tôi có một phương pháp thực hiện một cái gì đó như sau:

before_filter :authenticate_rights, :only => [:show]

def authenticate_rights
  project = Project.find(params[:id])
  redirect_to signin_path unless project.hidden
end

Tôi cũng muốn sử dụng phương pháp này trong một số Bộ điều khiển khác, vì vậy tôi đã sao chép phương thức này vào một trình trợ giúp có trong application_controller.

vấn đề là, trong một số bộ điều khiển, id cho dự án không phải là :idbiểu tượng mà là fe :project_id(và a cũng :idcó (đối với một mô hình khác)

Bạn sẽ giải quyết vấn đề này như thế nào? có tùy chọn để thêm một tham số vào hành động before_filter (để chuyển param bên phải) không?

Câu trả lời:


86

Tôi sẽ làm như thế này:

before_filter { |c| c.authenticate_rights correct_id_here }

def authenticate_rights(project_id)
  project = Project.find(project_id)
  redirect_to signin_path unless project.hidden
end

Trong trường hợp correct_id_herelà id liên quan đến truy cập một Project.


2
có cách nào để thêm một ,:only => [:show]biểu tượng? Tôi gặp lỗi khi thửbefore_filter { |c| c.authenticate_rights correct_id_here }, :only => [:show]
choise

27
Thử khoảng cách khác: before_filter(:only => [:show]) { <block_code_here> }. Các ví dụ khác ở đây: apidock.com/rails/ActionController/Filters/ClassMethods/…
fguillen

1
Nếu bạn bảo mật điều này bằng cách đặt before_filterphương thức riêng tư, thì có thể tái yếu tố (ví dụ: di chuyển nó sang bộ điều khiển mẹ, ApplicationController, v.v.), bạn sẽ cần sử dụng c.send(:filter_name, ...)vì bộ lọc sẽ không chạy trong ngữ cảnh bộ điều khiển. Guide.rubyonrails.org/…
Richard Michael

2
Việc làm này giúp cho before_filter không thể bị ghi đè / bỏ qua do thiếu tên (proc). Các giá trị tôi muốn chuyển vào là cấp độ lớp. Điều đó có thể không?
oreoshake

1
@oreoshake: tôi cũng có vấn đề tương tự. Bạn đã tìm thấy một giải pháp?
marcus3006

67

Với một số đường cú pháp:

before_filter -> { find_campaign params[:id] }, only: [:show, :edit, :update, :destroy]

Hoặc nếu bạn quyết định trở nên lạ mắt hơn:

before_filter ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

Và vì Rails 4 before_action, một từ đồng nghĩa với before_filter, đã được giới thiệu, nên nó có thể được viết là:

before_action ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

NB

->viết tắt của lambda, được gọi là nghĩa đen lambda , giới thiệu trong Ruby 1.9

%i sẽ tạo ra một mảng ký hiệu


5
Câu trả lời này là tao nhã hơn vì giá trị mặc định lambda với bối cảnh thực hiện các lớp, do đó phương pháp tư nhân có thể được gọi mà không sử dụng '.send'
David Pelaez

@Vadym Tyemirov Có phải find_campaigntên phương thức riêng không? Trong param=params[:id], paramtên của biến cục bộ mới sẽ được chuyển làm đối số find_campaign? Có nghĩa là bên trong find_campaignphương thức private, chúng ta paramkhông sử dụng params{:id],?
ahnbizcad

1
find_campaigncó thể là một trong hai, nhưng tôi sẽ đặt nó ở chế độ riêng tư để đảm bảo rằng chúng tôi không tiết lộ những gì không được tiêu thụ. paramslà một biến băm có sẵn với các phương pháp của chúng tôi, parambất kỳ biến mà bạn cần phải vượt qua để phương pháp find_campaign, ví dụ:before_action ->(campaign_id=params[:id]) { find_campaign(campaign_id) }, only: %i| show edit update destroy |
Vadym Tyemirov

14

Để tiếp tục câu trả lời @alex ', nếu bạn muốn :excepthoặc :onlymột số phương pháp, đây là cú pháp:

before_filter :only => [:edit, :update, :destroy] do |c| c.authenticate_rights params[:id] end 

Tìm thấy ở đây .


5

Tôi thấy phương pháp khối sử dụng dấu ngoặc nhọn thay vì do...endlà lựa chọn rõ ràng nhất

before_action(only: [:show]) { authenticate_rights(id) }

before_action chỉ là cú pháp ưu tiên mới hơn cho before_filter


-1

Điều này sẽ hoạt động:

project = Project.find(params[:project_id] || params[:id])

Điều này sẽ trả về params[:project_id]nếu nó có trong params hash hoặc trả về params[:id]nếu nó không có.


vấn đề là, đôi khi cả hai đều có mặt (lồng nhau) và nó tìm thấy một dự án không phù hợp.
choise

@choise: Điều đó sẽ không xảy ra: nếu project_idcó thì ormệnh đề sẽ đảm bảo điều này được sử dụng - chỉ khi a project_idkhông được cung cấp thì idtham số mới được chọn. Nói cách khác: khi cả hai tham số được cung cấp, ormệnh đề đảm bảo giá trị chính xác được sử dụng, vì nó sẽ luôn thích hơn project_id. Đương nhiên, bạn sẽ không muốn gọi phương thức này khi không có hoặc khi không có project_idnhưng có một phương thức idkhông tham chiếu đến một dự án.
Ola Tuvesson
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.