与图像的多态关联
Polymorphic associations with images
提前抱歉我的英语不好。我用 rails 生成了两个模型,一个文章模型和一个图片模型。在图片模型中,我使用 CarrierWave 上传图片。现在我的问题是如何在完成文章表单后将图像保存在数据库 table 中。当我上传图像然后按提交时,表单会保存所有数据,图像除外。我想我的 Article 控制器有问题。
我会为每篇文章保存图片,并使用上传多张图片的表单来完成。上传来自 CarrierWave。但是当我提交表单时,我获得了显示视图,其中包含除图像之外的文章的所有参数(标题、描述等)。我使用多态关联是因为我还需要将图片模型用于其他模型。
文章形式为:
<%= form_for([:admin, @article], html: { class: "form-horizontal", role: "form" }) do |f| %>
<% if @article.errors.any? %>
<div class="alert alert-danger alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h4>
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :article_category_id, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.collection_select :article_category_id, ArticleCategory.all, :id, :name, {}, {class: "form-control"} %>
</div>
</div>
<div class="form-group">
<%= f.label :title, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_field :title, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :description, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_area :description, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :tag_list, "Tag (separati dalla virgola)", class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_field :tag_list, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :pictures, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.file_field :pictures, multiple: true %>
<p>larghezza: 800px - altezza: 800px<br />DPI 72<br />peso inferiore a 50kb<br />tipo file jpg o png (scarica esempio da <%= link_to "qui", "/res/test.jpg", :target => "_blank" %>)</p>
</div>
</div>
<div class="form-group">
<%= f.label :date, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.date_select :date, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :status, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.select :status, options_for_select(Article.statuses.collect{|item, val| [item.humanize, item]}, selected: @article.status), class: "form-control" %>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<%= f.submit class: "btn btn-primary" %>
</div>
</div>
<% end %>
文章负责人是:
class Admin::ArticlesController < Admin::AdminController
include Sortable
before_action :set_article, only: [:show, :edit, :update, :destroy]
# GET /articles
# GET /articles.json
def index
if params[:tag]
@articles = Article.tagged_with(params[:tag])
else
@articles = Article.all
end
end
# GET /articles/1
# GET /articles/1.json
def show
end
# GET /articles/new
def new
@article = Article.new
end
# GET /articles/1/edit
def edit
end
# POST /articles
# POST /articles.json
def create
@article = Article.new(article_params)
respond_to do |format|
if @article.save
format.html { redirect_to [:admin, @article], notice: 'Articolo creato con successo.' }
format.json { render :show, status: :created, location: @article }
else
format.html { render :new }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /articles/1
# PATCH/PUT /articles/1.json
def update
respond_to do |format|
if @article.update(article_params)
format.html { redirect_to [:admin, @article], notice: 'Articolo aggiornato con successo.' }
format.json { render :show, status: :ok, location: @article }
else
format.html { render :edit }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.json
def destroy
@article.destroy
respond_to do |format|
format.html { redirect_to admin_articles_url, notice: 'Articolo eliminato con successo.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
@article = Article.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:article_category_id, :title, :description, :date, :tag_list, :status, :pictures_attributes => [:id, :picturable_type, :picturable_id, :image => []])
end
end
文章型号为:
class Article < ApplicationRecord
acts_as_list
acts_as_taggable_on :tags
belongs_to :article_category
has_many :comments
has_many :pictures, as: :picturable
accepts_nested_attributes_for :pictures
enum status: {bozza: 0, pubblicato: 1}
default_scope {order("position ASC")}
def final_image_url
if self.image.present?
return self.image_url
else
return "/res/no-image.png"
end
end
end
# == Schema Information
#
# Table name: articles
#
# id :integer not null, primary key
# article_category_id :integer
# title :string(255)
# description :text(65535)
# date :date
# created_at :datetime not null
# updated_at :datetime not null
# position :integer
# status :integer
#
图片型号为:
class Picture < ApplicationRecord
belongs_to :picturable, polymorphic: true
mount_uploader :image, ImageUploader
end
# == Schema Information
#
# Table name: pictures
#
# id :integer not null, primary key
# image :string(255)
# picturable_type :string(255)
# picturable_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
上传者设置为:
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process scale: [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_whitelist
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
提前感谢您的帮助。
尝试使用以下代码更改表单代码:-
.................
................
<div class="form-group">
<%= f.label :tag_list, "Tag (separati dalla virgola)", class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_field :tag_list, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.fields_for :pictures, f.object.pictures.build do |picture| %>
<label class="col-sm-2 control-label">Image</label>
<div class="col-sm-10">
<%= picture.file_field :image, class: "form-control"%>
<p>larghezza: 800px - altezza: 800px<br />DPI 72<br />peso inferiore a 50kb<br />tipo file jpg o png (scarica esempio da <%= link_to "qui", "/res/test.jpg", :target => "_blank" %>)</p>
</div>
</div>
<div class="form-group">
<%= f.label :date, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.date_select :date, class: "form-control" %>
</div>
</div>
..............
..............
并使用以下代码更改您的控制器许可方法:-
def article_params
params.require(:article).permit(:article_category_id, :title, :description, :date, :tag_list, :status, :pictures_attributes => [:id, :image])
end
然后再次尝试提交您的表单...:)
提前抱歉我的英语不好。我用 rails 生成了两个模型,一个文章模型和一个图片模型。在图片模型中,我使用 CarrierWave 上传图片。现在我的问题是如何在完成文章表单后将图像保存在数据库 table 中。当我上传图像然后按提交时,表单会保存所有数据,图像除外。我想我的 Article 控制器有问题。 我会为每篇文章保存图片,并使用上传多张图片的表单来完成。上传来自 CarrierWave。但是当我提交表单时,我获得了显示视图,其中包含除图像之外的文章的所有参数(标题、描述等)。我使用多态关联是因为我还需要将图片模型用于其他模型。 文章形式为:
<%= form_for([:admin, @article], html: { class: "form-horizontal", role: "form" }) do |f| %>
<% if @article.errors.any? %>
<div class="alert alert-danger alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h4>
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :article_category_id, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.collection_select :article_category_id, ArticleCategory.all, :id, :name, {}, {class: "form-control"} %>
</div>
</div>
<div class="form-group">
<%= f.label :title, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_field :title, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :description, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_area :description, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :tag_list, "Tag (separati dalla virgola)", class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_field :tag_list, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :pictures, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.file_field :pictures, multiple: true %>
<p>larghezza: 800px - altezza: 800px<br />DPI 72<br />peso inferiore a 50kb<br />tipo file jpg o png (scarica esempio da <%= link_to "qui", "/res/test.jpg", :target => "_blank" %>)</p>
</div>
</div>
<div class="form-group">
<%= f.label :date, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.date_select :date, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :status, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.select :status, options_for_select(Article.statuses.collect{|item, val| [item.humanize, item]}, selected: @article.status), class: "form-control" %>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<%= f.submit class: "btn btn-primary" %>
</div>
</div>
<% end %>
文章负责人是:
class Admin::ArticlesController < Admin::AdminController
include Sortable
before_action :set_article, only: [:show, :edit, :update, :destroy]
# GET /articles
# GET /articles.json
def index
if params[:tag]
@articles = Article.tagged_with(params[:tag])
else
@articles = Article.all
end
end
# GET /articles/1
# GET /articles/1.json
def show
end
# GET /articles/new
def new
@article = Article.new
end
# GET /articles/1/edit
def edit
end
# POST /articles
# POST /articles.json
def create
@article = Article.new(article_params)
respond_to do |format|
if @article.save
format.html { redirect_to [:admin, @article], notice: 'Articolo creato con successo.' }
format.json { render :show, status: :created, location: @article }
else
format.html { render :new }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /articles/1
# PATCH/PUT /articles/1.json
def update
respond_to do |format|
if @article.update(article_params)
format.html { redirect_to [:admin, @article], notice: 'Articolo aggiornato con successo.' }
format.json { render :show, status: :ok, location: @article }
else
format.html { render :edit }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.json
def destroy
@article.destroy
respond_to do |format|
format.html { redirect_to admin_articles_url, notice: 'Articolo eliminato con successo.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
@article = Article.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:article_category_id, :title, :description, :date, :tag_list, :status, :pictures_attributes => [:id, :picturable_type, :picturable_id, :image => []])
end
end
文章型号为:
class Article < ApplicationRecord
acts_as_list
acts_as_taggable_on :tags
belongs_to :article_category
has_many :comments
has_many :pictures, as: :picturable
accepts_nested_attributes_for :pictures
enum status: {bozza: 0, pubblicato: 1}
default_scope {order("position ASC")}
def final_image_url
if self.image.present?
return self.image_url
else
return "/res/no-image.png"
end
end
end
# == Schema Information
#
# Table name: articles
#
# id :integer not null, primary key
# article_category_id :integer
# title :string(255)
# description :text(65535)
# date :date
# created_at :datetime not null
# updated_at :datetime not null
# position :integer
# status :integer
#
图片型号为:
class Picture < ApplicationRecord
belongs_to :picturable, polymorphic: true
mount_uploader :image, ImageUploader
end
# == Schema Information
#
# Table name: pictures
#
# id :integer not null, primary key
# image :string(255)
# picturable_type :string(255)
# picturable_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
上传者设置为:
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process scale: [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_whitelist
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
提前感谢您的帮助。
尝试使用以下代码更改表单代码:-
.................
................
<div class="form-group">
<%= f.label :tag_list, "Tag (separati dalla virgola)", class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.text_field :tag_list, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.fields_for :pictures, f.object.pictures.build do |picture| %>
<label class="col-sm-2 control-label">Image</label>
<div class="col-sm-10">
<%= picture.file_field :image, class: "form-control"%>
<p>larghezza: 800px - altezza: 800px<br />DPI 72<br />peso inferiore a 50kb<br />tipo file jpg o png (scarica esempio da <%= link_to "qui", "/res/test.jpg", :target => "_blank" %>)</p>
</div>
</div>
<div class="form-group">
<%= f.label :date, class: "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= f.date_select :date, class: "form-control" %>
</div>
</div>
..............
..............
并使用以下代码更改您的控制器许可方法:-
def article_params
params.require(:article).permit(:article_category_id, :title, :description, :date, :tag_list, :status, :pictures_attributes => [:id, :image])
end
然后再次尝试提交您的表单...:)