我正在尝试创建一个上传表单,允许用户选择一个空白值,然后导致另一个上传过程。 (我在“课堂”中替换了我的实际班级名称)。
我的上传表单是
<%= form_for @upload, :url => class_uploads_path(@uploader), :method =>
:post, :html =>{ :multipart => true } do |f| %>
<%= render "shared/error_messages", :target => @upload %>
<p>This media relates to...<br/>
<%= select "upload", "class_id", Class.all.collect {|class| [class.name,class.id] }, {
:include_blank => true } %></p>
<p>Title:<br/>
<%= f.text_field :title %></p>
<p>Description:<br/>
<%= f.text_area :description, :rows => 3 %></p>
<p>File to upload:<br/>
<%= f.file_field :data %></p>
<p><%= f.submit 'Upload for review' %></p>
<% end %>
这是我的创建方法,如果用户将选择表单留空,我希望首先运行上传操作,如果他们选择了一个类,我希望第二次上传运行。
def create
upload_params = params[:upload] || params[:image] || params[:video]
@class = Class.find(upload_params[:class_id]) || nil
begin
if upload_params[:data]
file_name = upload_params[:data].original_filename
file_contents = upload_params[:data].read
end
rescue
@upload = Upload.new
flash[:error] = "Could not find upload file data. Please reselect file."
render :action => 'new' and return
end
begin
if @class.nil?
@upload = Upload.factory({ :file => file_contents,
:name => file_name,
:network => @uploader,
:title => upload_params[:title],
:description => upload_params[:description] })
else
@upload = Upload.factory({ :file => file_contents,
:name => file_name,
:class => @class,
:network => @uploader,
:title => upload_params[:title],
:description => upload_params[:description] })
end
@upload.save!
我尝试了很多不同的黑客攻击,我试图避免在数据库中添加新列。提前谢谢。
答案 0 :(得分:1)
Kyle,如果选择了空白选项,我相信params [:class_id]应为“”(空白字符串)。您应该检查一下 - 查看开发日志,看看哪些参数被传递回控制器方法,无论是选择课程还是不选择。
如果这是正确的:
class_id = params[:class_id]
@class = Class.find(class_id.to_i) if class_id and not class_id.empty?
正如gg_s指出的那样,重构你发布的代码有很大的空间。但是,如果您只想让现有代码正常工作,这可能会有所帮助。
将来,当某些东西不起作用时,而不仅仅是“在它工作之前进行攻击”,请查看日志/控制台输出以获取更多信息。将日志记录语句添加到控制器方法,打印出变量值等。然后尝试一下,再次查看日志以查看方法内部发生的情况。
答案 1 :(得分:0)
如果两个上传之间的唯一区别是:class => @class
对,则没有理由进行两项单独的操作。
我假设以下内容:
Upload
个对象(upload.rb
模型,uploads_controller.rb
控制器)Upload.factory
是一种处理方法,用于处理和格式化上传数据,从而生成包含文件和元数据的完整Upload
对象。如果是这样,所有控制器逻辑都可以移动到模型中。使用实例变量(通过attr_accessor
,而不是通过添加列)将数据传递给模型。在before_create
上按下factory
过滤器,以便在保存之前处理您的上传。
使用验证来处理“无数据”错误。
这是一个例子。 upload.rb
:
before_create :factory # run your factory method before creating
attr_accessor :form_data, :form_network, :form_title, \ # settable from controller
:form_description, :form_class_id
validates :form_data, :presence => true, :on => :create, \ # fail if no data
:message => "No file data. Please reselect file."
private
def factory
file_name = self.form_data.original_filename
file_contents = self.form_data.read
class = Class.where(:id => self.form_class_id).first # returns Class or nil
# if class is nil, handle it however you need to here
# access self.form_network, self.form_title, self.form_description directly
# ... factory magic ...
end
现在你的控制器可以像这样整洁:
def create
upload_params = params[:upload] || params[:image] || params[:video]
@upload = Upload.new({ :form_data => upload_params[:data],
:form_network => @uploader, # <-- undefined!
:form_class_id => upload_params[:class_id],
:form_title => upload_params[:title],
:form_description => upload_params[:description]})
if @upload.save
redirect_to @upload
else
render :action => "new"
end
end
请注意@uploader
未定义。
@upload.save
将验证@upload
。如果文件数据不存在,save
将失败,使用“无数据”错误消息将您踢回new
操作。否则,如果验证通过,则调用factory
,然后记录保存。