【问题标题】:Rails form not passing image with carrierwaveRails 形成不通过载波传递图像
【发布时间】:2014-10-30 00:04:38
【问题描述】:

我目前有一个上传表单,它采用 epub 文件,使用 epubinfo 对其进行解析,然后以另一种表单显示以验证我们提取的信息是否正确。然后我们从这个表单提交这个新的上传。

第一个表单 (upload.html.erb) 似乎完全符合我的预期,提取了我需要的所有信息,包括封面图片,并在编辑/验证表单 (new.html.erb) 中适当显示)。但是,问题在于第二种形式(新)。发布后,它不会保留显示的封面图像,而是不保存任何内容,即使此表单中任何其他更改(或未更改)的数据按应有的方式发布。

需要注意的是,当上传表单发布时,public/tmp 会得到两个文件,epub 和 png,并且在发布新表单时,epub tmp 会消失并被公开,但是 png 保持在 public/温度。

红宝石 2.1.1p76 导轨 4.1 CarrierWave 0.10.0

/views/pages/upload.html.erb

      <%= form_for Book.new, :url => new_book_path do |f| %>
    <div class="form-group">
      <%= f.label :book, "Upload an epub" %>
      <%= f.file_field :book, class: "form-control" %>
      <%= f.hidden_field :book_cache %>
    </div>

    <br />

    <div class="form-group">
      <%= f.button "Upload", class: "btn btn-primary", data: {disable_with: "Uploading..."} %>
    </div>
  <% end %>

/app/controllers/books_controller.rb(经过一些处理):

class BooksController < ApplicationController
  before_action :redirect_to_book, only: [:index]
  before_action :set_book, only: [:show, :edit, :update, :destroy, :download]
  before_action :is_mod, only: [:edit, :update, :destroy]

    def create
    @books = Book.new(book_params)
    if @books.author.nil? && book_params[:author_name].present?
      @books.author = Author.where(name: book_params[:author_name]).first_or_create
    end
    if @books.series.nil? && book_params[:series_name].present?
      @books.series = Series.where(name: book_params[:series_name]).first_or_create
    end
    if book_params[:is_public].present?
    else
      @books.is_public == true
    end
    if @books.save
      redirect_to book_path(@books), success: "The book was successfully saved!"
    else
      redirect_to new_book_path
    end
  end

  def new
    @authors = Author.all
    @series = Series.all
    @books = Book.new(book_params)
    @books.extract_epub_info
  end

  private
    def set_book
      @books = Book.find(params[:id])
    rescue ActiveRecord::RecordNotFound
      redirect_to "/404"
    end

    def redirect_to_book
      redirect_to book_path(params[:book_id]) if params[:book_id]
    end

    def book_params
      params.require(:book).permit(:book, :cover, :title, :isbn, :summary, :is_public, :series_nbr, :author_id, :author_name, :series_id, :series_name, :tag_list, :book_cache)
    end

    def is_mod
      unless current_mod
        redirect_to book_path, error: "You're not allowed to edit books."
      end
    end

end

/app/uploaders/book_uploader.rb

class BookUploader < CarrierWave::Uploader::Base
  storage :file

  def store_dir
    "uploads/#{mounted_as}"
  end

  def filename
    "#{model.id}.epub"
  end

end

/app/uploaders/cover_uploader.rb

class CoverUploader < CarrierWave::Uploader::Base
  storage :file

  def store_dir
    "uploads/#{mounted_as}"
  end

  def filename
    "#{model.id}.png"
  end

end

/app/models/book.rb

class Book < ActiveRecord::Base
  belongs_to :author
  belongs_to :series
  has_many :downloads
  has_many :flags
  has_many :ratings
  has_many :raters, :through => :ratings, :source => :users

  validates :title, :author_id, presence: true

  attr_accessor :author_name, :series_name

  acts_as_taggable
  scope :public_books, ->{ where(is_public: true) }
  mount_uploader :book, BookUploader
  # validates_presence_of :book
  mount_uploader :cover, CoverUploader
  # validates_presence_of :cover

    searchable do
      text :title
      text :summary
      text :isbn
    integer :is_public
    end

  def epub
    @epub ||= EPUBInfo.get(book.file.path)
  end

  def extract_epub_info

    if epub.creators.first.name.include? ","
      self.author = Author.where(name: epub.creators.first.name).first_or_create
    else
      parts = epub.creators.first.name.split
      first = parts.first
      last = parts[1..-1].join(" ")

      self.author = Author.where(name: "#{last}, #{first}").first_or_create
    end

    self.title = epub.titles.first
    self.summary = epub.description
    self.is_public = true
    self.isbn = epub.identifiers.find{ |i| i.scheme == "ISBN" }.try(:identifier)

    if epub.cover.present?
      self.cover = epub.cover.tempfile
    else
    end
  end

end

以及正确显示封面但在您提交表单时不发布的编辑表单。 /views/books/new.html.erb:

