Carrierwave上传适用于Rails 4.x但不适用于Rails 5

时间:2016-03-04 22:53:09

标签: ruby-on-rails carrierwave

我已将代码编入虚拟测试网站进行验证。在使用Rails(4.2.5.1)时,此代码完全按预期工作,但在使用Rails(5.0)时失败。我不明白实际问题在哪里。

我的具体错误是Attachment article must exist,它告诉我某种方式我没有将文章实例传递给此,但我无法弄清楚为什么这样可行,就像在Rails 4.x中一样实例,但不是在Rails 5测试版中,并认为它必须是我在其他地方看不到的东西。希望有人知道。

我有一个附件模型:

class Attachment < ApplicationRecord
  belongs_to :article
  mount_uploader :file, AttachmentUploader
end

我有一个文章模型:

class Article < ApplicationRecord  
  has_many :attachments, dependent: :destroy
  accepts_nested_attributes_for :attachments, reject_if: :all_blank
end

我有文章管理员:

class ArticlesController < ApplicationController
  before_action :set_article, only: [:show, :edit, :update, :destroy]

  # GET /articles/new
  def new
    @article = Article.new
    @article.attachments.build
  end

  def create
    @article = Article.new(article_params)

     respond_to do |format|
     if @article.save
        format.html { redirect_to @article, notice: 'Article was successfully created.' }
        format.json { render :show, status: :created, location: @article }
  else
        format.html { render :new }
        format.json { render json: @article.errors, status: :unprocessable_entity }
      end
   end
  end

private
  # Use callbacks to share common setup or constraints between actions.
  def set_article
    @article = Article.find(params[:id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def article_params
    params.require(:article).permit(:name, :content, attachments_attributes: [:file, :file_cache])
   end
end

我的表格正如您所期望的那样。我的文章形式:

<%= form_for(article) do |f| %>
  <% if article.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(article.errors.count, "error") %> prohibited this    article from being saved:</h2>

  <ul>
  <% article.errors.full_messages.each do |message| %>
    <li><%= message %></li>
  <% end %>
  </ul>
  </div>
 <% end %>

<div class="field">
  <%= f.label :name %>
  <%= f.text_field :name %>
</div>

<div class="field">
  <%= f.label :content %>
  <%= f.text_area :content %>
</div>

<div id="attachments">
  <h3>Attachments</h3>
  <%= render partial: "attachments/form", locals: { f: f, index: 0 } %>
</div>

<div class="actions">
  <%= f.submit %>
</div>

<% end %>

我的附件部分:

<%= f.fields_for :attachments, child_index: index do |ff| %>
  <%= ff.file_field :file, as: :file, label: "File ##{index += 1}" %>
  <%= ff.hidden_field :file_cache %>
<% end %>

2 个答案:

答案 0 :(得分:1)

ArticlesController中,对于newcreate,您要将Article对象分配给@article变量。但在您的表单中,您使用的是article,而不是@article。看看更新变量是否能解决问题。

Article模型更新为以下内容:

class Attachment < ApplicationRecord
  belongs_to :article, optional: true
  mount_uploader :file, AttachmentUploader
end

答案 1 :(得分:0)

按照Rails 4 Way中的建议,切换到使用decent_exposure gem,这样你就可以将实例变量保留在视图之外,并从控制器中删除额外的查找操作。

https://github.com/hashrocket/decent_exposure

class ArticlesController < ApplicationController

  expose(:article, params: :article_params)
  expose(:attachment, ancestor: :article)

  def create
    if article.save
      format.html { redirect_to article, notice: 'Article was successfully created.' }
      format.json { render :show, status: :created, location: article }
    else
      format.html { render :new }
      format.json { render json: article.errors, status: :unprocessable_entity }
    end
  end

  private

  def article_params
    params.require(:article).permit(:name, :content, attachments_attributes: [:file, :file_cache])
  end
end

在此示例中,new方法被消除,因为Decent Exposure负责查找操作。