Rails 4、Cloudinary、Carrierwave没有上传

Rails 4, Cloudinary, Carrierwave not uploading

我已经绞尽脑汁地翻阅了几个小时的文档,但我终究无法弄清楚哪里出了问题。该表单正在接受图像,但不会触发直接上传。下面是我的文件。

Gemfile

source 'https://rubygems.org'

# Platform 
  gem 'rails', '4.2.6'

# Authentication / Authorization 
  gem 'devise'

# View Tools
  gem 'jquery-rails'
  gem 'jquery-ui-rails'
  gem 'haml-rails'
  gem 'font-awesome-rails'
  gem 'friendly_id', '~> 5.1.0'

# Form
  gem 'cocoon'
  gem 'ckeditor'
  gem 'mini_magick'

# DB Tools
  gem 'pg'
  gem 'seed_dump'
  gem 'annotate'

# Image Serving & Uploading
  gem 'carrierwave'
  gem 'cloudinary'

# Server Tools
  gem 'puma'
  gem 'foreman'
  gem 'turbolinks'
  gem 'rails_12factor' # To silence Heroku deprecation warning

# Gems used only for assets and not required in production environments by default.
  gem 'sassc-rails'
  gem 'uglifier'

group :development do 
  gem 'web-console', '~> 2.0'
  gem 'awesome_print', :require => 'ap'
  gem 'better_errors'
  gem 'binding_of_caller'
  gem 'meta_request'
end

application.js

//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require bootstrap.min
//= require cloudinary
//= require cocoon
//= require turbolinks
//= require_tree .

scripts.js

$(function() {
  if($.fn.cloudinary_fileupload !== undefined) {
    $("input.cloudinary-fileupload[type=file]").cloudinary_fileupload();
  }
});

application.haml

    !!!
    %html

      %head
        %meta{:charset => "utf-8"}
        %meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"}
        %meta{:content => "width=device-width, initial-scale=1", :name => "viewport"}/
        %title Martin Furniture
        = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
        = javascript_include_tag 'application', 'data-turbolinks-track' => true
        = csrf_meta_tags
        = cloudinary_js_config

        %link{:href => "https://fonts.googleapis.com/css?family=Open+Sans|Oswald", :rel => "stylesheet"}

      %body
        = render :partial => 'layouts/partials/header'
        = yield
        = render :partial => 'layouts/partials/footer'

image_uploader.rb

class ImageUploader < CarrierWave::Uploader::Base
  include Cloudinary::CarrierWave
end

figure.rb

# == Schema Information
#
# Table name: figures
#
#  id              :integer          not null, primary key
#  caption         :string(255)
#  link            :text
#  figureable_id   :integer
#  figureable_type :string
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#  title           :string(255)
#  alt             :string(255)
#  image           :string
#

class Figure < ActiveRecord::Base
  default_scope                     { order(id: :ASC) }

  mount_uploader                    :image, ImageUploader

  # Figureable (Polymorphic)
  # ==========================================================================================================  
    belongs_to                      :figureable, 
                                      polymorphic:    true

end

page.rb

# == Schema Information
#
# Table name: pages
#
#  id          :integer          not null, primary key
#  name        :string(255)      not null
#  slug        :string
#  created_at  :datetime         not null
#  updated_at  :datetime         not null
#  template_id :integer          default(1), not null
#  title       :string(255)
#  content     :text
#  link        :text
#  parent_id   :integer
#

class Page < ActiveRecord::Base
  default_scope                     { order(id: :ASC) }

  extend FriendlyId
  friendly_id :name, use: :slugged

  # Figures (Polymorphic)
  # ==========================================================================================================  
    has_many                        :figures, 
                                      as:             :figureable

    accepts_nested_attributes_for   :figures, 
                                      reject_if:      :all_blank, 
                                      allow_destroy:  true

  # Validations
  # ==========================================================================================================  
    validates                       :name, 
                                      presence:       true,
                                      format:         { with: /[0-9a-zA-Z\s\/_:\-.|]*/ }

end

figures_controller.rb

class FiguresController < ApplicationController
  before_action :set_figure, only: [:show, :edit, :update, :destroy]

  def index
    @figures = Figure.all
  end

  def show
  end

  def new
    @figure = Figure.new
  end

  def edit
  end

  def create
    @figureable   = find_figureable

    if @figurable
      @figure     = @figureable.figures.build(figure_params)
    else 
      @figure     = Figure.new(figure_params)
    end

    if @figure.save
      redirect_to @figure, notice: 'Figure was successfully created.'
    else
      render :new
    end
  end

  def update
    if @figure.update(figure_params)
      redirect_to @figure, notice: 'Figure was successfully updated.'
    else
      render :edit
    end
  end

  def destroy
    @figure.destroy
    redirect_to figures_url, notice: 'Figure was successfully destroyed.'
  end

  private
    def set_figure
      @figure = Figure.find(params[:id])
    end

    def figure_params
      params.require(:figure).permit(:caption, :link, :figurable_id, :figurable_type)
    end

    def find_figureable
      params.each do |name, value|
        if name =~ /(.+)_id$/
          return = .classify.constantize.find(value)
        end
      end

      nil

    end
end

pages_controller.rb

