รูปแบบการประดิษฐ์ภายในตัวควบคุมที่แตกต่างกัน


129

ฉันใช้อัญมณีประดิษฐ์สำหรับกระบวนการ sign_in / sign_out

ฉันสร้างไฟล์มุมมองจากการประดิษฐ์โดยใช้ rails g devise views

ฉันเห็นว่ามีไฟล์รุ่น / เซสชัน / new.html.erb ซึ่งมีแบบฟอร์มสำหรับลงชื่อเข้าใช้

ฉันสร้างไฟล์อื่นอีกครั้งประดิษฐ์ / session / _form.html.erb และทำ<%= render 'form' %>ภายในไฟล์ new.html.erb และนั่นก็ใช้ได้ดีมาก

ตอนนี้ฉันต้องการรวมฟอร์มนี้จากคอนโทรลเลอร์อื่น ดังนั้นในคอนโทรลเลอร์ที่เรียกว่า 'main', (โดยเฉพาะภายในหน้าดู) 'mains / index.html.erb' ฉันรวม<%= render 'devise/sessions/form' %>ไฟล์ไว้ด้วย ดูเหมือนว่าการรวมนั้นใช้ได้ดี แต่ฉันได้รับข้อผิดพลาดต่อไปนี้

NameError in Mains#index

Showing /home/administrator/Ruby/site_v4_ruby/app/views/devise/sessions/_form.html.erb where line #1 raised:

undefined local variable or method `resource' for #<#<Class:0x007f1aa042d530>:0x007f1aa042b870>
Extracted source (around line #1):

1: <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
2:   <p><%= f.label :email %><br />
3:   <%= f.text_field :email %></p>
4: 

ดูเหมือนว่าส่วน form_for (resource, ... ) เป็นสาเหตุของปัญหา (ซึ่งทำงานได้ดีถ้าฉันอยู่ที่หน้าเดิม sign_in ประดิษฐ์ ... ฉันจะแก้ไขปัญหานี้ในลักษณะทางรถไฟได้อย่างไร?

ฉันเองชอบใช้ฟังก์ชั่น 'เรนเดอร์' เพื่อรวมฟอร์มแทนที่จะเขียนโค้ด html แบบอินไลน์

ฉันต้องระบุบางสิ่ง (ทรัพยากร) ภายในตัวควบคุม 'หลัก' หรือไม่

ฉันจะขอขอบคุณสำหรับความช่วยเหลือของคุณ ขอบคุณ.


มีวิธีแก้ปัญหา ... ตั้งแต่ พ.ย. / 16 ฉันยังไม่มีวิธีแก้ปัญหาโดยใช้การเรนเดอร์ .. แม้ว่าฉันจะพิมพ์ inline code มันก็ใช้ได้เหมือนกัน ..
user482594

คุณหาทางออกสำหรับสิ่งนี้หรือไม่?
neebz

ใช่ฉันเลือกคำตอบที่ช่วยแก้ปัญหาของฉัน มันง่ายกว่าที่ฉันคิด
user482594

คำตอบ:


241

ดังที่ Andres พูดว่าฟอร์มเรียกตัวช่วยที่ระบุโดย Devise และจะไม่ปรากฏเมื่อคุณเข้าถึงฟอร์ม Devise จากตัวควบคุมที่ไม่ใช่ Devise

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

  def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

  def devise_mapping
    @devise_mapping ||= Devise.mappings[:user]
  end

ที่มา: http://pupeno.com/blog/show-a-devise-log-in-form-in-another-page/


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

1
inherited_resourcesสิ่งที่ไม่ดีเกี่ยวกับการแก้ปัญหานี้ก็คือว่ามันแบ่ง
jrhorn424

6
หากต้องการ จำกัด ขอบเขตของวิธีการเหล่านี้ (และหลีกเลี่ยงความขัดแย้งของเนมสเปซกับอัญมณีอื่น ๆ ) ให้ลองเพิ่มวิธีการด้านบนให้กับตัวควบคุมพร้อมด้วยhelper_method :resource_name, :resource_class, :resource, :devise_mapping( :resource_classดูเหมือนว่าจะเป็นข้อกำหนดในเวอร์ชันที่ใหม่กว่า)
spume

1
วิธีการแก้ปัญหาที่ควรจะเป็นถ้าเรามีรูปแบบการประดิษฐ์ไม่กี่?
yozzz

ฉันมีสองรุ่นของ Devise และต้องลงชื่อเข้าใช้สำหรับทั้งสองในหน้าแรก ความคิดใดที่จะทำสิ่งที่คล้ายกับคำตอบของคุณ?
DR_

8

ลองสิ่งนี้ได้ด้วย ... ตรวจสอบคำถามนี้

แหล่ง

<%= form_for("user", :url => user_session_path) do |f| %>
  <%= f.text_field :email %>
  <%= f.password_field :password %>
  <%= f.check_box :remember_me %>
  <%= f.label :remember_me %>
  <%= f.submit 'Sign in' %>
  <%= link_to "Forgot your password?", new_password_path('user') %>
<% end %> 

นี่ไม่ใช่วิธีปฏิบัติที่ดีที่สุดสำหรับคำตอบทั้งหมดใช่หรือไม่
allegutta

4

แบบฟอร์มที่คุณสร้างขึ้นจะทำงานเมื่อแสดงผลจากตัวควบคุม Devise เนื่องจาก "ทรัพยากร" ถูกกำหนดผ่านทาง Devise ดูการใช้งานDevise SessionsController - จากสิ่งที่ฉันเข้าใจคุณกำลังพยายามทำซ้ำการกระทำ "ใหม่" วิธีการ "build_resource" อาจเป็นสิ่งที่คุณกำลังดูแล

คุมอัญมณีคือที่ "ทรัพยากร" วัตถุที่มาจาก หากคุณต้องการขุดลึกลงไปนั่นคือสถานที่ที่จะมองหา


ฉันเพิ่งเรียกว่า 'build_resource' ใน mains_controller แต่มันเรียกใช้ข้อผิดพลาด [ตัวแปรโลคอลหรือเมธอด `build_resource 'ที่ไม่ได้กำหนดไว้ ฉันพยายามรวมผู้ช่วยภายในด้วยการแทรก 'รวม Devise :: Controllers :: InternalHelpers' ที่ด้านบนของ 'mains_controller' แต่มันก็เรียกใช้ข้อผิดพลาดด้วย 'AbstractController :: ActionNotFound'
user482594

