【问题标题】:Empty child record gets created after creating Parent record (Rails 4)创建父记录后创建空子记录(Rails 4)
【发布时间】:2014-07-24 19:11:18
【问题描述】:

我有一个名为 Images 的模型,并附有一个上传器 (Carrierwave)。图片属于一个名为Listing的模型。创建列表后,我被重定向到图像索引页面以上传文件 (localhost:3000/listings/1/images)

但由于某种原因,每次我创建一个列表时,它都会同时创建一个图像。实际上没有图像,但它显示了我对每张图像的“删除”链接。

<span><%= link_to 'DELETE', listing_image_path(@listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>

有什么帮助吗?谢谢。

列表控制器

class ListingsController < ApplicationController
   before_action :set_listing, only: [:show, :edit, :update, :destroy]
   before_filter :authenticate_user!, :except => [:show, :index]

   def index
      @listings = Listing.order('created_at DESC')

      respond_to do |format|
         format.html
         format.json { render json: @listings }
      end
   end

   def show
   end

   def new
      @listing = Listing.new
      @listing.user = current_user
   end

   def edit
   end

   def create
      @listing = Listing.new(listing_params)
      @listing.user = current_user

      respond_to do |format|
         if @listing.save
            format.html { redirect_to listing_images_path(@listing), notice: 'Post was successfully created.' }
         else
            format.html { render action: 'new' }
            format.json { render json: @listing.errors, status: :unprocessable_entity }
         end
      end
   end

   def update
      respond_to do |format|
         if @listing.update(listing_params)
            flash[:notice] = 'Deal was successfully updated.'
            format.html { redirect_to @listing }
            format.json { head :no_content }
         else
            format.html { render action: 'edit' }
            format.json { render json: @listing.errors, status: :unprocessable_entity }
         end
      end
   end

   def destroy
      @listing.destroy

      respond_to do |format|
         format.html { redirect_to listings_url }
         format.json { head :no_content }
      end
   end

   private
      # Use callbacks to share common setup or constraints between actions.
      def set_listing
         @listing = Listing.friendly.find(params[:id])
      end

      # Never trust parameters from the scary internet, only allow the white list through.
      def listing_params
         params.require(:listing).permit(:id, :condition, :description, :nickname, :price, :size, :title, :user_id)
      end
end

列表表格

<%= form_for(@listing, :html => { :class => 'form', :multipart => true }) do |f| %>
   <% if @listing.errors.any? %>
      <div id="error_explanation">
         <h2><%= pluralize(@listing.errors.count, "error") %> prohibited this listing from being saved:</h2>

         <ul>
         <% @listing.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
         <% end %>
         </ul>
      </div>
   <% end %>

   <div>
      <%= f.label :title %>
      <%= f.text_field :title, :required => true %>
   </div>

   <div>
      <%= f.label :price %>
      <%= f.text_field :price %>
   </div>

   <div class="actions">
      <%= f.submit 'Submit', :class => 'buyNow' %>
   </div>
<% end %>

图像控制器

class ImagesController < ApplicationController
   before_action :set_image, only: [:show, :edit, :update, :destroy]
   before_filter :load_listing

   def index
      @images = @listing.images.load
      @image = @listing.images.new
   end

   def new
   end

   def edit
   end

   def create
      @image = @listing.images.new(image_params)

      respond_to do |format|
         if @image.save
            format.html { redirect_to :back, notice: 'Image was successfully created.' }
            format.json { head :no_content }
         else
            format.html { render action: 'new' }
            format.json { render json: @image.errors, status: :unprocessable_entity }
         end
      end
   end

   def update
      respond_to do |format|
         if @image.update(image_params)
            format.html { redirect_to (@image.listing), notice: 'Image was successfully updated.' }
            format.json { head :no_content }
         else
            format.html { render action: 'edit' }
            format.json { render json: @image.errors, status: :unprocessable_entity }
         end
      end
   end

   def destroy
      @image = @listing.images.find(params[:id])
      @image.destroy

      respond_to do |format|
         format.html { redirect_to :back }
         format.json { head :no_content }
      end
   end

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

      def load_listing
         @listing = Listing.find(params[:listing_id])
      end

      # Never trust parameters from the scary internet, only allow the white list through.
      def image_params
         params.require(:image).permit(:file, :listing_id)
      end
end

图片索引

<div>
    <%= form_for [@listing, @image], :html => { :class => 'uploadImages', :multipart => true } do |f| %>
       <%= f.hidden_field :listing_id %>

       <div>
          <%= f.label :file, 'Upload Images' %>
          <%= f.file_field :file, multiple: true, name: 'image[file]' %>
       </div>
    <% end %>
</div>

<div id="progress"></div>

<% if @images.present? %>
    <ul class="editGallery">
        <% @listing.images.each do |image| %>
            <li>
                <%= image_tag image.file_url(:list) if image.file? %>
                <span><%= link_to 'DELETE', listing_image_path(@listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
            </li>
        <% end %>
    </ul>
<% end %>

【问题讨论】:

  • 在没有图片的情况下点击删除会发生什么?
  • 我收到“没有路线匹配 [DELETE]”错误,因为没有与该图像关联的 ID。图片 URL 通常是:../listings/1/images/ID#。对于那个空图像是:../listings/1/images。 @jkeuhlen
  • 如何创建列表?从您在此处显示的表单中,您实际上是在上传图片。
  • @chrisbedoya 我认为@images = @listing.images.load 可能是罪魁祸首。看起来您正在加载(并显示)零记录?
  • 我删除了.load,它仍然显示记录@jkeuhlen

标签: ruby-on-rails carrierwave nested-attributes


【解决方案1】:

问题出在这一行:

@image = @listing.images.new

这是为@listing 构建一个新图像,因此当您调用@listing.images.each 时,该新图像将包含在图像数组中。在为它构建删除链接之前,请检查该图像是否已实际保存到数据库中。

<% @listing.images.each do |image| %>
  <% unless image.new_record? %>
    <li>
      <%= image_tag image.file_url(:list) if image.file? %>
      <span><%= link_to 'DELETE', listing_image_path(@listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
    </li>
  <% end %>
<% end %>

【讨论】:

  • 比你晚了 46 秒才弄明白这一点 :(
  • 不错,我没注意到那个!
  • 感谢您的帮助!
【解决方案2】:

看看你的这部分代码:

<% if @images.present? %>
<ul class="editGallery">
    <% @listing.images.each do |image| %>
        <li>
            <%= image_tag image.file_url(:list) if image.file? %>
            <span><%= link_to 'DELETE', listing_image_path(@listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
        </li>
    <% end %>
</ul>

我相信你的问题是这个和你的图像控制器索引操作的组合。

当您点击索引操作时,您会创建一条新记录 @image = @listing.images.new

现在您的@listing.images.each 调用注册在尚未保存的对象上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多