我遇到了这个问题,控制器的“ new”(有时是“ edit”)动作会引发:
First argument in form cannot contain nil or be empty
虽然我100%确信第一个参数不是nil也不为空。要磨练这一点,我只会询问“新”操作,因为资源只是设置为Resource.new
permissions / new.haml
= form_for @permission do |f|
= f.label :name, class: 'form-control-label'
= f.text_field :name, class: 'form-control'
permissions_controller.rb
class PermissionsController < ApplicationController
before_action :set_permission, only: [:show, :edit, :update, :destroy]
def new
@permission = Permission.new
end
def show
@modules = Modules.all
end
def index
// handling content with api calls instead
end
...
end
这个问题我已经有很长时间了,但是直到现在我还没有想到要在我的开发环境中成功地重现它。
我可以通过以下步骤来重现此问题:转到同一控制器的“显示”操作,然后回到“索引”操作,再转到“新”操作。此时,在我编辑控制器文件或重新启动服务器之前,“新”页面不再起作用。
更换控制器(在末尾添加一个空格)或重新启动服务器后,它突然又可以工作了。
这不是发生这种情况的唯一资源。通常,其他资源(如用户)也有相同的问题。我有多个项目都遇到了同样的问题,而这个问题却以某种方式消失了,所以我再也没有为这个做更多的工作。
Ruby版本:2.3.5p376
轨道版本:5.1.4
编辑:
我注意到,如果我注释掉Modules.all
,我将无法再复制它。
模块不是activerecord类,它是帮助程序类,可以读取目录中的不同文件,这种读取是否会带来问题?
modules.rb
class Modules
def self.all
controllers = Dir.glob("#{Rails.root}/app/controllers/**/*.rb").
map{ |e|
if e.include?('/api/')
e.match(/api\/[^\/]*\/[^\/]*.rb/)[0].gsub('.rb', '').gsub('/', '::_').camelcase
else
e.match(/[^\/]*.rb/)[0].gsub('.rb', '').camelcase
end
}
modules = {}
controllers.each do |e|
c = Object.const_get e
modules[e.gsub(':','').gsub('Controller', '').underscore] = get_actions_for c if
!no_permission_needed_for e and c.action_methods.size > 0
end
return modules
end
def self.get_actions_for(controller)
actions = controller.action_methods
grouped_actions.each do |key, value|
actions.delete(key)
end
return actions
end
def self.grouped_actions
{"new" => "create", "edit" => "update"}
end
end
编辑:
我注意到的是,我正在尝试调用actions.delete(key)
,其中action是字符串的Set
,其中key
是String
当我执行actions = controller.action_methods.to_a
并将集合强制设置为数组时,我的问题似乎消失了。至少我不能再复制了。现在,我想知道在ruby中是否存在根本上出错的地方,即从Set
中删除某些内容实际上是很奇怪的事情。
答案 0 :(得分:0)
一种可行但不推荐的方法是在表单内初始化Permission
实例:
<%= form_for Permission.new do |f| %>
检查包含您表单的视图是否实际上是通过new
的{{1}}操作呈现的。
答案 1 :(得分:0)
我想我已经弄清楚了。
我注意到的是,在modules.rb
中,我正在通过controller.action_methods
加载控制器内部的动作。之后,我要删除new
和edit
操作。
我以为我只是在接收一组包含动作名称而不是实际动作的字符串。因此,如果删除new
和edit
操作似乎是合乎逻辑的,那么我的视图将默认为ActionController :: Base中的new
和edit
操作。这将意味着未设置@permission,并且视图会引发应有的错误。
我假设这样做会在运行时删除控制器的这些动作。这意味着它在我重启服务器后当然会再次工作。
因此,我通过执行controller.action_methods.to_a
来解决我的问题,该问题强制将控制器中的实际动作解耦。之后,我可以随意删除该数组中不需要的字符串。
故事的寓意:请注意controller.action_methods
?