Skip to main content
 首页 » 编程设计

ruby-on-rails中rails 4 : Multiple image upload using paperclip

2025年01月19日11jackei

我希望将多个图像上传到我的“位置”模型。我将图像模型称为“ Assets ”。一个地点拥有多项 Assets 。我还使用回形针来处理上传和nested_form以允许选择多个 Assets 。

奇怪的是,位置哈希看起来正确地传递了变量,但它们似乎没有被 Assets 模型拾取。任何帮助都会很棒!

位置模型

class Location < ActiveRecord::Base 
 
  has_many :location_post 
  has_many :posts, :through => :location_post   
  has_many :assets, dependent: :destroy 
 
  attr_accessor :asset, :assets_attributes 
  accepts_nested_attributes_for :assets, :allow_destroy => true  
end 

Assets 模型

class Asset < ActiveRecord::Base 
 
   belongs_to :location 
 
   has_attached_file :asset, 
                    :styles => { 
                      :blurred => "600x300^",:large => "600x600>", :medium => "250x250^" , :thumb => "100x100^"}, 
                      #:source_file_options =>  {:all => '-rotate "-90>"'}, 
                      :convert_options => { 
                      :all => '-auto-orient', :blurred => "-blur 0x6 +repage -resize 600x300^"  
                        }, 
                      :storage => :s3, 
                      :s3_credentials => "#{Rails.root}/config/s3.yml", 
                      :bucket => "[bucketname]", 
                      :path => "/:style/:id/:filename"     
 
validates_attachment_content_type :asset, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"] 
 
end 

位置 Controller

class LocationsController < ApplicationController 
 
... 
 
  def new 
    @location = Location.new 
    @location.assets.build 
    @georesult = Geocoder.search(params[:query]) 
  end 
 
  def create 
 
    @location = Location.find_or_create_by(name: location_params[:name]) 
 
 
    respond_to do |format| 
     if @location.save 
       format.html { redirect_to @location, notice: ' <borat voice> Great success! </borat voice>' } 
       format.json { render :show, status: :created, location: @location } 
     else 
       format.html { render :new } 
       format.json { render json: @location.errors, status: :unprocessable_entity } 
     end 
   end 
  end 
 
  # PATCH/PUT /locations/1 
  # PATCH/PUT /locations/1.json 
  def update 
    respond_to do |format| 
     if @location.update(location_params) 
      format.html { redirect_to @location, notice: 'Location was successfully updated.'  } 
      format.json { render :show, status: :ok, location: @location } 
     else 
      format.html { render :edit } 
      format.json { render json: @location.errors, status: :unprocessable_entity } 
     end 
    end 
  end 
 
 ... 
 
 private 
    # Use callbacks to share common setup or constraints between actions. 
 def location_params 
      params[:location].permit(:name, :notes, :longitude, :country, :latitude, :query, assets_attributes: [ :asset, :asset_content_type, :asset_file_name, :tempfile, :asset_file_size, :asset_updated_at, :_destroy]) 
    end 
 end 

表单 View

<%= nested_form_for(@location, :html=> {:multipart => true}) do |f| %> 
 
... 
 
  <%= f.fields_for :assets do |a| %> 
    <%= a.file_field :asset %> 
    <%= a.link_to_remove "Remove this image" %> 
  <% end %> 
<%= f.link_to_add "Add an image", :assets %> 
 
... 
 
    <%= f.submit "Submit", :class => "btn btn-success submit_location" %> 
 
<% end %> 

日志输出

Processing by LocationsController#update as HTML 
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"n4spoLjq4B3sZSJjqsGFRVjkseOwGgvquAHATBRG1Nk=", "location"=>{"name"=>"York", "notes"=>"", "lat 
itude"=>"53.96230079999999", "longitude"=>"-1.0818844", "country"=>"", "assets_attributes"=>{"0"=>{"asset"=>#<ActionDispatch::Http::UploadedFile 
:0x007ff739b7bb68 @tempfile=#<Tempfile:/var/folders/sc/gps8hkgj7yg31j81gpnfg9h00000gn/T/RackMultipart20140706-43312-kdpghs>, @original_filename= 
"78509.max1024.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"location[assets_attributes][0][asset]\"; filen 
ame=\"78509.max1024.jpg\"\r\nContent-Type: image/jpeg\r\n">, "_destroy"=>"false"}}}, "commit"=>"Submit", "id"=>"240"} 
  User Load (0.6ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1 
  Location Load (0.4ms)  SELECT  "locations".* FROM "locations"  WHERE "locations"."id" = $1 LIMIT 1  [["id", 240]] 
   (0.2ms)  BEGIN 
   (0.3ms)  COMMIT 
Redirected to http://localhost:3000/locations/240 
Completed 302 Found in 9ms (ActiveRecord: 1.6ms) 

请您参考如下方法:

我在您的代码中发现了几个问题:

首先,您需要从 Location 模型中删除以下行:

attr_accessor :asset, :assets_attributes 

因为它使 assetasset_attributes 作为虚拟属性,这就是它们不保存在数据库中的原因。此外,您不需要 Location 模型中的 asset 属性,因为它已由 Asset 模型处理。

然后,按照 @Pavan 的建议更新 location_params:

def location_params 
  ## Use `require` method 
  params.require(:location).permit(:name, :notes, :longitude, :country, :latitude, :query, assets_attributes: [ :asset, :asset_content_type, :asset_file_name, :tempfile, :asset_file_size, :asset_updated_at, :_destroy]) 
end 

接下来,更新 create 操作,如下所示,以确保位置的名称是唯一的:

def create 
  @location = Location.find_by(name: location_params[:name]) 
  unless @location 
    @location = Location.new(location_params) 
  end  
  respond_to do |format| 
    if @location.save 
      format.html { redirect_to @location, notice: ' <borat voice> Great success! </borat voice>' } 
      format.json { render :show, status: :created, location: @location } 
    else 
      format.html { render :new } 
      format.json { render json: @location.errors, status: :unprocessable_entity } 
    end 
  end 
end