Rails response_with: มันทำงานอย่างไร


128

ฉันได้อ่านที่นี่และเกี่ยวกับวิธีที่ยอดเยี่ยมrespond_withใน Rails 3 แต่ฉันไม่พบการอ้างอิงถึงมันใน Rails APIs หรือโดยการค้นหาแหล่งที่มา ใครช่วยอธิบายให้ฉันฟังหน่อยได้ไหมว่ามันทำงานอย่างไร (คุณสามารถใช้ตัวเลือกอะไร ฯลฯ ) หรือชี้ให้ฉันดูที่ที่มันใช้งานจริงเพื่อที่ฉันจะได้อ่านโค้ดด้วยตัวเอง

คำตอบ:


128

อัปเดตสำหรับ Rails 4.2+

#respond_withและ::respond_to( nbวิธีการเรียน) จะไม่เป็นส่วนหนึ่งของทางรถไฟ พวกเขาถูกย้ายไปยังอัญมณีตอบโต้ของบุคคลที่สามณ Rails 4.2 ( บันทึกประจำรุ่น / กระทำลงวันที่ ส.ค. 2014) แม้ว่าระบบตอบกลับจะไม่รวมอยู่ใน Rails ตามค่าเริ่มต้น แต่ก็เป็นการพึ่งพาของ Devise ดังนั้นจึงมีให้ใช้งานในแอปพลิเคชัน Rails จำนวนมาก

#respond_to วิธีเช่นแต่ยังเป็นส่วนหนึ่งของทางรถไฟ (5.2rc1 เช่นการเขียนนี้)

เอกสาร Rails API อย่างเป็นทางการสำหรับActionController::MimeRespondsอธิบายวิธีการ#respond_toทำงาน เดิม Rails คู่มือการแสดงความคิดเห็นสำหรับเอกสาร#respond_withและ::respond_toยังสามารถพบได้ในการตอบสนองรหัสแหล่งอัญมณี


คำตอบเดิม

รหัสสำหรับผู้ตอบจะขึ้นอยู่กับคลาสและโมดูล MimeRespondsซึ่งรวมอยู่ในActionController :: Baseคลาสที่คุณApplicationControllerสืบทอดมา จากนั้นจะมีActionController :: Responderซึ่งมีพฤติกรรมเริ่มต้นเมื่อใช้ response_with


ตามค่าเริ่มต้นรางพฤติกรรมเดียวที่ให้ในการตอบสนองคือความพยายามโดยปริยายในการแสดงเทมเพลตที่มีชื่อตรงกับการกระทำ สิ่งที่นอกเหนือจากนั้นต้องการคำแนะนำเพิ่มเติมในการดำเนินการหรือการเรียก response_to ที่กำหนดเองพร้อมบล็อกเพื่อจัดการการตอบกลับหลายรูปแบบ

เนื่องจากตัวควบคุมส่วนใหญ่ใช้รูปแบบการปรับแต่งที่ค่อนข้างธรรมดาผู้ตอบสนองจึงให้ระดับนามธรรมพิเศษโดยการแนะนำพฤติกรรมเริ่มต้นมากขึ้น อ่านการดำเนินการที่เรียก to_xml / to_json สำหรับรูปแบบเฉพาะและการดำเนินการ mutator ที่มีการเปลี่ยนเส้นทางเช่นเดียวกับการดำเนินการ mutator ที่ประสบความสำเร็จ


มีโอกาสสองสามอย่างในการปรับแต่งพฤติกรรมของผู้ตอบตั้งแต่การปรับแต่งเล็กน้อยไปจนถึงการลบล้างหรือขยายพฤติกรรมโดยสมบูรณ์

ระดับชั้น: respond_to

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

# Responds to html and json on all actions
respond_to :html, :json

# Responds to html and json on index and show actions only.
respond_to :html, :json, :only => [:index,:show]

# Responds to html for everything except show, and json only for index, create and update
respond_to :html, :except => [:show]
respond_to :json, :only => [:index, :create, :update]

ระดับชั้น: responder

