Разработайте форму в другом контроллере

129

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

Я создал файлы представлений из devise, используя rails g devise views

Я видел, что есть файл devise / sessions / new.html.erb, который содержит форму для sign_in.

Я создал еще один файл devise / sessions / _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-коды.

Нужно ли мне указывать что-то (ресурс) в «основном» контроллере?

Буду признателен за вашу помощь. Спасибо.

user482594
источник
Есть какое-нибудь решение ...? По состоянию на 16 ноября у меня действительно нет решения, использующего рендеринг ... хотя, если я просто
наберу
вы нашли решение для этого?
neebz
Да, я выбрал ответ, который решает мою проблему. Это было проще, чем я думал.
user482594

Ответы:

242

Как говорит Андрес, форма вызывает помощников, которые указаны в 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 02
6
Чтобы ограничить область действия этих методов (и избежать конфликта пространства имен с другими драгоценными камнями, например), попробуйте добавить указанные выше методы в сам контроллер вместе с helper_method :resource_name, :resource_class, :resource, :devise_mapping( :resource_classкажется, это требование в новых версиях Devise).
spume 03
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 %> 
JSP
источник
Разве это не лучшая практика из всех ответов?
allegutta
4

Созданная вами форма работает при визуализации из контроллера Devise, потому что «ресурс» определяется через Devise. Взгляните на реализацию Devise SessionsController - насколько я понимаю, вы пытаетесь воспроизвести «новое» действие. Возможно, вам нужен метод build_resource.

Warden самоцвет где «ресурс» объекты как . Если вы хотите копнуть глубже, вам стоит поискать это место.

Андрес Фрейрия
источник
Я только что вызвал build_resource в mains_controller, но он вызывает ошибку [неопределенная локальная переменная или метод build_resource]. Я попытался включить внутренний помощник разработки, вставив «include 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?
bbozo
источник
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
Кристофер Озбек
источник