给定代码(在routes.rb中):
resources :products do
member do
get :delete #this works
delete delete: "products#destroy" #this doesn't work
delete "delete" => "products#destroy" #but this works
end
end
为什么行delete delete: "products#destroy"
不工作而行delete "delete" => "products#destroy"
工作?
Rails版本3.2.11
如果你想将删除操作映射到销毁,你应该使用match
match 'products/:id/delete', controller: :products, action: :destroy, via: :delete
但是我看不出这样做的理由。在我看来,你应该坚持使用rails默认的destroy动作。
它不起作用因为在资源中你已经指定了控制器它用于使用适当的http协议添加动作
如果您遵循错误回溯,那么这不起作用的原因是因为Rails中的mapper.rb
中的以下行。
def match(path, *rest)
if rest.empty? && Hash === path
options = path
path, to = options.find { |name, value| name.is_a?(String) }
options[:to] = to
options.delete(path)
paths = [path]
else
options = rest.pop || {}
paths = [path] + rest
end
options[:anchor] = true unless options.key?(:anchor)
if options[:on] && !VALID_ON_OPTIONS.include?(options[:on])
raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
end
paths.each { |_path| decomposed_match(_path, options.dup) }
self
end
这是由幕后的所有方法调用(例如delete
, post
, get
, put
)。我们特别要找的行是这样的:
path, to = options.find { |name, value| name.is_a?(String) }
不确定他们为什么要检查字符串,但因为名称是一个符号,而不是String
,而是Symbol
。这几乎将路径作为nil值发送到decomposed_match
,从而导致不能在路由中使用符号的原因。
注意
resources :products do
member do
get :delete #this works
delete delete: "products#destroy" #this doesn't work
delete "delete" => "products#destroy" #but this works
end
end
get :delete
工作的原因是match
方法被调用之前的行。
特别是在这个方法下
def map_method(method, *args, &block)
options = args.extract_options!
options[:via] = method
args.push(options)
match(*args, &block)
self
end
args.extract_options!
行从数组中删除一个哈希值。您可以在extract_options.rb
文件下找到它,这是Array
类的一个添加方法。
无论如何,由于get :delete
不是散列,而是一个参数,因此它被映射为如下内容
Path: [delete]
Options [{via: "get"}]
现在,其他的像这样被映射以delete delete: "product#destroy"
Path {:delete=>"collaborators#destroy", via: "delete"}
Options []
然后回到我最初的陈述,为什么符号不能在路由中工作
新的散列语法仅在Ruby 1.9版本中得到支持。您使用的是哪个版本的Ruby ?