Ruby on Rails - Paperclip不能保存到数据库

6
我正在尝试在rails中创建产品页面,其中包括添加多个图片。我有一个产品模型,一个照片模型和一个用户模型。我正在使用paperclip宝石来上传照片。但是我有两个问题。
  1. 我的文件输入框不能让我选择多个图片。
  2. 当我查看产品时,没有图片显示,因为图片没有被保存到数据库中

P.S.我使用HAML,我没有照片控制器。

产品控制器

class ProductsController < ApplicationController
    before_filter :current_user, only: [:create, :destory]
    before_filter :correct_user, only: :destory

  def new 
@product = Product.new
    @photo = Photo.new
    5.times { @product.photos.build }
  end

  def create

  @photo = current_user.photos.build(params[:photo])

  @product = current_user.products.build(params[:product])
    if @product.save
        render "show", :notice => "Sale created!"
    else
        render "new", :notice => "Somehting went wrong!"
    end
end

def show
@product = Product.find(params[:id]) 
end

创建产品页面
= form_for @product, :html => { :multipart => true } do |f|
  - if @product.errors.any?
    .error_messages
      %h2 Form is invalid
      %ul
        - for message in @product.errors.full_messages
          %li
            = message
  %p
    = f.label :name
    = f.text_field :name
  %p
    = fields_for :photos do |f_i|
      =f_i.file_field :image 

  %p.button
    = f.submit

产品型号

class Product < ActiveRecord::Base
  attr_accessible :description, :name, :price, :condition, :ship_method, :ship_price, :quantity, :photo
  has_many :photos, dependent: :destroy
  accepts_nested_attributes_for :photos
  belongs_to :user

照片模式

class Photo < ActiveRecord::Base
  attr_accessible :product_id

  belongs_to :product
  has_attached_file :image,
    :styles => {
      :thumb=> "100x100#",
      :small  => "300x300>",
      :large => "600x600>"
        }
end

用户模型

class User < ActiveRecord::Base
  attr_accessible :email, :password, :password_confirmation, :name

  attr_accessor :password
  has_many :products, dependent: :destroy
  has_many :photos,:through=>:products

展示产品页面
  %b seller
  = @product.user.name
  %br 
  - @product.photos.each do |photo|
    = image_tag photo.image.url

你的用户模型中是否有这个方法:User has many :photos, :through=>:products? - Remon Amin
1
不,我没有。我有has_many:products,dependent:destroy。 - Alain Goldman
1
http://railscasts.com/episodes/196-nested-model-form-part-1 - Larry McKenzie
请查看我在原帖中的更新,有些事情已经改变。 - Alain Goldman
我到目前为止还不明白你为什么要再次问同样的问题...旧的那个呢?你在浪费别人的时间...https://dev59.com/g3HYa4cB1Zd3GeqPSf8f - Muhammad Sannan Khalid
显示剩余5条评论
6个回答

3

你的 User 模型没有关联到照片,所以照片只属于 Product 模型,因此你需要修改 User 模型

 class User < ActiveRecord::Base
  has_many :products
  has_many :photos,:through=>:products


  end

然后你可以通过

获取用户照片

 @photos =current_user.photos 

或者你可以轻松地建立一张照片。
@photo = current_user.photos.build(params[:photo])

在您的视图中,您需要使用以下代码代替= f.file_field :photo, multiple: 'multiple':

使用

= fields_for :photos do |f_i|
    =f_i.file_field :image

试一下。

这是使用多对多关联的简单方法。

   class Document < ActiveRecord::Base
  has_many :sections
  has_many :paragraphs, :through => :sections
  end

 class Section < ActiveRecord::Base
 belongs_to :document
  has_many :paragraphs
end

class Paragraph < ActiveRecord::Base
 belongs_to :section
 end

你可以查看以下指南以获取更多信息 http://guides.rubyonrails.org/association_basics.html 同时,你需要添加

 accepts_nested_attributes_for :photos

在您的产品模型中

如果您想了解有关嵌套表单的完整教程,可以观看这些屏幕录像。

http://railscasts.com/episodes/196-nested-model-form-revised

这不是免费的。

如果你没有订阅railscasts.com,你可以观看这些免费的屏幕录像。

http://railscasts.com/episodes/196-nested-model-form-part-1

http://railscasts.com/episodes/197-nested-model-form-part-2


1
嗯,我做了那个更改,执行了 bundle exec rake db:migrate 然后重启了服务器,但我仍然得到相同的错误。 - Alain Goldman
在你的产品模型中,你需要放置 has_many :photos 而不是 has_attached_file :photo,这样它才能正常工作。 - Remon Amin
未定义方法“photos”用于nil:NilClass - Alain Goldman
在你的Product模型中添加accepts_nested_attributes_for :photos。 - Remon Amin
同时删除@photo = current_user.photos.build(params[:photo]),因为照片将作为嵌套在产品表单中构建。 - Remon Amin
我已经从代码中删除了@photo = current_user.photos.build(params[:photo]),并在产品模型中添加了accepts_nested_attributes_for :photos,但仍然出现“undefined method 'photos' for nil:NilClass”错误。 - Alain Goldman

