มีฟังก์ชัน Rails เพื่อตรวจสอบว่ามีบางส่วนหรือไม่


98

เมื่อฉันแสดงผลบางส่วนที่ไม่มีอยู่ฉันจะได้รับข้อยกเว้น ฉันต้องการตรวจสอบว่ามีบางส่วนหรือไม่ก่อนที่จะแสดงผลและในกรณีที่ไม่มีอยู่จริงฉันจะแสดงอย่างอื่น ฉันใช้รหัสต่อไปนี้ในไฟล์. erb ของฉัน แต่ฉันคิดว่าควรมีวิธีที่ดีกว่าในการทำสิ่งนี้:

    <% begin %>
      <%= render :partial => "#{dynamic_partial}" %>
    <% rescue ActionView::MissingTemplate %>
      Can't show this data!
    <% end %>

1
คำตอบที่ใช้rescueมีความเสี่ยง ฉันจะดูวิธีแก้ปัญหาอื่น ๆ ก่อนใช้งาน
Grant Hutchins

คำตอบ:


99

ขณะนี้ฉันใช้สิ่งต่อไปนี้ในโครงการ Rails 3 / 3.1 ของฉัน:

lookup_context.find_all('posts/_form').any?

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

นอกจากนี้ยังใช้งานได้ใน Rails 4


9
lookup_context.exists? ('posts / find') ไม่ได้ผลสำหรับฉัน แต่ฉันใช้ lookup_context.exists? (ชื่อคำนำหน้าบางส่วน) หรือ lookup_content.exists? ('find', 'posts', true) ในตัวอย่างนี้
Jenn

2
นี่คือวิธีปัจจุบัน (ราง> = 3.2) ในการตรวจสอบแม่แบบ (แหล่งapidock )
maček

1
lookup_context.exists?("find", lookup_context.prefixes, true)หากบางส่วนที่อยู่ในโฟลเดอร์เดียวกันเป็นแม่แบบมุมมองปัจจุบันคุณสามารถใช้ ด้วยวิธีนี้คุณไม่จำเป็นต้องฮาร์ดโค้ดไดเร็กทอรีมุมมองลงในการโทร หมายเหตุนี่เป็นเพียงบางส่วน สำหรับ non-partials ให้ละเว้น arg สุดท้าย (หรือใช้ false แทน true)
Nathan Wallace

72

ฉันก็ดิ้นรนกับเรื่องนี้เช่นกัน นี่เป็นวิธีที่ฉันใช้:

<%= render :partial => "#{dynamic_partial}" rescue nil %>

โดยทั่วไปหากไม่มีบางส่วนให้ทำอะไรเลย คุณต้องการพิมพ์อะไรบางอย่างถ้าบางส่วนหายไปหรือไม่?

แก้ไข 1:โอ้ฉันล้มเหลวในการอ่านจับใจความ คุณบอกว่าคุณต้องการแสดงอย่างอื่น ในกรณีนี้เป็นอย่างไร?

<%= render :partial => "#{dynamic_partial}" rescue render :partial => 'partial_that_actually_exists' %>

หรือ

<%= render :partial => "#{dynamic_partial}" rescue "Can't show this data!" %>

แก้ไข 2:

ทางเลือก: การตรวจสอบการมีอยู่ของไฟล์บางส่วน:

<%= render :partial => "#{dynamic_partial}" if File.exists?(Rails.root.join("app", "views", params[:controller], "_#{dynamic_partial}.html.erb")) %>

6
คำถามของฉันคือฉันไม่ต้องการใช้ข้อยกเว้นในการควบคุมการไหลซึ่งเป็นการต่อต้านรูปแบบ: stackoverflow.com/questions/1546514/…
Daniel Cukier

6
ข้อยกเว้นคือการควบคุมโฟลว์ประเภทหนึ่งที่ใช้จัดการกับสิ่งที่เกิดขึ้นนอกเหนือจากการทำงานปกติของโปรแกรม หากพลวัตบางส่วนควรจะอยู่ที่นั่น แต่มีบางอย่างผิดพลาดและไม่ได้อยู่ที่นั่นนั่นเป็นการใช้ข้อยกเว้นที่สมเหตุสมผล (แน่นอนว่า IMO - การใช้ข้อยกเว้นอย่างเหมาะสมคือสงครามศักดิ์สิทธิ์นั่นเอง) ฉันจะบอกว่าทางเลือกของคุณคือตรวจสอบระบบไฟล์ว่ามีไฟล์อยู่จริงหรือไม่ ฉันจะอัปเดตคำตอบของฉันด้วยรหัสนั้น
Jeff

3
ฉันชอบวิธีแก้ปัญหาอย่างไรก็ตามมันกลืนข้อยกเว้นใด ๆ ที่โยนลงในบางส่วน IMHO ทำให้ยากต่อการติดตามข้อผิดพลาด
Matt

5
หากคุณมีข้อยกเว้นประเภทอื่นrescue nilและ... rescue ...วิธีการจะซ่อนไว้ ซึ่งนำไปสู่จุดบกพร่องที่ยากต่อการแก้ไข
nicholaides

8
ฉันไม่ชอบวิธีแก้ปัญหานี้จริงๆ การช่วยชีวิตมีราคาแพงและ File.exists? ถือว่าบางส่วนสามารถอยู่ในตำแหน่งเดียวเท่านั้น วิธีแก้ปัญหาของ @ Rein โดยใช้ lookup_context เป็นวิธีที่จะไปฉันเชื่อ
Bert Goethals

