Rails 4 - พารามิเตอร์ที่แข็งแกร่ง - วัตถุที่ซ้อนกัน


144

ฉันมีคำถามง่ายๆ แต่ยังไม่พบวิธีแก้ไข

ดังนั้นนี่คือสตริง JSON ที่ฉันส่งไปยังเซิร์ฟเวอร์:

{
  "name" : "abc",
  "groundtruth" : {
    "type" : "Point",
    "coordinates" : [ 2.4, 6 ]
  }
}

ด้วยวิธีการใช้ใบอนุญาตใหม่ฉันได้รับ:

params.require(:measurement).permit(:name, :groundtruth)

สิ่งนี้จะไม่มีข้อผิดพลาด แต่รายการฐานข้อมูลที่สร้างขึ้นมีnullแทนค่า groundtruth

ถ้าฉันเพิ่งตั้ง:

params.require(:measurement).permit!

ทุกอย่างได้รับการบันทึกตามที่คาดไว้ แต่แน่นอนว่าความปลอดภัยนี้จะช่วยรักษาความปลอดภัยของพารามิเตอร์

ฉันพบวิธีแก้ปัญหาวิธีอนุญาตให้ใช้อาร์เรย์ แต่ไม่ใช่ตัวอย่างเดียวโดยใช้วัตถุที่ซ้อนกัน สิ่งนี้จะต้องเป็นไปได้เพราะมันควรจะเป็นกรณีการใช้งานที่ค่อนข้างธรรมดา ดังนั้นมันทำงานอย่างไร



1
@winodadhikary มันถูกต้อง…ฉันคิดว่า OP สับสน ฟังดูแปลก ๆ เมื่อคุณต้องการอนุญาตแอตทริบิวต์ที่ซ้อนกันคุณระบุคุณสมบัติของวัตถุที่ซ้อนกันภายในอาร์เรย์ ในทางกลับกันถ้าคุณต้องการซ้อนวัตถุหลาย ๆ อันคุณต้องห่อมันไว้ในแฮช…ดูapi.rubyonrails.org/classes/ActionController/ … และgithub.com/rails/rails/blob/master/actionpack/lib/ …
j03w

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

คำตอบ:


181

ฟังดูแปลก ๆ เมื่อคุณต้องการอนุญาตแอตทริบิวต์ที่ซ้อนกันคุณระบุคุณสมบัติของวัตถุที่ซ้อนกันภายในอาร์เรย์ ในกรณีของคุณมันจะเป็น

อัปเดตตามที่แนะนำโดย @RafaelOliveira

params.require(:measurement)
      .permit(:name, :groundtruth => [:type, :coordinates => []])

ในทางกลับกันถ้าคุณต้องการซ้อนวัตถุหลาย ๆ อันคุณก็หุ้มมันไว้ในแฮช…แบบนี้

params.require(:foo).permit(:bar, {:baz => [:x, :y]})


Rails มีเอกสารที่ดีอยู่แล้วในเรื่องนี้: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

สำหรับการชี้แจงเพิ่มเติมคุณสามารถดูการใช้งานpermitและstrong_parametersตัวมันเอง: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247


5
ทั้งสองกรณีเหมือนกันในคำตอบนี้จริง ๆ แล้วมันคือว่าวงเล็บปีกกาเป็นทางเลือกรอบ ๆ {: groundtruth => [... ]}; มันเป็นแฮช แต่ล่ามสามารถระบุได้ว่าแฮชเริ่มต้นและสิ้นสุดที่ใดโดยไม่ต้องใช้วงเล็บปีกกาที่ชัดเจน
พูด

อาร์เรย์ของแอตทริบิวต์ที่ซ้อนกันไม่อนุญาตให้มีแอตทริบิวต์ที่ซ้อนกัน แอตทริบิวต์ที่ซ้อนกันและ attr_accessor แสดงอยู่ในแอปพลิเคชันของฉันเป็น "พารามิเตอร์ที่ไม่ได้รับการส่ง" ยังคงมองหาวิธีแก้ปัญหาที่ปลอดภัย
Katarzyna

ในกรณีที่มีวัตถุซ้อนกันหลายรายการคุณควรอนุญาตให้ใช้รหัสนี้ในการทำงาน ข้อมูลเพิ่มเติมที่นี่: stackoverflow.com/questions/18308714/…
Fabrice Carrega

1
อนุญาตให้ใช้แอตทริบิวต์ที่ซ้อนกันได้เพียงชุดเดียวเท่านั้น นี้จะไม่ทำงานในกรณีที่หนึ่งถึงหลาย ๆ
AKWF

23

ฉันพบว่าคำแนะนำนี้มีประโยชน์ในกรณีของฉัน:

  def product_params
    params.require(:product).permit(:name).tap do |whitelisted|
      whitelisted[:data] = params[:product][:data]
    end
  end

ตรวจสอบลิงค์ของความคิดเห็นของซาเวียร์ใน GitHub นี้

วิธีการนี้จะอนุญาตรายการทั้งหมดของพารามิเตอร์ [: การวัด] [: groundtruth]

การใช้คุณลักษณะคำถามดั้งเดิม:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end

4
เพียงบันทึกด้านข้างนี้จะยังคงแสดงในบันทึกเป็นพารามิเตอร์ที่ไม่ได้ส่ง แต่รุ่นจะยอมรับพวกเขาต่อไป
Weston Ganger

5
ไม่แน่ใจเกี่ยวกับ Rails 4 แต่ในโครงการ Rails 5 ของฉันฉันต้องโทรpermit!ไปที่ได้รับอนุญาตพิเศษหรืออย่างอื่นก็ยังไม่ได้รับการตอบรับหลังจากแตะมัน ในกรณีนี้มันจะเป็นparams[:measurement][:groundtruth].permit!
nayiaw

@nayiaw ฉันยังได้รับข้อความที่ยังไม่ได้ส่ง แต่การเพิ่มpermit!ทำให้เกิดข้อผิดพลาดนี้NoMethodError (undefined method ! ' สำหรับ # <Array: 0x007f80cb71ea00>): `
wuliwong

@wuliwong เป็นวิธีการที่ไม่สามารถใช้ได้ในpermit! Arrayคุณจะต้องมีสิทธิ์เข้าถึงอินสแตนซ์ของคลาสที่เกี่ยวข้องเพื่อให้สามารถเข้าถึงได้permit!(ไม่นานมานี้ดังนั้นฉันจึงลืมชื่อคลาส แต่มีลักษณะคล้ายActionController::Parametersกับเพจนี้ )
nayiaw

8

อนุญาตวัตถุที่ซ้อนกัน:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})

0

ถ้าเป็น Rails 5 เพราะสัญกรณ์แฮชใหม่: params.permit(:name, groundtruth: [:type, coordinates:[]])จะทำงานได้ดี

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