Rails 4 przesyłanie wielu obrazów lub plików za pomocą carrierwave
Jak mogę przesłać wiele obrazów z okna wyboru plików za pomocą Rails 4 i CarrierWave? Mam model post_controller
i post_attachments
. Jak mogę to zrobić?
6 answers
Jest to rozwiązanie do przesyłania wielu obrazów za pomocą carrierwave w rails 4 od podstaw
Lub można znaleźć demo pracy : Wiele Szyn Mocujących 4
Aby to zrobić, wykonaj następujące kroki.
rails new multiple_image_upload_carrierwave
W pliku gem
gem 'carrierwave'
bundle install
rails generate uploader Avatar
Create Post scaffold
rails generate scaffold post title:string
Create post_attachment
rails generate scaffold post_attachment post_id:integer avatar:string
rake db:migrate
W poczta.rb
class Post < ActiveRecord::Base
has_many :post_attachments
accepts_nested_attributes_for :post_attachments
end
W post_attachment.rb
class PostAttachment < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
belongs_to :post
end
W post_controller.rb
def show
@post_attachments = @post.post_attachments.all
end
def new
@post = Post.new
@post_attachment = @post.post_attachments.build
end
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
params[:post_attachments]['avatar'].each do |a|
@post_attachment = @post.post_attachments.create!(:avatar => a)
end
format.html { redirect_to @post, notice: 'Post was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
private
def post_params
params.require(:post).permit(:title, post_attachments_attributes: [:id, :post_id, :avatar])
end
In views / posts / _form.html.erb
<%= form_for(@post, :html => { :multipart => true }) do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<%= f.fields_for :post_attachments do |p| %>
<div class="field">
<%= p.label :avatar %><br>
<%= p.file_field :avatar, :multiple => true, name: "post_attachments[avatar][]" %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Aby edytować załącznik I listę załączników dla dowolnego posta. In views / posts / show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= @post.title %>
</p>
<% @post_attachments.each do |p| %>
<%= image_tag p.avatar_url %>
<%= link_to "Edit Attachment", edit_post_attachment_path(p) %>
<% end %>
<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>
Update form to edit an attachment views / post_attachments / _form.html.erb
<%= image_tag @post_attachment.avatar %>
<%= form_for(@post_attachment) do |f| %>
<div class="field">
<%= f.label :avatar %><br>
<%= f.file_field :avatar %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Modify Update method in post_attachment_controller.rb
def update
respond_to do |format|
if @post_attachment.update(post_attachment_params)
format.html { redirect_to @post_attachment.post, notice: 'Post attachment was successfully updated.' }
end
end
end
W rails 3 nie ma potrzeby definiowania silnych parametrów i jak można zdefiniować attribute_accessible zarówno w modelu, jak i accept_nested_attribute do modelu post, ponieważ atrybut accessible jest przestarzały w rails 4.
Aby edytować załącznik, nie możemy modyfikować wszystkich załączników na raz. więc będziemy zastępować załącznik jeden po drugim, lub możesz modyfikować zgodnie z Twoją regułą, tutaj po prostu pokażę Ci, jak zaktualizować dowolny załącznik.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-02 04:43:49
Jeśli przyjrzymy się dokumentacji CarrierWave ' a, jest to teraz bardzo proste.
Https://github.com/carrierwaveuploader/carrierwave/blob/master/README.md#multiple-file-uploads
Użyję produktu jako modelu, który chcę dodać zdjęcia, jako przykład.
-
Pobierz master branch Carrier i dodaj go do swojego Gemfile:
gem 'carrierwave', github:'carrierwaveuploader/carrierwave'
-
Utwórz kolumnę w modelu przeznaczonym do hostowania tablicy obrazy:
rails generate migration AddPicturesToProducts pictures:json
-
Uruchom migrację
bundle exec rake db:migrate
-
Dodaj zdjęcia do modelu produktu
app/models/product.rb class Product < ActiveRecord::Base validates :name, presence: true mount_uploaders :pictures, PictureUploader end
-
Dodaj zdjęcia do strong params w ProductsController
app/controllers/products_controller.rb def product_params params.require(:product).permit(:name, pictures: []) end
-
Pozwól formularzowi akceptować wiele zdjęć
app/views/products/new.html.erb # notice 'html: { multipart: true }' <%= form_for @product, html: { multipart: true } do |f| %> <%= f.label :name %> <%= f.text_field :name %> # notice 'multiple: true' <%= f.label :pictures %> <%= f.file_field :pictures, multiple: true, accept: "image/jpeg, image/jpg, image/gif, image/png" %> <%= f.submit "Submit" %> <% end %>
-
W swoich widokach możesz odwoływać się do obrazów przetwarzających tablicę obrazów:
@product.pictures[1].url
Jeśli wybierzesz kilka obrazów z folderu, kolejność będzie dokładna od góry do dołu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-16 22:25:58
Kilka drobnych dodatków do SSR odpowiedź:
Accepts_nested_attributes_for nie wymaga zmiany kontrolera obiektu nadrzędnego. Więc jeśli poprawić
name: "post_attachments[avatar][]"
Do
name: "post[post_attachments_attributes][][avatar]"
Wtedy wszystkie te zmiany kontrolera, takie jak te, stają się zbędne:
params[:post_attachments]['avatar'].each do |a|
@post_attachment = @post.post_attachments.create!(:avatar => a)
end
Należy również dodać PostAttachment.new
do formularza obiektu nadrzędnego:
In views / posts / _form.html.erb
<%= f.fields_for :post_attachments, PostAttachment.new do |ff| %>
<div class="field">
<%= ff.label :avatar %><br>
<%= ff.file_field :avatar, :multiple => true, name: "post[post_attachments_attributes][][avatar]" %>
</div>
<% end %>
To sprawiłoby, że ta zmiana w kontroler rodzica:
@post_attachment = @post.post_attachments.build
Aby uzyskać więcej informacji zobacz Rails fields_for form not showing up, nested form
Jeśli używasz Rails 5, Zmień Rails.application.config.active_record.belongs_to_required_by_default
wartość z true
na false
(w config/initializers/new_framework_defaults.rb) z powodu błędu wewnątrz accepts_nested_attributes_for (w przeciwnym razie accepts_nested_attributes_for generalnie nie będzie działać pod Rails 5).
Edytuj 1:
Aby dodać o :
In models / post.rb
class Post < ApplicationRecord
...
accepts_nested_attributes_for :post_attachments, allow_destroy: true
end
In views / posts / _form.html.erb
<% f.object.post_attachments.each do |post_attachment| %>
<% if post_attachment.id %>
<%
post_attachments_delete_params =
{
post:
{
post_attachments_attributes: { id: post_attachment.id, _destroy: true }
}
}
%>
<%= link_to "Delete", post_path(f.object.id, post_attachments_delete_params), method: :patch, data: { confirm: 'Are you sure?' } %>
<br><br>
<% end %>
<% end %>
W ten sposób po prostu nie musisz mieć kontrolera obiektu potomnego w ogóle! To znaczy, żadne {[12] } nie jest już potrzebne. Jeśli chodzi o kontroler obiektu nadrzędnego (PostController
), ty również prawie nie zmieniasz go - jedyną rzeczą, którą tam zmieniasz, jest lista param na białej liście (aby uwzględnić param powiązane z obiektami podrzędnymi), jak to:
def post_params
params.require(:post).permit(:title, :text,
post_attachments_attributes: ["avatar", "@original_filename", "@content_type", "@headers", "_destroy", "id"])
end
Dlatego accepts_nested_attributes_for
jest tak niesamowity.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:02
Również wymyśliłem, jak zaktualizować przesyłanie wielu plików i trochę go zrefakturowałem. Ten kod jest mój, ale rozumiesz.
def create
@motherboard = Motherboard.new(motherboard_params)
if @motherboard.save
save_attachments if params[:motherboard_attachments]
redirect_to @motherboard, notice: 'Motherboard was successfully created.'
else
render :new
end
end
def update
update_attachments if params[:motherboard_attachments]
if @motherboard.update(motherboard_params)
redirect_to @motherboard, notice: 'Motherboard was successfully updated.'
else
render :edit
end
end
private
def save_attachments
params[:motherboard_attachments]['photo'].each do |photo|
@motherboard_attachment = @motherboard.motherboard_attachments.create!(:photo => photo)
end
end
def update_attachments
@motherboard.motherboard_attachments.each(&:destroy) if @motherboard.motherboard_attachments.present?
params[:motherboard_attachments]['photo'].each do |photo|
@motherboard_attachment = @motherboard.motherboard_attachments.create!(:photo => photo)
end
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-03 06:17:03
Oto mój drugi refaktor do modelu:
- Przenieś prywatne metody do modelu.
- Zastąp @ płytę główną self.
Kontroler:
def create
@motherboard = Motherboard.new(motherboard_params)
if @motherboard.save
@motherboard.save_attachments(params) if params[:motherboard_attachments]
redirect_to @motherboard, notice: 'Motherboard was successfully created.'
else
render :new
end
end
def update
@motherboard.update_attachments(params) if params[:motherboard_attachments]
if @motherboard.update(motherboard_params)
redirect_to @motherboard, notice: 'Motherboard was successfully updated.'
else
render :edit
end
end
W modelu płyty głównej:
def save_attachments(params)
params[:motherboard_attachments]['photo'].each do |photo|
self.motherboard_attachments.create!(:photo => photo)
end
end
def update_attachments(params)
self.motherboard_attachments.each(&:destroy) if self.motherboard_attachments.present?
params[:motherboard_attachments]['photo'].each do |photo|
self.motherboard_attachments.create!(:photo => photo)
end
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-03 19:23:38
Podczas używania asocjacji @post.post_attachments
nie musisz ustawiać post_id
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-05 17:06:13