<%= form_for @books, url: books_path, html: {multipart: true} do |f| %>
  <% if @books.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@books.errors.count, "error") %> prohibited this author from being saved:</h2>
      <ul>
        <% @books.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <br/><br/>

  <div class="alert alert-warning">
    <strong>Please validate that all of this information is correct before saving the book!</strong>
  </div>

  <br/>

  <% if @books.cover.present? %>
    <div align="center">
      <%= image_tag @books.cover %>
    </div>
  <% end %>

  <div class="form-group">
    <%= f.label :title %>
    <%= f.text_field :title, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= f.label :author %>
    <%= f.collection_select(:author_id, @authors.order("name ASC"), :id, :name, {:include_blank => true} ) %>
    OR New Author Name:
    <%= f.text_field :author_name, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= f.label :isbn %>
    <%= f.text_field :isbn, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= f.label :summary %>
    <%= f.text_area :summary, class: "form-control", size: "20x10" %>
  </div>

  <div class="form-group">
    <%= f.label :series_nbr %>
    <%= f.text_field :series_nbr, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= f.label :series %>
    <%= f.collection_select(:series_id, @series.order("name ASC"), :id, :name, {:include_blank => true} ) %>
    OR New Series Name:
    <%= f.text_field :series_name, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= f.label :tag_list %>
    <%= f.text_field :tag_list, class: "form-control" %>
  </div>

  <%= f.hidden_field :book_cache %>

  <div class="form-group">
    <%= f.label :cover, "Upload a cover" %>
    <%= f.file_field :cover, class: "form-control" %>
  </div>

  <br/>

  <div class="form-group">
    <%= f.hidden_field :is_public, :value => "1" %>
    <%= f.submit class: "btn btn-primary", data: { confirm: "Are you sure all of this information is correct?\rYou will not be able to edit it later." } %>
  </div>

<% end %>

编辑路线 11/2 @ 9:20ET

routes.rb

App::Application.routes.draw do
  root "pages#home"

  # All pages
  get "browse" => "books"
  get "browse/new" => "books#newest"
  get "browse/popular" => "books#popular"
  get "browse/random" => "books#random"
  get "faq" => "pages#faq"
  get "empowerment" => "pages#empowerment"
  get "legal" => "pages#legal"
  get "pages/catalog"
  get "search" => "search#search"
  get "search/search"
  get "upload" => "pages#upload"
  get "download" => "pages#download"
  get "dmca" => "pages#dmca"

  # Catalog Routes
  get "catalog" => "catalog#index", defaults: {format: :atom}
  get "catalog/search" => "catalog#search", defaults: {format: :atom}
  %w{ newest popular random author title serie tag }.each do |section|
    get "catalog/#{section}", controller: :catalog, action: section, defaults: {format: :atom}
  end
  get "catalog/author/:id" => "catalog#authored_by", defaults: {format: :atom}
  get "catalog/tag/:tag" => "catalog#tagged", defaults: {format: :atom}

  # Normal Model stuff
  resources :authors
  resources :series
  resources :books do
    collection do
      get "tagged/:tag", action: :tagged, as: :tagged
      post "new", action: :new, as: :new_book
    end
    member do
      get :download
    end
  end
  resources :tags

  # Stuff for Mods and management
  devise_for :mods
  namespace "admin" do
    resources :mods
  end
  devise_scope :mod do
    get "mods" => "devise/sessions#new"
  end

  # Lists for dropdowns
  get "authorlist" => "books#authorlist"
  get "serieslist" => "books#serieslist"
  get "taglist" => "books#taglist"

  # Let's be nice and support old urls.
  get "book/show/id/:id" => "books#show"
  get "serie/:id" => "series#show"
  get "author/:id" => "authors#show"
  get "browse/author/:id" => "authors#show"

end

我不确定还需要什么。我觉得我缺少的东西很简单,但是盯着它看了这么久我只是停止了任何进步。我知道封面图片显示在 new.html.erb 中,因为它显示在表单的 image_tag 中,但是在发布时它不会保存参数。

停下! :(

【问题讨论】:

  • 是书籍/新书无法正常工作吗?
  • 正确。上传表单可以正常工作,但新表单不会将封面图片保存到数据库中。

标签: ruby-on-rails ruby forms carrierwave


【解决方案1】:

/views/pages/upload.html.erb -- 缺少multipart: true

&lt;%= form_for Book.new, html: { multipart: true } do |f| %&gt;

我认为您不需要提供 url 参数,除非您错误地设置了您的路线/模型。您也应该在其他表单中更改此设置。

/app/controllers/books_controller.rb

您完全缺少编辑/更新方法。这是设计使然吗?为什么?这就是您在表单中提供url 选项的原因吗?这会造成混乱。

您是否查看过book_params 的内容以查看图像数据是否被正确接收?如何检查实际的图像文件是否已创建?如果它们被创建,也许它们只是不可访问(检查文件权限)。

进一步编辑:我无法根据您显示的内容确定事物的路由方式。请同时显示您的路线,并清楚说明哪些操作会导致不良后果。

即“我想创建一本新书,但上传的图片没有保存”(意味着它不存在于数据库中,并且磁盘上的任何地方都没有实际的图片)。

或

“我可以创建一本书并保存图像,但在查看编辑页面时,图像不显示”

【讨论】:

  • 在新表单中添加了 multipart: true (似乎没有什么区别,并且不应该是必需的,因为 form_for 会为您完成,但是添加它是为了保持一致)。我通常不在表单中使用 url,这两个表单是必需的,因为我们需要 anyone 能够上传一本书,然后与验证表单 (new.html.erb) 交互,但是他们不能在事后编辑/销毁它们。 OP 已更新以包括路线。图像实际上保存在 /public/tmp 以及书籍中。发布新书后,书会消失并保存,封面不会。保留在 tmp 中。
猜你喜欢
  • 2015-06-08
  • 2015-02-08
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-15
  • 1970-01-01
相关资源
最近更新 更多