Rails选择具有两个选项的表单

时间:2012-01-29 00:40:20

标签: ruby-on-rails ruby ruby-on-rails-3

我正在尝试创建一个上传表单,允许用户选择一个空白值,然后导致另一个上传过程。 (我在“课堂”中替换了我的实际班级名称)

我的上传表单是

<%= 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!

我尝试了很多不同的黑客攻击,我试图避免在数据库中添加新列。提前谢谢。

2 个答案:

答案 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,然后记录保存。