before_filter พร้อมพารามิเตอร์


84

ฉันมีวิธีที่ทำสิ่งนี้:

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

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

ฉันต้องการใช้วิธีนี้ในตัวควบคุมอื่น ๆ ด้วยดังนั้นฉันจึงคัดลอกเมธอดไปยังตัวช่วยที่รวมอยู่ใน application_controller

ปัญหาคือในคอนโทรลเลอร์บางตัว id ของโปรเจ็กต์ไม่ใช่:idสัญลักษณ์ แต่เป็น fe :project_id(และยังมี:idอยู่ (สำหรับรุ่นอื่น)

คุณจะแก้ปัญหานี้อย่างไร? มีตัวเลือกในการเพิ่มพารามิเตอร์ให้กับการกระทำ before_filter (เพื่อส่งผ่านพารามิเตอร์ที่ถูกต้อง) หรือไม่

คำตอบ:


86

ฉันจะทำเช่นนี้:

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

ที่ไหนcorrect_id_hereคือ ID Projectที่เกี่ยวข้องกับการเข้าถึง


2
มีวิธีเพิ่ม,:only => [:show]สัญลักษณ์ไหม ฉันได้รับข้อผิดพลาดพยายามbefore_filter { |c| c.authenticate_rights correct_id_here }, :only => [:show]
choise

27
ลองใช้วิธีรอบอื่น ๆbefore_filter(:only => [:show]) { <block_code_here> }: ตัวอย่างเพิ่มเติมที่นี่: apidock.com/rails/ActionController/Filters/ClassMethods/…
fguillen

1
หากคุณรักษาความปลอดภัยโดยการสร้างbefore_filterเมธอดส่วนตัวบางทีอาจแยกตัวประกอบอีกครั้ง (เช่นย้ายไปยังคอนโทรลเลอร์หลัก ApplicationController ฯลฯ ) คุณจะต้องใช้c.send(:filter_name, ...)เนื่องจากตัวกรองจะไม่ทำงานในบริบทคอนโทรลเลอร์ guide.rubyonrails.org/…
Richard Michael

2
การทำเช่นนี้ทำให้ before_filter ไม่สามารถแทนที่ / ข้ามได้เนื่องจากไม่มีชื่อ (proc) ค่าที่ฉันต้องการส่งผ่านคือระดับชั้นเรียน เป็นไปได้หรือไม่
oreoshake

1
@oreoshake: ฉันมีปัญหาเดียวกัน คุณพบวิธีแก้ปัญหาหรือไม่?
marcus3006

67

ด้วยน้ำตาลสังเคราะห์บางส่วน:

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

หรือถ้าคุณตัดสินใจที่จะแฟนซีมากขึ้น:

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

และตั้งแต่ Rails 4 before_actionซึ่งเป็นคำพ้องความหมายbefore_filterถูกนำมาใช้ดังนั้นจึงสามารถเขียนเป็น:

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

NB

->ย่อมาจากlambdaชื่อlambda literalแนะนำใน Ruby 1.9

%i จะสร้างอาร์เรย์ของสัญลักษณ์


5
คำตอบนี้มีความสวยงามมากขึ้นเนื่องจากแลมด้าเป็นค่าเริ่มต้นของบริบทการดำเนินการของคลาสดังนั้นจึงสามารถเรียกวิธีส่วนตัวโดยไม่ใช้ ".send"
David Pelaez

@ Vadym Tyemirov เป็นfind_campaignชื่อเมธอดส่วนตัวหรือไม่? ในparam=params[:id]เป็นparamชื่อของตัวแปรท้องถิ่นใหม่ที่จะถูกส่งผ่านเป็นอาร์กิวเมนต์นั้นfind_campaign? หมายความว่าภายในfind_campaignเมธอดส่วนตัวเราparamไม่ใช้params{:id]?
ahnbizcad

1
find_campaignอาจเป็นได้ แต่ฉันจะทำให้เป็นส่วนตัวเพื่อให้แน่ใจว่าเราจะไม่เปิดเผยสิ่งที่ไม่ได้บริโภค paramsเป็นตัวแปรแฮชที่มีให้สำหรับวิธีการของเราparamเป็นตัวแปรใด ๆ ที่คุณต้องส่งผ่านไปยังเมธอด find_campaign เช่นbefore_action ->(campaign_id=params[:id]) { find_campaign(campaign_id) }, only: %i| show edit update destroy |
Vadym Tyemirov

14

เพื่อดำเนินการต่อคำตอบของ @alex หากคุณต้องการ:exceptหรือ:onlyวิธีการบางอย่างนี่คือไวยากรณ์:

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

พบที่นี่


5

ฉันพบวิธีการบล็อกโดยใช้วงเล็บปีกกาแทนที่จะdo...endเป็นตัวเลือกที่ชัดเจนที่สุด

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

before_action เป็นเพียงไวยากรณ์ที่ใหม่กว่าที่ต้องการสำหรับ before_filter


-1

สิ่งนี้ควรใช้งานได้:

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

สิ่งนี้ควรส่งคืนparams[:project_id]หากมีอยู่ในแฮช params หรือส่งคืนparams[:id]หากไม่มี


ปัญหาคือบางครั้งทั้งสองอย่างมีอยู่ (ซ้อนกัน) และพบโครงการที่ไม่ถูกต้อง
choise

@choise: สิ่งนี้ไม่ควรเกิดขึ้น: หากproject_idมีอยู่orประโยคจะทำให้แน่ใจว่ามีการใช้สิ่งนี้ - เฉพาะในกรณีที่project_idไม่ได้ให้มาเท่านั้นidพารามิเตอร์จะถูกเลือก ในคำอื่น ๆ : เมื่อพารามิเตอร์ทั้งสองจะจัดที่ข้อเพื่อให้แน่ใจว่าค่าที่ถูกต้องถูกนำมาใช้ในขณะที่มันมักจะชอบor project_idโดยปกติแล้วคุณไม่ต้องการเรียกวิธีนี้เมื่อไม่มีอยู่หรือเมื่อไม่มีproject_idแต่มีidที่ไม่ได้อ้างอิงโครงการ
Ola Tuvesson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.