นี่คือแอตทริบิวต์คลาสที่เก็บการตอบกลับ นี่อาจเป็นอะไรก็ได้ที่ตอบสนองต่อการโทรซึ่งหมายความว่าคุณสามารถใช้ proc / lambda หรือคลาสที่ตอบสนองต่อการโทร อีกทางเลือกหนึ่งคือการผสมในหนึ่งหรือโมดูลกับการตอบกลับที่มีอยู่เพื่อโอเวอร์โหลดเมธอดที่มีอยู่เพิ่มพฤติกรรมเริ่มต้น

class SomeController < ApplicationController
  respond_to :json

  self.responder = proc do |controller, resources, options|
    resource = resources.last
    request = controller.request
    if request.get?
      controller.render json: resource
    elsif request.post? or request.put?
      if resource.errors.any?
        render json: {:status => 'failed', :errors => resource.errors}
      else
        render json: {:status => 'created', :object => resource}
      end
    end
  end
end

ในขณะที่อาจมีกรณีการใช้งาน edge ที่น่าสนใจ แต่ก็มีแนวโน้มว่าการขยายหรือผสมโมดูลเข้ากับเครื่องมือตอบกลับเริ่มต้นจะเป็นรูปแบบทั่วไป ไม่ว่าในกรณีใดตัวเลือกที่เกี่ยวข้องคือทรัพยากรและตัวเลือกเนื่องจากถูกส่งผ่านจาก from response_with

ระดับอินสแตนซ์: respond_with

ตัวเลือกที่นี่คือตัวเลือกที่จะถูกส่งไปยังการแสดงผลหรือ redirect_to ในคอนโทรลเลอร์ของคุณ แต่จะรวมไว้สำหรับสถานการณ์ความสำเร็จเท่านั้น สำหรับการดำเนินการ GET สิ่งเหล่านี้จะเป็นการเรียกการแสดงผลสำหรับการดำเนินการอื่น ๆ จะเป็นตัวเลือกสำหรับการเปลี่ยนเส้นทาง อาจเป็นประโยชน์ที่สุดคือ:locationตัวเลือกซึ่งสามารถใช้เพื่อลบล้างเส้นทางการเปลี่ยนเส้นทางนั้นในกรณีที่อาร์กิวเมนต์สำหรับ response_with ไม่เพียงพอที่จะสร้าง URL ที่ถูกต้อง

# These two are essentially equal
respond_with(:admin, @user, @post)
respond_with(@post, :location => admin_user_post(@user, @post)

# Respond with a 201 instead of a 200 HTTP status code, and also
# redirect to the collection path instead of the resource path
respond_with(@post, :status => :created, :location => posts_path)

# Note that if you want to pass a URL with a query string
# then the location option would be needed.
# /users?scope=active
respond_with(@user, :location => users_path(:scope => 'active'))

ในอีกทางเลือกหนึ่งอัญมณีผู้ตอบกลับไม่เพียง แต่จัดเตรียมโมดูลบางส่วนสำหรับการลบล้างพฤติกรรมเริ่มต้นบางอย่าง จะแทนที่การตอบกลับเริ่มต้นด้วยคลาสที่ไม่ระบุชื่อที่ขยายการตอบกลับเริ่มต้นและจัดเตรียมวิธีระดับคลาสสำหรับการผสมในโมดูลที่กำหนดเองกับคลาสนี้ สิ่งที่มีประโยชน์ที่สุดในที่นี้คือแฟลชตอบกลับซึ่งมีชุดแฟลชเริ่มต้นโดยมอบหมายการปรับแต่งให้กับระบบ I18n config/locales/en.ymlตามค่าเริ่มต้น

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


1
ฉันคิดว่าคุณหมายถึง (ในชั้นเรียน) self.responder =เพราะresponder =จะมอบหมายให้ท้องถิ่น
horseyguy

ขอบคุณ! การมีอยู่ของlocationตัวเลือกคือข้อมูลที่ฉันต้องการ!
JellicleCat

1
คำอธิบายนั้นยังคงเกี่ยวข้องกับ Rails 4/5 หรือไม่ ฉันได้ยินมาว่าrespond_withจะเลิกใช้งาน แต่ฉันไม่สามารถหาสาเหตุได้
Arnlen

1
@Arnlen, response_with ถูกแยกออกมาเป็นอัญมณีที่แยกต่างหาก ' ผู้ตอบสนอง '
Nick Roz

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