覆盖 Devise 控制器的问题

发布于 2024-12-27 20:54:46 字数 1708 浏览 4 评论 0原文

我正在尝试覆盖 Devise 控制器以进行一些细微的更改,例如在请求未注册电子邮件地址的确认电子邮件时添加一条闪存消息。

我尝试覆盖 Devise::ConfirmationsController1这样:

# app/controllers/confirmations_controller.rb
class ConfirmationsController < Devise::ConfirmationsController

  include Devise::Controllers::InternalHelpers # tried to add this, no success

  def create
    self.resource = resource_class.send_confirmation_instructions(params[resource_name])

    if successfully_sent?(resource)
      respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
    else
      respond_with(resource)
    end
  end

end

我想我添加了路线正确:

devise_for :users, :controllers => { :confirmations => "confirmations" }

我的控制器方法被调用,但是它引发了此异常:

NoMethodError in ConfirmationsController#create

undefined method `successfully_sent?' for #<ConfirmationsController:0x007fa49e229030>

在我重写的控制器中,我刚刚复制了 Devise::ConfirmationsController#create 的代码,它本身调用 successively_sent?(resource)

successively_sent? 方法在 InternalHelpers 中定义 2,这就是我尝试添加 include Devise::Controllers::InternalHelpers

这不是我第一次尝试覆盖 Devise 控制器,这不是我第一次失败。我总是设法找到解决方法,但我想了解我缺少什么......提前感谢您的帮助!

[编辑] Devise 版本为 1.4.9 Rails 是 3.0.10

I'm trying to override a Devise controller to have some minor changes, for example adding a flash message when requesting a confirmation email for an unregistered email address.

I tried to override Devise::ConfirmationsController1 this way:

# app/controllers/confirmations_controller.rb
class ConfirmationsController < Devise::ConfirmationsController

  include Devise::Controllers::InternalHelpers # tried to add this, no success

  def create
    self.resource = resource_class.send_confirmation_instructions(params[resource_name])

    if successfully_sent?(resource)
      respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
    else
      respond_with(resource)
    end
  end

end

I think I added the route correctly:

devise_for :users, :controllers => { :confirmations => "confirmations" }

My controller method gets called, however it raises this exception:

NoMethodError in ConfirmationsController#create

undefined method `successfully_sent?' for #<ConfirmationsController:0x007fa49e229030>

In my overridden controller, I just copied the code of Devise:: ConfirmationsController#create, which itself calls successfully_sent?(resource)

The successfully_sent? method is defined in InternalHelpers 2, this is why I tried to add include Devise::Controllers::InternalHelpers

This is not the first time I try to override a Devise controller, and this is not the first time I fail. I always managed to get a workaround, but I'd like to understand what I'm missing... Thanks in advance for your help!

[EDIT]
Devise is in version 1.4.9
Rails is 3.0.10

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光瘦了 2025-01-03 20:54:46

好吧,感谢凯尔在我的问题评论中的帮助,我将为这个初学者的错误写出正确的答案。

我没有查看我自己的 Devise 版本来覆盖控制器,而是只是查看 Devise 的 Github 存储库。由于我尝试覆盖的控制器在我的版本和最后提交的版本之间发生了更改,因此我尝试使用的帮助器方法根本没有在我的版本中定义...

正如凯尔所指出的,您可以使用 < code>bundle open devise 查看您实际使用的 gem 的代码,或者您可以使用 gem list devise 查看其版本号,并在Github(对于 Devise,他们为每个版本设置了标签这样您就可以通过选择相应的标签来浏览1.4.9版本的代码)。

这样做,我会使用以下代码覆盖控制器的 create 方法:

def create
  self.resource = resource_class.send_confirmation_instructions(params[resource_name])

  if successful_and_sane?(resource)
    set_flash_message(:notice, :send_instructions) if is_navigational_format?
    respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
  else
    respond_with_navigational(resource){ render_with_scope :new }
  end
end

使用 successful_and_sane? 而不是 successively_sent? ...

它 总结这个答案,可能有一种更好的方法来向此方法添加闪现消息,而不是覆盖它。 jarrad 建议使用 around_filter,但我还无法让它工作,而且我不确定在从过滤器方法中生成渲染视图后是否仍然可以更改渲染视图...欢迎评论!

Well, thanks to the help of Kyle in my question's comments, I will write the correct answer to this beginner's mistake.

Instead of looking at my own version of Devise to override the controller, I was simply looking at Devise's Github repository. Since the controller I was trying to override had changes between my version and the last committed one, the helper method I was trying to use was simply not defined in my version...

As indicated by Kyle, you can use bundle open devise to look at the code of the gem you're actually using, or you can look at its version number with gem list devise and find the code for this release on Github (for Devise they set the tags for each release so that you can browse the code for release 1.4.9 by selecting the corresponding tag).

Doing this, I would have overrode my controller's create method with the following code instead:

def create
  self.resource = resource_class.send_confirmation_instructions(params[resource_name])

  if successful_and_sane?(resource)
    set_flash_message(:notice, :send_instructions) if is_navigational_format?
    respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
  else
    respond_with_navigational(resource){ render_with_scope :new }
  end
end

which uses successful_and_sane? and not successfully_sent? ...

To conclude this answer, there may be a better way of adding a flash message to this method than overriding it. jarrad is advising to use around_filter, but I can't get it to work yet and I'm unsure I can still change the rendered view after I yielded it from the filter method... Comments welcomed!

伪装你 2025-01-03 20:54:46

这可能无法帮助您理解为什么重写 Devise 控制器失败,但它会使您的代码保持干燥,因为您不需要从 Devise::ConfirmationsController#crete 复制代码

所以,如果您只是想要设置 Flash 消息,请查看 过滤器ActionControllers

具体来说,看看周围过滤器:

class ConfirmationsController < Devise::ConfirmationsController
  around_filter :my_custom_stuff, :only => :create

  private

  def my_custom_stuff
    # do your thing here...
  end
end

This may not help you understand why overriding the Devise controller is failing, but it will keep your code DRY in that you do not need to copy the code from Devise::ConfirmationsController#crete

So, if you just want to set a flash message, look at Filters for ActionControllers

Specifically, look at the Around Filter:

class ConfirmationsController < Devise::ConfirmationsController
  around_filter :my_custom_stuff, :only => :create

  private

  def my_custom_stuff
    # do your thing here...
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文