更新控制器不保存附加文件,ruby on rails

时间:2014-08-07 13:51:39

标签: ruby-on-rails ruby-on-rails-4 carrierwave

在我的应用程序中,我有一个项目,每个项目用户都可以上传许多资产。上传由载波完成。 我有两个问题:

1)有没有更好的方法来编写create方法?

2)我应该如何更改更新方法以更新附加文件

模型,project.rb

class Project < ActiveRecord::Base

    belongs_to :user
    has_many :assets
end

资产模式,asset.rb

class Asset < ActiveRecord::Base

   belongs_to :project
   belongs_to :user
   mount_uploader :attachment, AttachmentUploader #CarrierWave 


end

这是我的Create方法,可以正常使用

  def create
      @project = Project.new(project_params)
      respond_to do |format|
    if @project.save
        if params[:assets] && params[:assets]['attachment'] 
            params[:assets]['attachment'].each do |a|
                @asset = @project.assets.create!(:attachment => a, :user_id=>@project.user.id) 
                format.html { redirect_to @project, notice: 'Project was successfully created.' }
                format.json { render :show, status: :created, location: @project }
        end
        else   
            format.html { render :new }
            format.json { render json: @project.errors, status: :unprocessable_entity }
     end
    else 
        format.html { render :new }
        format.json { render json: @project.errors, status: :unprocessable_entity }
    end
end 
end


def project_params
  params.require(:project).permit(:user_id,  :summary, :start_date,assets_attributes: [:id, :project_id, :attachment,:user_id] )
end

这是Update方法

  def update
  respond_to do |format|
  if @project.update(project_params)

            format.html { render :edit }
            format.json { render json: @project.errors, status: :unprocessable_entity }

  else
    format.html { render :edit }
    format.json { render json: @project.errors, status: :unprocessable_entity }
  end
end

1 个答案:

答案 0 :(得分:0)

您可以使用活动记录中内置的accepts_nested_attributes_for方法轻松处理创建,更新和销毁嵌套模型

http://railscasts.com/episodes/196-nested-model-form-revised?view=asciicast

编辑问题变更

您似乎对原始问题进行了多次修改,让我看看能否为您解决一些问题。

假设您的资产类有一个名为attachment的列,并且您有一个名为AttachmentUploader的carrierwave上传程序类。然后,您可以像在问题中显示的那样将该类安装到资产类

 mount_uploader :attachment, AttachmentUploader #CarrierWave 

您没有在问题中显示表单标记,但根据您的控制器的project_params方法,您似乎期待一个名为asset_attributes的属性。您将要确保表单正确构建该数组,最容易通过使用fields_for帮助程序来完成。如果您对该部分感到困惑,请参阅此问题Rails 4 Nested Attributes Unpermitted Parameters

基本上它看起来应该是这样的

项目/ _form.html.erb

<%= form_for @project, :html => {:multipart => true} do |f| %>
  <%= f.error_messages %>

  <%= f.fields_for :assets do |builder| %>
     <%= render 'assets_fields', :f => builder %>
  <% end %>
  <p><%= f.submit %></p>
<% end %>

项目/ _assets_fields.html.erb

<p>
   <%= f.file_field :attachment %>
</p>

提交项目表单时,您不需要手动循环资产,确定它们是否是正在更新的现有资产,正在创建的新资产或标记为删除的资产。通过将此逻辑添加到项目类

,可以为您处理该逻辑
accepts_nested_attributes_for :assets, :allow_destroy => true

只需致电

project.save 

project.update

将自动创建/更新/销毁在事务中包装整个进程的嵌套资产,以便它们都成功或全部失败。唯一的做法就是活动记录不能在数据库事务中包装载波动作,因此您最终可能会在服务器上上传孤立的文件。