2

试试这个:

新产品页面

= form_for @product, :html => {:multipart => true} do |f|
  %p
    = f.label :description
    = f.text_field :description

  = f.fields_for :photo do |fp|
    = fp.file_field :image
    = fp.check_box :_destroy
    = fp.label :_destroy, "Remove Image" 

  %p.button
    = f.submit

产品控制器

def new
  @product = Product.new
  @product.photos.build
end

def create  
  @product = current_user.products.create(params[:product])
  # or
  # @product = current_user.products.build(params[:product])
  # @product.save
end

产品型号
class Product < ActiveRecord::Base
  attr_accessible :description, :name, :photo
  accepts_nested_attributes_for :photo, :reject_if => lambda { |p| p[:image].nil? }, :allow_destroy => true

  belongs_to :user
  has_many :photos, dependent: :destroy

  validates :user_id,      presence: true
  validates :photo,        presence: true
end

照片模型

class Photo < ActiveRecord::Base
  attr_accessible :image
  belongs_to :product
    validates_attachment :image, presence: true,
         content_type: { content_type: ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'] },
         size: { less_than: 5.megabytes }
    has_attached_file :image, styles: { medium: "320x240>"}

end

使用这个代码我得到了NoMethodError在ProductsController#new中,undefined method `build' for nil:NilClass。 - Alain Goldman
1
请查看更新后的代码,并将“@product.photo.build”替换为“@product.build_photo”。 - Sachin Singh
@AlainGoldman 这个问题是我自己的笔误,我写成了 '@product.photo.build' ,而实际应该是 '@product.photos.build'。 - Larry McKenzie
@SachinSingh 感谢您的编辑,但这是一个 has_many 关联而不是 has_one。 - Larry McKenzie

1
  1. 如果您正在使用嵌套表单,则无需单独创建每个对象。创建产品将创建嵌套的照片。
  2. build方法只会创建一个对象,不会将对象保存到数据库中。您应该在create操作中调用object.save或者使用create方法而不是build方法。

我使用了 Build 来创建一个没有照片的产品。 - Alain Goldman
1
@AlainGoldman,照片属性嵌套在产品属性中,参数看起来像这样 :product => {:description => 'blah blah', :photo_attributes => {:image => "<File>"}}。因此,当您创建一个产品对象时,还会创建一个关联的照片。 - user946611

1

如果你正在使用Resque进行后台作业处理,那么你需要使用rake resque:work QUEUE='*'来启动它。在Rails中,通常使用Resque来处理涉及邮件发送和图片上传的后台作业。或者,以下是一个示例,product.html.erb具有用于该产品照片上传的partial,并配置了Amazon S3的paperclip。

product.html.erb

<%= render :partial => 'photos' %>

_photos.html.erb至少需要一张图片

       <% if @product.photos[0].nil? %>
                <a href="javascript:void(0);" class="add-photos" >
                <img src="/assets/default/product-add-photos.png" alt="Add product photos"/>              
                 </a>   
        <% end %>
 <img src="<%= (@product.product_photos[0].nil? ? "" : @product.photos[0].image.url(:small)) %>" id="photos_1" class="product-photos-src <%=@product.photos[0].nil? ? 'dontdisplay' : ''%> "/>

0

我认为这里的实际问题是您想通过paperclip在一个模型上附加多个照片。 每个模型只能附加1个文件,所以我建议您这样做:

1. create model Photo with paperclip migrations + has_attached_file
2. Product has_many :photos
3. (optional) make a function to return all image urls, otherwise just call the method in the view

   class Product 
     def get_pics
        photos.collect{|p| p.image.url}
     end
   end

另外一个好处是,现在你可以在照片模型中包含元数据,比如alt文本等!

<% @product.photos.each do |photo| %>
  <%= image_tag photo.image.url, :alt => photo.alt_text %>
<% end %>

0

我也遇到了同样的问题。我在stackoverflow上提问,最终通过自己的努力和rails cast的帮助解决了问题。

首先需要更改的是: 您必须按照以下步骤在模型端和控制器端实现嵌套属性:

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

然后请点击下面的链接,查看我的回答,其中包括你应该遵循嵌套表单的 Rails Cast 链接:

你会看到 Rails Cast 的第二个链接会动态地将每个字段分开,因为它无法将每组字段分开。但是在 Rails Cast 中也存在身份唯一性算法的不足之处。因此,我进行了改进,以确保某些字段集的唯一性与其他字段集不同。

jquery 渲染局部只需一次,第二次不再渲染,只显示上一个


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接