我遇到了一个奇怪的问题,经过一系列的研究无法接近。我有几种通过Carrierwave上传文件的表单。当我上传信息时,部分路线被切断(我认为)。
例如,我有一个多部分表单提交到:
https:/ domain / programs / 223 / add_file as POST
但在提交时我收到错误
没有路线匹配[POST]“/ 223 / add_file”
即使我的地址栏中的内容是完整的路线。如果将完整路线作为GET请求提交,则可以正常工作。当我运行rake路线时,路线显示就好了。
以下是我路线的一部分:
resources :programs do
match "add_file" => "programs#add_file"
如果重要的话,我在Apache上使用Passenger运行Rails 3.2.2。问题只发生在这个生产服务器上,从不在开发中。
有什么想法吗?我坚持这个,因为它影响多个路线,我已经尝试为那个形式定义一个没有运气的自定义路线。
更新 当我删除多部分=> true或表单中的file_field_tag修复了问题。它仍然是一个问题,但似乎不是关于路由而是关于文件上传的表单。
答案 0 :(得分:6)
使用以下代码在passenger_extension.rb
文件夹中创建lib
:
乘客3
module PhusionPassenger
module Utils
protected
NULL = "\0".freeze
def split_by_null_into_hash(data)
args = data.split(NULL, -1)
args.pop
headers_hash = Hash.new
args.each_slice(2).to_a.each do |pair|
headers_hash[pair.first] = pair.last unless headers_hash.keys.include? pair.first
end
return headers_hash
end
end
end
乘客5
module PhusionPassenger
module Utils
# Utility functions that can potentially be accelerated by native_support functions.
module NativeSupportUtils
extend self
NULL = "\0".freeze
class ProcessTimes < Struct.new(:utime, :stime)
end
def split_by_null_into_hash(data)
args = data.split(NULL, -1)
args.pop
headers_hash = Hash.new
args.each_slice(2).to_a.each do |pair|
headers_hash[pair.first] = pair.last unless headers_hash.keys.include? pair.first
end
return headers_hash
end
def process_times
times = Process.times
return ProcessTimes.new((times.utime * 1_000_000).to_i,
(times.stime * 1_000_000).to_i)
end
end
end # module Utils
end # module PhusionPassenger
然后在'config / application.rb'中执行:
class Application < Rails::Application
...
config.autoload_paths += %W(#{config.root}/lib)
require 'passenger_extension'
end
然后重新启动网络服务器。
注意:我不确定这是否会破坏任何其他功能,因此请自行承担风险,如果您发现此方法有任何损害,请与我们联系。
答案 1 :(得分:0)
这里的一个问题是您没有指定路由是在集合上还是在成员上定义的。哪一个是正确的路线?
programs/:id/add_file
programs/add_file
你应该像这样构建你的路线:
resources :programs do
post 'add_file', :on => :member
end
或
resources :programs do
member do
post 'add_file'
end
end
上述内容将在programs/:id/add_file
上发布请求,并将ProgramsController.add_file
作为程序ID发送给params[:id]
。
如果你想在集合中使用它,你可以这样做:
resources :programs do
post 'add_file', :on => :collection
end
或
resources :programs do
collection do
post 'add_file'
end
end
这会在programs/add_file
上发布请求并将其发送到ProgramsController.add_file
,但不会设置params[:id]
。
一般情况下,您应始终指定路线是否在集合或成员上,并且您应指定路线应接受的动词(即使用'get'或'post'等而不是'match')。
尝试以上操作,看看是否能解决您的问题,如果没有,请告诉我,我会再看看。
答案 2 :(得分:0)
我认为您可能需要添加
:via => [:post]
到你的路线规范。看起来它很适合开发而不是生产,但是当我理解rails路由时,你添加的匹配器只会响应get。
尝试将您的匹配更改为
match "add_file" => "programs#add_file", :via => [:post]
另外,根据Andrew刚刚提交的答案,您最好使用成员说明符明确表示操作是在具有特定ID的特定程序上发生的,而不是集合。它还应该在你的add_file方法中保存一些代码,这可能很难从url获取id参数。