วิธีทดสอบว่ามีพารามิเตอร์อยู่ในรางหรือไม่


179

ฉันใช้คำสั่ง IF ใน Ruby on Rails เพื่อลองและทดสอบว่ามีการตั้งค่าพารามิเตอร์คำขอหรือไม่ ไม่ว่าจะมีการตั้งค่าพารามิเตอร์ทั้งสองหรือไม่ส่วนแรกของสิ่งต่อไปนี้ถ้าบล็อกถูกเรียกใช้ ฉันจะทำให้ส่วนนี้ได้รับการทริกเกอร์เฉพาะเมื่อทั้ง params [: หนึ่ง] และ params [: two] ถูกตั้งค่าอย่างไร

if (defined? params[:one]) && (defined? params[:two])
 ... do something ...
elsif (defined? params[:one])
 ... do something ...
end

10
@Nakilon: เนื่องจากว่าparamsเป็นวิธีการควบคุม Rails (ที่เกิดขึ้นเพื่อส่งกลับ HashWithIndifferentAccess) มันเป็นเรื่องเกี่ยวกับ Rails
mu สั้นเกินไป

คำตอบ:


348

คุณต้องการhas_key?:

if(params.has_key?(:one) && params.has_key?(:two))

เพียงแค่การตรวจสอบif(params[:one])จะถูกหลอกโดย "มี แต่ไม่มี" และ "มี แต่ค่าเท็จ" และคุณกำลังถามเกี่ยวกับการดำรงอยู่ คุณอาจต้องแยกความแตกต่าง:

  • ไม่ได้มีเลย
  • มี nilแต่
  • มี falseแต่
  • มี แต่สตริงว่าง

เช่นกัน ยากที่จะพูดโดยไม่มีรายละเอียดเพิ่มเติมเกี่ยวกับสถานการณ์ที่แม่นยำของคุณ


3
@sawa ไม่สามารถส่งผ่านnilพารามิเตอร์ได้ หากพารามิเตอร์มีอยู่มันจะเป็นสตริงว่าง
Jacob Relkin

5
@Jacob: ไม่มีการรับประกันว่าparamsยังไม่ได้รับการประมวลผลล่วงหน้าก่อนที่เราจะไปถึงจุดที่เรากำลังตรวจสอบสิ่งที่อยู่ในนั้น ดังนั้นรายการกรณีพิเศษที่เป็นไปได้ในการตรวจสอบของฉัน ดีที่สุดที่จะพูดในสิ่งที่คุณหมายถึง IMHO
mu สั้นเกินไป

