在不同的控制器中设计表单

时间:2010-11-02 20:18:34

标签: ruby-on-rails ruby-on-rails-3 devise

我正在为sign_in / sign_out程序使用设计宝石。

我使用rails g devise views

从设计生成了视图文件

我看到有一个devise / sessions / new.html.erb文件,其中包含sign_in的表单。

我在new.html.erb文件中创建了另一个文件devise / sessions / _form.html.erb并执行了<%= render 'form' %>,这非常合适。

现在,我想从不同的控制器中包含此表单。因此,在一个名为“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页面上工作正常......如何以rails方式解决此问题?

我个人更喜欢使用'render'函数来包含表单,而不是内联编写html代码。

我是否必须在'main'控制器中指定某些内容(资源)?

感谢您的帮助。谢谢。

5 个答案:

答案 0 :(得分:230)

正如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/

答案 1 :(得分:8)

也可以尝试这个...查看question

Source

<%= 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 %> 

答案 2 :(得分:4)

您创建的表单在从Devise控制器渲染时起作用,因为“资源”是通过Devise定义的。看一下Devise SessionsController的实现 - 从我的理解,你试图复制“新”动作。 “build_resource”方法可能就是您正在寻找的方法。

Warden gem是“资源”对象的来源。如果你想深入挖掘,那就是值得一看的地方。

答案 3 :(得分: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?

答案 4 :(得分: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