Розробіть форму в іншому контролері


129

Я використовую розроблювальний камінь для процедур sign_in / sign_out.

Я генерував файли переглядів із програми, використовуючи rails g devise views

Я побачив, що був файл devise / session / new.html.erb, який містив форму для sign_in.

Я створив ще один файл devise / 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 (ресурс, ...) викликає проблему (яка працює добре, якщо я перебуваю на оригінальній сторінці розробки sign_in ... Як я можу вирішити цю проблему рейками?

Я особисто вважаю за краще використовувати функцію "візуалізації" для включення форми, а не для написання HTML-кодів inline.

Чи потрібно вказувати щось (ресурс) у "головному" контролері?

Я буду вдячний за вашу допомогу. Дякую.


Чи є рішення ...? Станом на ноябрь / 16 Я на насправді не отримали рішення з допомогою візуалізації .. хоча , якщо я просто наберіть в вбудованому коді, це працює відмінно, здається , ..
user482594

ти знайшов рішення для цього?
neebz

Так, я вибрав відповідь, яка вирішує мою проблему. Це було простіше, ніж я думав.
user482594

Відповіді:


241

Як каже Андрес, форма закликає помічників, які вказані 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
Відмінно. Переконайтеся, що це йде в помічнику, а не в контролері. Також це може призвести до величезних проблем, якщо у вас є інші ресурси (наприклад, компанії, які також можуть увійти) і ви хочете завантажити їх форму. Переконайтесь, що перегляньте назви, і маршрутизація також може стати проблемою.
Майкл Шміц

1
Поганим у цьому рішенні є те, що він ламається inherited_resources.
jrhorn424

6
Щоб обмежити сферу застосування цих методів (і уникнути конфлікту простору імен з іншими дорогоцінними каменями, наприклад), спробуйте додати вищевказані методи до самого контролера разом із helper_method :resource_name, :resource_class, :resource, :devise_mapping( :resource_classмабуть, це є вимогою у новіших версіях Devise).
спайм

1
Яке рішення має бути, якщо у нас мало придуманих моделей?
йозз

У мене є дві моделі 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" - це, мабуть, те, про що ви доглядаєте.

Warden самоцвіт де «ресурс» об'єкти як . Якщо ви хочете копати глибше, це було б місце, де варто подивитися.


Я щойно закликав "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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.