3

ในการปรับแต่งคำตอบที่ยอมรับเราใช้ตัวช่วยนี้เพื่ออนุญาตทรัพยากรประเภทต่างๆ:

def resource_name
  @resource_name ||= if admin_controller?
    :admin_user
  else
    :user
  end
end

def resource
  @resource ||= resource_name.to_s.classify.constantize.new
end

def devise_mapping
  @devise_mapping ||= Devise.mappings[resource_name]
end

ซึ่งadmin_controller?เป็นสิ่งที่เราได้จากมาก่อนในApplicationControllerการเปลี่ยนเส้นทางการเข้าสู่ระบบการจัดการ:

def admin_controller?
  !devise_controller? and request.path =~ /^\/admin/
end
helper_method :admin_controller?

2

ฉันได้รับข้อผิดพลาดเดียวกับที่undefined local variable or method "resource"คุณอธิบายจากหนึ่งในคอนโทรลเลอร์ของฉันเพราะคลาสพื้นฐานคอนโทรลเลอร์ของฉันไม่มีข้อมูลต่อไปนี้ (Rails-API ActionController :: API ผิดพลาด):

include ActionController::Helpers

ดังนั้นวิธีการช่วยเหลือจาก Devise จึงไม่สามารถแก้ไขได้ในมุมมอง

เพื่อให้ Devise ทำงานร่วมกับ Rails-API ได้ฉันจำเป็นต้องรวม:

class ApplicationController < ActionController::API

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