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_NAME
、API_KEY
、SIGNATURE
、AUTHENTICITY_TOKEN
和SECRET_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
我已经绞尽脑汁地翻阅了几个小时的文档,但我终究无法弄清楚哪里出了问题。该表单正在接受图像,但不会触发直接上传。下面是我的文件。
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_NAME
、API_KEY
、SIGNATURE
、AUTHENTICITY_TOKEN
和SECRET_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