class PagesController < ApplicationController
  before_action :set_page, only: [:edit, :update, :destroy]

  # GET /pages
  def index
    @pages = Page.all.reorder(slug: :ASC)
  end

  # GET /pages/1
  def show
    @page = Page.friendly.find(params[:id])

    page_template = "layouts/templates/#{@page.name.parameterize.underscore}"

    if lookup_context.find_all(page_template).any?
      render page_template
    else
      render :show
    end
  end

  # GET /pages/new
  def new
    @page = Page.new    
  end

  # GET /pages/1/edit
  def edit
  end

  # POST /pages
  def create
    @page = Page.new(page_params)

    if @page.save
      redirect_to pages_url, notice: 'Page was successfully created.'
    else
      render :new
    end
  end

  # PATCH/PUT /pages/1
  def update
    if @page.update(page_params)
      redirect_to pages_url, notice: 'Page was successfully updated.'
    else
      render :edit
    end
  end

  # DELETE /pages/1
  def destroy
    @page.destroy
    redirect_to pages_url, notice: 'Page was successfully destroyed.'
  end

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

    # Only allow a trusted parameter "white list" through.
    def page_params
      params.require(:page)
        .permit(
          :name, 
          :slug,
          :template_id,
          :title,
          :content,
          :link,

          # belongs_to
            :parent_id,

          # has_many (Nested Attributes)
            { :figures_attributes => [ 
                :_destroy,
                :id,
                :caption,
                :link,
                :title,
                :alt,
                :image
            ]},

        )
    end
end

pages/_form.haml

= form_for @page do |f|
  - if @page.errors.any?
    #error_explanation
      %h2= "#{pluralize(@page.errors.count, "error")} prohibited this page from being saved:"
      %ul
        - @page.errors.full_messages.each do |msg|
          %li= msg

  .field
    = f.label :name
    = f.text_field :name

  %h3 Figures
  #figures
    = f.fields_for :figures do |figure|
      = render 'figures/figure_fields', f: figure
    .links
      = link_to_add_association 'Add Figure', f, :figures, partial: 'figures/figure_fields'

  .field
    = f.cktext_area :content

  .actions
    = f.submit 'Save'

figures/_figure_fields.html

.nested-fields
  .field
    = f.label :caption
    = f.text_field :caption
  .field
    = f.label :link
    = f.text_field :link

  .field
    = f.label :image, "Image"
    = f.cl_image_upload :image

  = link_to_remove_association "Remove Figure", f

表单提交参数

Processing by PagesController#create as HTML
20:43:40 web.1  |   Parameters: {"utf8"=>"✓", "authenticity_token"=>"AUTHENTICITY_TOKEN", "page"=>{"name"=>"Blah2", "figures_attributes"=>{"1471318988746"=>{"caption"=>"B", "link"=>"C", "_destroy"=>"false"}}, "content"=>""}, "file"=>"main_image.jpg", "commit"=>"Save"}

呈现的输入元素

<input type="file" name="file" data-url="https://api.cloudinary.com/v1_1/CLOUD_NAME/auto/upload" data-form-data="{"callback":"http://localhost:8080/cloudinary_cors.html","timestamp":1471319573,"signature":"SIGNATURE","api_key":"API_KEY"}" data-cloudinary-field="page[figures_attributes][1471319575584][image]" class="cloudinary-fileupload">

cloudinary.yml

---
#Production MF
development:
  cloud_name: CLOUD_NAME
  api_key: 'API_KEY'
  api_secret: SECRET_KEY
  enhance_image_tag: true
  static_image_support: false
production:
  cloud_name: CLOUD_NAME
  api_key: 'API_KEY'
  api_secret: SECRET_KEY
  enhance_image_tag: true
  static_image_support: true
test:
  cloud_name: CLOUD_NAME
  api_key: 'API_KEY'
  api_secret: SECRET_KEY
  enhance_image_tag: true
  static_image_support: false

*注意上面的CLOUD_NAMEAPI_KEYSIGNATUREAUTHENTICITY_TOKENSECRET_KEY填写的信息正确,但已被删除为此 post。此外,cloudinary_cores.html 文件在我的 public 目录中。

我已经尝试按照 Cloudinary Gems repo and on their help docs 上的说明进行操作,但无法弄清楚问题所在。

如果还有任何其他需要,请告诉我。

所以,原来 turbolinks gem 是这里的罪魁祸首。通过将 scripts.js 更改为以下内容,我现在正在正确上传。

注意:这是 Turbolinks 5 的用法 - 以前的版本需要稍微不同的设置。

scripts.js

// jQuery "$(document).ready()" equivalent for Trubolinks 5 usage

$(document).on('turbolinks:load', function() {
  console.log("trubolinks:load - jQuery Ready!");

  $(function() {
    cloudinaryUploaderInit();
  });
});

var cloudinaryUploaderInit = function() {
  // console.log("cloudinaryUploaderInit");
  if ($.fn.cloudinary_fileupload !== undefined) {
    $("input.cloudinary-fileupload[type=file]").each(function() {
      $(this).cloudinary_fileupload();
    });
  } else {
    // console.log("`cloudinary_fileupload` is undefined");
  }
}

编辑: 或者(可能更合适),您可以使用 jquery-turbolinks gem,如下所述:https://github.com/cloudinary/cloudinary_gem/issues/126