在不同的控制器中使用Devise:未定义的方法“resource =”

时间:2017-04-05 04:21:38

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

我有Devise 4.2.1和Rails 5.0.1。我正在尝试在sign_in以外的控制器中使用Devise registrations。有许多方法没有定义,所以我不得不将它们添加为帮助者:

module ApplicationHelper
  def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

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

  def build_resource(hash=nil)
    self.resource = resource_class.new_with_session(hash || {}, session)
    # ^the source of the error^
  end

  def resource_class
    devise_mapping.to
  end
end

但现在我收到以下错误:

NoMethodError in Static#show
undefined method 'resource=' for (class)

我没有在我的代码中的任何地方写入“resource =”,当然也没有错误指向的行(上面标记)。 我的服务器从哪里获得该错误?

另外,我想我只是使用标准的sign_in代码:

<%
build_resource({})
set_minimum_password_length
yield resource if block_given?
respond_with self.resource
%>

<% form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>
  ...

1 个答案:

答案 0 :(得分:1)

我相信您的问题有2个答案:为什么会出现此错误,以及如何在所有控制器上使用sign_in部分错误:

创建sign_in部分

首先,sign_in方法属于sessions,而非registrations小心不要更换错误的控制器:)

您刚刚添加了一些代码,而不是您想要的代码。要创建部分sign_in以便在任何地方使用,只需使用默认的Devise表单:

<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <%= f.label :email %><br />
  <%= f.email_field :email, autofocus: true %>

  <%= f.label :password %><br />
  <%= f.password_field :password, autocomplete: "off" %>

  <% if devise_mapping.rememberable? -%>
    <%= f.check_box :remember_me %>
    <%= f.label :remember_me %>
  <% end -%>

  <%= f.submit "Log in" %>
<% end %>

不需要build_resource({})部分,因为当您提交表单时,Devise会自行处理。{由于不需要build_resource,因此您只需在ApplicationHelper上使用以下代码:

module ApplicationHelper
  def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

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

这应该足以在任何控制器视图中都有sign_in表单。如果您需要更多地控制登录流程,可以查看Devise Readme上的配置控制器部分,以获取有关如何创建可自定义控制器的更多信息。

为什么您的代码会抛出NoMethodError错误

您的代码抛出NoMethodError,因为您还没有为@resource实例变量定义一个setter。应该是:

def resource=(value)
  @resource = value
end

attr_writer :resource

我推荐这个问题以获取有关该主题的更多信息: Why use Ruby's attr_accessor, attr_reader and attr_writer?