53

จากภายในมุมมอง template_exists? ใช้งานได้ แต่รูปแบบการเรียกใช้ไม่ได้กับสตริงชื่อบางส่วน แต่ใช้ template_exists แทน? (ชื่อคำนำหน้าบางส่วน)

ในการตรวจสอบบางส่วนบนเส้นทาง: app / views / posts / _form.html.slim

ใช้:

lookup_context.template_exists?("form", "posts", true)

ใน Rails 3.0.10 ฉันพบว่าถ้าฉันมีส่วนขยายสำรองเช่น app / views / posts / _foo.txt.erb ฉันจำเป็นต้องเพิ่มสิ่งนั้นในอาร์กิวเมนต์เป็น: template_exists? ("foo.txt", "posts" , จริง)
Gabe Martin-Dempesy

สิ่งนี้เลิกใช้แล้วในราง 3.2
maček

ดูเหมือนว่าจะไม่ถูกมอบหมายใน Rails 3.2.x อย่างไรก็ตามอาร์กิวเมนต์ที่สองคืออาร์เรย์ของคำนำหน้า นอกจากนี้ยังมีอยู่ในตัวควบคุมปัจจุบัน
Brendan

2
คุณสามารถใช้ lookup_context.prefixes เป็นอาร์กิวเมนต์ที่สอง: lookup_context.template_exists? ("form", lookup_context.prefixes, true)
lion.vollnhals

นี่คือคำตอบที่ดีกว่าในแง่ของการเข้าถึงข้อมูลนี้จากเลเยอร์มุมมอง
Brendon Muir

30

ใน Rails 3.2.13 หากคุณอยู่ในคอนโทรลเลอร์คุณสามารถใช้สิ่งนี้:

template_exists?("#{dynamic_partial}", _prefixes, true)

template_exists?ได้รับมอบหมายให้lookupcontextตามที่คุณเห็นในAbstractController::ViewPaths

_prefixes ให้บริบทของห่วงโซ่การสืบทอดของคอนโทรลเลอร์

true เนื่องจากคุณกำลังมองหาบางส่วน (คุณสามารถละอาร์กิวเมนต์นี้ได้หากคุณต้องการเทมเพลตทั่วไป)

http://api.rubyonrails.org/classes/ActionView/LookupContext/ViewPaths.html#method-i-template_exists-3F


โหวตแล้ว ทันสมัยมากขึ้นและอธิบายพารามิเตอร์ได้ดีขึ้น
jacobsimeon

4
จากมุมมองของ (เช่นรูปแบบ) lookup_context.template_exists?("navbar", controller._prefixes, :partial)งานนี้: สิ่งนี้จะบอกฉันว่าเทมเพลตปัจจุบันที่แสดงเลย์เอาต์นี้มี "navbar" บางส่วนหรือไม่และถ้าเป็นเช่นนั้นฉันสามารถแสดงผลได้ ฉันผ่าน:partialเพียงเพื่อให้ชัดเจนว่าบูลีนคืออะไร - :partialเป็นความจริง ขอบคุณสำหรับ_prefixesบิต @Flackou!
pdobb

แทนที่_prefixesด้วยnilถ้าคุณกำลังเรียกบางส่วนที่อยู่ในไดเรกทอรีหลักอื่น
เบ็น

8

ฉันรู้ว่าคำตอบนี้ได้รับคำตอบและมีอายุเป็นล้านปี แต่นี่คือวิธีที่ฉันจะแก้ไขสิ่งนี้ให้ฉันได้ ...

ราง 4.2

ก่อนอื่นฉันใส่สิ่งนี้ใน application_helper.rb ของฉัน

  def render_if_exists(path_to_partial)
    render path_to_partial if lookup_context.find_all(path_to_partial,[],true).any?
  end

และตอนนี้แทนที่จะโทร

<%= render "#{dynamic_path}" if lookup_context.find_all("#{dynamic_path}",[],true).any? %>

ฉันเพิ่งโทร <%= render_if_exists "#{dynamic_path}" %>

หวังว่าจะช่วยได้ (ยังไม่ได้ลองใน rail3)


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

นี่คือสิ่งที่ฉันกำลังมองหา คำตอบที่สะอาดมาก
ซันนี่

1
@BenPolinsky ฉันคิดว่าคุณสามารถใช้def render_if_exists(*args); render(*args) if ...สำหรับสิ่งนั้นได้
ไซต์

6

ฉันใช้กระบวนทัศน์นี้หลายครั้งและประสบความสำเร็จอย่างมาก:

<%=
  begin
    render partial: "#{dynamic_partial}"
  rescue ActionView::MissingTemplate
    # handle the specific case of the partial being missing
  rescue
    # handle any other exception raised while rendering the partial
  end
%>

ข้อดีของโค้ดด้านบนคือเราสามารถจัดการลากจูงในบางกรณีได้:

  • บางส่วนหายไปแน่นอน
  • มีบางส่วน แต่เกิดข้อผิดพลาดด้วยเหตุผลบางประการ

หากเราใช้โค้ด<%= render :partial => "#{dynamic_partial}" rescue nil %>หรืออนุพันธ์บางส่วนอาจมีบางส่วนอยู่ แต่จะเพิ่มข้อยกเว้นซึ่งจะถูกกินอย่างเงียบ ๆ และกลายเป็นที่มาของความเจ็บปวดในการแก้ไขข้อบกพร่อง


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