1
@muistooshort สิ่งที่ไม่ดีของฉันนั่นคือPython :(
FloatingRock

2
ใน Rails 5 วัตถุ params ไม่ใช่แฮชอีกต่อไปและฉันไม่เห็นkey?วิธีการ edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson

1
@muistooshort โอ้เยี่ยมมาก ฉันยังลังเลที่จะใช้วิธีการที่ไม่ได้เป็นส่วนหนึ่งของ API เอกสาร แต่ฉันแน่ใจว่าปลอดภัยพอ params.to_h.key?ตอนนี้ฉันกำลังโทรหา
stephen.hanson

86

ฉันเป็นแฟนตัวยงของ

params[:one].present?

เพียงเพราะมันเก็บparams[sym]ฟอร์มไว้เพื่อให้อ่านง่ายขึ้น


1
ดีกว่าสั้นกว่า 3 ตัวอักษรเรียบง่าย
Bengala

อันนี้ควรเป็นคำตอบที่ถูกต้องที่สุด!
jacktrade

4
ระวังการใช้ของขวัญ? ด้วย booleans (วิธีที่ไม่ได้กำหนด `ปัจจุบัน 'สำหรับจริง: TrueClass) คำตอบที่ได้รับการยอมรับกับ has_key? ใช้ได้กับทุกประเภท
StCleezy

2
เพื่อให้ชัดเจนสิ่งนี้ไม่สามารถใช้งานได้ในบางกรณีเช่น false.present? => false ดังนั้นจะไม่ทำงานเมื่อเช่นผ่านพารามิเตอร์ผ่าน json body ที่สามารถส่งผ่าน booleans
James

1
หากคุณใช้ตรรกะนี้ในมุมมองปัจจุบันจะล้มเหลวเนื่องจากอาร์เรย์พารามิเตอร์กำลังถูกเรียกใช้และล้มเหลวหากไม่มี has_keyให้สิ่งที่คุณต้องการแทน
Jerome

22

ใช้เปล่า? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

unless params[:one].blank? && params[:two].blank?

จะคืนค่าจริงถ้าว่างหรือไม่มี

ยัง ... ที่จะไม่ทำงานถ้าคุณกำลังทดสอบค่าบูลีน .. ตั้งแต่

>> false.blank?
=> true

ในกรณีที่คุณสามารถใช้

unless params[:one].to_s.blank? && params[:two].to_s.blank?

3
หรือซึ่งจะส่งกลับตรงข้ามของpresent? blank?ดังนั้นคุณสามารถเปลี่ยนมันunlessให้เป็นifถ้าคุณต้องการ
Inkling

@ หมึกที่ใช้งานได้ แต่ inline unlessมันก็โอเค แต่ใช่ฉันชอบมากขึ้นifด้วยpresent?
Orlando

18

คุณสามารถเขียนได้กระชับกว่าดังต่อไปนี้:

required = [:one, :two, :three]
if required.all? {|k| params.has_key? k}
  # here you know params has all the keys defined in required array
else
  ...
end

1
ฉันชอบความสะอาดของสิ่งนี้ ฉันใหม่กับทับทิมแม้ว่า ข้อผิดพลาดใด ๆ หรือกรณีขอบพลาดฉันควรรู้
ฌอน

10

ง่ายเหมือนพาย

if !params[:one].nil? and !params[:two].nil?
  #do something...
elsif !params[:one].nil?
  #do something else...
elsif !params[:two].nil?
  #do something extraordinary...
end

3
ไม่ได้ตรวจสอบว่ามีพารามิเตอร์ แต่ตั้งค่าเป็นศูนย์หรือไม่
Daemin

@Daemin ในความเป็นจริงแม้ว่าพารามิเตอร์ไม่สามารถตั้งค่าเป็นศูนย์ในส่วนหัวคำขอ มันเป็นศูนย์หรือสตริง
Jacob Relkin

ใช่ แต่ตามที่คนอื่น ๆ ระบุไว้อาจมีการเปลี่ยนแปลงอย่างอื่นปลั๊กอินอัญมณีหรือรหัสของคุณเองหรือไม่สามารถแยกวิเคราะห์ด้วยเหตุผลที่แปลกประหลาดบางอย่าง
Daemin

4
การสร้างพายนั้นซับซ้อนจริง ๆ
Cesar

ทำไมคุณไม่ใช้ยกเว้น
Alireza Rahmani Khalili


5

วิธีง่ายๆในการให้ค่าเริ่มต้นกับพารามิเตอร์ของคุณ: params[:foo] ||= 'default value'


2
คุณก็ทำได้เช่นparams.fetch(:foo, 'default value')กัน
Mario Pérez

5

ฉันเพิ่งอ่านสิ่งนี้ในคลาส RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

คุณสามารถใช้ได้ blank?วิธีการซึ่งเทียบเท่ากับparams[:one].nil? || params[:one].empty?

(เช่น)

if params[:one].blank? 
  # do something if not exist
else
  # do something if exist
end

สมบูรณ์แบบฉันกำลังใช้params[:one].nil? || params[:one].empty?
GOXR3PLUS

มีคีย์เป็นวิธีที่ถูกต้องวิธีการของคุณสันนิษฐานว่ามีพารามิเตอร์นี้อยู่แล้วดังนั้นคุณจึงตรวจสอบว่าไม่มีศูนย์ซึ่งสามารถใช้งานได้ แต่ไม่ใช่วิธีที่ดีที่สุด
พอล Brunache

3

คุณยังสามารถทำสิ่งต่อไปนี้:

unless params.values_at(:one, :two, :three, :four).includes?(nil)
 ... excute code ..
end 

ฉันมักจะใช้โซลูชันข้างต้นเมื่อฉันต้องการตรวจสอบมากกว่าหนึ่งหรือสอง params

.values_at ส่งกลับและอาร์เรย์ด้วยศูนย์ในตำแหน่งของคีย์พารามิเตอร์ใด ๆ ที่ไม่ได้กำหนด เช่น:

some_hash = {x:3, y:5}
some_hash.values_at(:x, :random, :y}

จะส่งคืนสิ่งต่อไปนี้:

[3,nil,5] 

.includes (ไม่มี) จากนั้นตรวจสอบอาร์เรย์เพื่อหาค่าใด ๆ มันจะกลับมาจริงคืออาร์เรย์รวมศูนย์

ในบางกรณีคุณอาจต้องการตรวจสอบว่าพารามิเตอร์ไม่มีและสตริงว่างเปล่าในค่าเท็จ

คุณสามารถจัดการค่าเหล่านั้นได้โดยเพิ่มรหัสต่อไปนี้ไว้เหนือคำสั่งเว้นแต่

params.delete_if{|key,value| value.blank?}

ทั้งหมดเข้าด้วยกันมันจะมีลักษณะเช่นนี้:

 params.delete_if{|key,value| value.blank?}
 unless params.values_at(:one, :two, :three, :four).includes?(nil)
   ... excute code ..
  end

สิ่งสำคัญคือต้องทราบว่า delete_if จะแก้ไขแฮช / params ของคุณดังนั้นควรใช้ด้วยความระมัดระวัง

วิธีการแก้ปัญหาข้างต้นจะต้องใช้เวลาในการตั้งค่ามากขึ้น แต่ก็คุ้มค่าหากคุณกำลังตรวจสอบมากขึ้นจากนั้นเพียงหนึ่งหรือสองพารามิเตอร์


3

นอกจากนี้ในการตอบก่อนนี้: has_key?และhas_value?มีทางเลือกที่สั้นกว่าในรูปแบบของและkey? value?ทีมทับทิมยังแนะนำให้ใช้ทางเลือกที่สั้นกว่า แต่เพื่อความสะดวกในการอ่านบางคนอาจยังคงชอบวิธีการเหล่านี้ในรุ่นที่ยาวกว่า

ดังนั้นในกรณีของคุณมันจะเป็นอย่างไร

if params.key?(:one) && params.key?(:two)
  ... do something ...
elsif params.key?(:one)
  ... do something ...
end

NB! .key?จะตรวจสอบว่ามีรหัสอยู่หรือไม่และจะละเว้นค่าที่เป็นไปได้ทั้งหมด ตัวอย่างเช่น:

2.3.3 :016 > a = {first: 1, second: nil, third: ''}
  => {:first=>1, :second=>nil, :third=>""}
2.3.3 :017 > puts "#{a.key?(:first)}, #{a.key?(:second)}, #{a.key?(:third), #{a.key?(:fourth)}}"
true, true, true, false

2

นี่คือสิ่งที่ฉันทำ

before_action :validate_presence

แล้ววิธีการต่อไปนี้:

    def check_presence
  params[:param1].present? && params[:param2].present?
 end

 def validate_presence
  if !check_presence
    render json:  {
                      error:  {
                                message: "Bad Request, parameters missing.",
                                status: 500
                              }
                    }
  end
 end

1

แก้ไขปัญหานี้ด้วยกัน:

before_filter :validate_params

private

def validate_params
  return head :bad_request unless params_present?
end

def params_present?  
  Set.new(%w(one two three)) <= (Set.new(params.keys)) &&
  params.values.all?
end

บรรทัดแรกจะตรวจสอบว่าคีย์เป้าหมายของเรามีอยู่ในคีย์ของพารามิเตอร์โดยใช้ <= ชุดย่อยหรือไม่ ผู้ประกอบการ Enumerable.all? โดยไม่มีบล็อกต่อค่าเริ่มต้นส่งกลับเท็จถ้าค่าใด ๆ เป็นศูนย์หรือเท็จ


0
if params[:one] && param[:two]
  ... excute code ..
end

นอกจากนี้คุณยังสามารถตรวจสอบว่าพารามิเตอร์ว่างเปล่าโดยใช้พารามิเตอร์ [: two] หรือไม่


1
ในขณะนี้ครอบคลุมกรณีที่กำหนดพารามิเตอร์ทั้งสอง มันไม่ครอบคลุมกรณีที่หนึ่งในนั้นประเมินเป็นเท็จ
EmFi

0

ฉันลองช้า แต่ตอบจากสายตาไกล:

หากคุณต้องการทราบว่ามีการตั้งค่าแฮช (ใด ๆ ) ค่าทั้งหมดข้างต้นจะตอบรับค่าจริงขึ้นอยู่กับมุมมองของพวกเขา

หากคุณต้องการที่จะทดสอบ (GET / POST .. ) params ของคุณคุณควรใช้สิ่งที่พิเศษมากขึ้นกับสิ่งที่คุณคาดหวังว่าจะค่าของparams[:one]บางอย่างเช่น

if params[:one]~=/   / and  params[:two]~=/[a-z]xy/

ละเว้นพารามิเตอร์ (GET / POST) ราวกับว่าพวกเขาไม่ได้ตั้งค่าถ้าพวกเขาไม่พอดีเช่นที่คาดไว้

เพียงแค่if params[:one] มีหรือไม่มีการตรวจจับไม่มี / จริงเป็นขั้นตอนเดียวที่จะเปิดหน้าของคุณสำหรับการแฮ็กเพราะมันเป็นขั้นตอนต่อไปที่จะใช้สิ่งที่ชอบselect ... where params[:one] ...ถ้ามีวัตถุประสงค์หรือไม่ใช้งานหรือภายในหรือหลังกรอบ

คำตอบหรือเพียงคำใบ้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.