Menyusun formulir dalam pengontrol yang berbeda

129

Saya menggunakan permata alat untuk prosedur sign_in / sign_out.

Saya menghasilkan file tampilan dari merancang, menggunakan rails g devise views

Saya melihat ada file merancang / sesi / new.html.erb yang berisi formulir untuk sign_in.

Saya membuat file lain merancang / sesi / _form.html.erb dan melakukannya <%= render 'form' %>dalam file new.html.erb, dan itu bekerja dengan sangat baik.

Sekarang, saya ingin memasukkan formulir ini dari pengontrol yang berbeda. Jadi dalam sebuah pengontrol yang disebut 'main', (khususnya, dalam halaman tampilan) 'mains / index.html.erb' saya memasukkan <%= render 'devise/sessions/form' %>file. Tampaknya inklusi berfungsi dengan baik, tetapi saya mendapatkan kesalahan berikut.

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: 

Tampaknya bagian form_for (sumber daya, ...) menyebabkan masalah (yang berfungsi dengan baik jika saya berada di halaman sign_in merancang yang asli ... Bagaimana saya bisa menyelesaikan masalah ini dengan cara rails?

Saya pribadi lebih suka menggunakan fungsi 'render' untuk memasukkan formulir, daripada menulis kode html sebaris.

Apakah saya harus menentukan sesuatu (sumber daya) di dalam pengontrol 'utama'?

Aku akan mengapresiasi bantuan mu. Terima kasih.

pengguna482594
sumber
Apakah ada solusi ...? Pada Nov / 16 saya belum benar-benar mendapatkan solusi menggunakan render .. walaupun jika saya cukup mengetikkan inline code, sepertinya berfungsi dengan baik ..
user482594
apakah Anda menemukan solusi untuk ini?
neebz
Ya, saya memilih jawaban yang menyelesaikan masalah saya. Itu lebih sederhana daripada yang saya pikirkan.
user482594

Jawaban:

241

Seperti yang dikatakan Andres, formulir tersebut memanggil bantuan yang ditentukan oleh Rancangan dan jadi tidak ada saat Anda mengakses formulir Rancangan dari pengontrol yang bukan Rancangan.

Untuk menyiasatinya, Anda perlu menambahkan metode berikut ini ke kelas helper controller yang ingin Anda tampilkan formulir di bawah. Atau, Anda bisa menambahkannya ke pembantu aplikasi Anda untuk membuatnya tersedia di mana saja.

  def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

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

Sumber: http://pupeno.com/blog/show-a-devise-log-in-form-in-another-page/

Rupert Madden-Abbott
sumber
6
Luar biasa. Pastikan itu masuk dalam helper, bukan di controller. Juga, ini dapat menyebabkan masalah besar jika Anda memiliki sumber daya lain (misalnya perusahaan yang juga dapat masuk) dan Anda ingin memuat formulir mereka. Pastikan untuk mendefinisikan ulang nama, dan perutean mungkin menjadi masalah juga.
Michael Schmitz
1
Hal buruk tentang solusi ini adalah ia rusak inherited_resources.
jrhorn424
6
Untuk membatasi ruang lingkup metode ini (dan menghindari konflik namespace dengan permata lain, misalnya), coba tambahkan metode di atas ke controller itu sendiri, bersama dengan helper_method :resource_name, :resource_class, :resource, :devise_mapping(yang :resource_classtampaknya menjadi persyaratan dalam versi Rancangan yang lebih baru).
Membuang
1
Solusi apa yang seharusnya jika kita memiliki beberapa model yang dirancang?
yozzz
Saya memiliki dua model Rancangan dan perlu masuk untuk keduanya di beranda. Adakah yang tahu bagaimana melakukan sesuatu yang mirip dengan jawaban Anda?
DR_
8

Dapat mencoba ini juga ... periksa pertanyaan ini .

Sumber

<%= 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 %> 
jsp
sumber
Bukankah ini praktik terbaik dari semua jawaban?
allegutta
4

Formulir yang Anda buat berfungsi saat ditampilkan dari pengontrol Devise karena "sumber" didefinisikan melalui Devise. Lihatlah implementasi dari Rancangan SessionsController - dari apa yang saya mengerti, Anda mencoba meniru tindakan "baru". Metode "build_resource" mungkin adalah yang Anda cari.

The Warden permata adalah di mana "sumber daya" benda berasal. Jika Anda ingin menggali lebih dalam, itu akan menjadi tempat untuk mencari.

Andres Freyria
sumber
Saya baru saja memanggil 'build_resource' dengan mains_controller, tetapi ia memanggil kesalahan [variabel lokal atau metode `build_resource '] yang tidak terdefinisi. Saya mencoba memasukkan alat bantu internal dengan memasukkan 'sertakan alat bantu Devise :: Controllers :: InternalHelpers' di bagian atas 'mains_controller' tetapi ia juga memanggil kesalahan dengan 'AbstractController :: ActionNotFound'
user482594
3

Untuk memperbaiki jawaban yang diterima, kami menggunakan penolong ini untuk memungkinkan berbagai jenis sumber daya:

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

di mana admin_controller?ada sesuatu yang kita miliki sebelumnya ApplicationControlleruntuk menangani pengalihan login:

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

Saya mendapatkan kesalahan yang sama dengan yang undefined local variable or method "resource"Anda gambarkan dari salah satu pengontrol saya, karena kelas dasar pengontrol saya kehilangan yang berikut ini (Rails-API ActionController :: API salah):

include ActionController::Helpers

Dengan demikian metode pembantu dari Rancangan tidak bisa diselesaikan dalam pandangan.

Untuk membuat Rancangan bekerja dengan Rails-API saya perlu menyertakan:

class ApplicationController < ActionController::API

  include AbstractController::Rendering
  include AbstractController::Layouts
  include ActionController::MimeResponds
  include AbstractController::Translation
  include ActionController::ImplicitRender
  include ActionController::Helpers
Christopher Oezbek
sumber