मैं रेल्स 4 और कैरियरवे का उपयोग करके फ़ाइल चयन विंडो से कई छवियां कैसे अपलोड कर सकता हूं? मैं एक है post_controller
और post_attachments
मॉडल। मैं यह कैसे कर सकता हूँ?
क्या कोई उदाहरण दे सकता है? क्या इसका कोई सरल तरीका है?
जवाबों:
यह खरोंच से 4 पटरियों में वाहक का उपयोग करके कई छवियों को अपलोड करने का समाधान है
या आप कार्यशील डेमो पा सकते हैं: मल्टीपल अटैचमेंट रेल 4
इन चरणों का पालन करने के लिए।
rails new multiple_image_upload_carrierwave
मणि फ़ाइल में
gem 'carrierwave'
bundle install
rails generate uploader Avatar
पोस्ट मचान बनाएं
rails generate scaffold post title:string
पोस्ट_टैचमेंट मचान बनाएं
rails generate scaffold post_attachment post_id:integer avatar:string
rake db:migrate
Post.rb में
class Post < ActiveRecord::Base
has_many :post_attachments
accepts_nested_attributes_for :post_attachments
end
Post_attachment.rb में
class PostAttachment < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
belongs_to :post
end
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
विचारों / पदों / _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 %>
किसी भी पोस्ट के लिए अटैचमेंट और लिस्ट को एडिट करना। विचारों / पोस्ट / 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 %>
अनुलग्नक दृश्य / पोस्ट_टैचमेंट / _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 %>
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
रेल में 3 को मजबूत मापदंडों को परिभाषित करने की आवश्यकता नहीं है और जैसा कि आप मॉडल में दोनों में attribute_accessible को परिभाषित कर सकते हैं और मॉडल पोस्ट करने के लिए accept_nested_attribute क्योंकि 4 में विशेषता सुलभ पदावनत है।
अनुलग्नक संपादित करने के लिए हम एक बार में सभी अनुलग्नकों को संशोधित नहीं कर सकते। इसलिए हम अनुलग्नक को एक-एक करके बदल देंगे, या आप अपने नियम के अनुसार संशोधित कर सकते हैं, यहाँ मैं आपको केवल दिखाता हूँ कि किसी भी अनुलग्नक को कैसे अपडेट किया जाए।
create
कार्रवाई में प्रत्येक पोस्ट अटैचमेंट के माध्यम से लूपिंग क्यों करते हैं ? स्वचालित रूप से संग्रह सहेजने के लिए रेल और कैरियरवाहक पर्याप्त स्मार्ट हैं।
:_destroy
भाग को संभालना )
यदि हम CarrierWave के प्रलेखन पर एक नज़र डालें, तो यह वास्तव में अब बहुत आसान है।
https://github.com/carrierwaveuploader/carrierwave/blob/master/README.md#multiple-file-uploads
मैं उत्पाद का उपयोग उस मॉडल के रूप में करूंगा जिसे मैं चित्रों को जोड़ना चाहता हूं, उदाहरण के रूप में।
मास्टर ब्रांच कैरियरवे को प्राप्त करें और इसे अपने जेमफाइल में जोड़ें:
gem 'carrierwave', github:'carrierwaveuploader/carrierwave'
छवियों का एक सरणी होस्ट करने के लिए इच्छित मॉडल में एक स्तंभ बनाएँ:
rails generate migration AddPicturesToProducts pictures:json
माइग्रेशन चलाएं
bundle exec rake db:migrate
मॉडल उत्पाद में चित्र जोड़ें
app/models/product.rb
class Product < ActiveRecord::Base
validates :name, presence: true
mount_uploaders :pictures, PictureUploader
end
ProductsController में मजबूत params के लिए चित्रों को जोड़ें
app/controllers/products_controller.rb
def product_params
params.require(:product).permit(:name, pictures: [])
end
अपने फ़ॉर्म को कई चित्रों को स्वीकार करने की अनुमति दें
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 %>
आपके विचार में, आप चित्रों को पार्स करने वाले चित्रों को संदर्भित कर सकते हैं:
@product.pictures[1].url
यदि आप किसी फ़ोल्डर से कई छवियां चुनते हैं, तो आदेश सटीक क्रम होगा जिसे आप उन्हें ऊपर से नीचे तक ले जा रहे हैं।
UndefinedConversionError ("\x89" from ASCII-8BIT to UTF-8)
SSR समाधान के लिए, यह ठीक काम करता है 4.xx रेल्स, लेकिन मुझे चुनौतियों का सामना करना पड़ रहा है (पटरियों 5.xx के साथ) यानी ActionDispatch::Http::UploadedFile
फाइलनाम के बजाय डेटाबेस में इसका भंडारण । यह भी अपलोडर में दिए गए पथ के लिए सार्वजनिक फ़ोल्डर में फ़ाइलों को संग्रहीत नहीं कर रहा है।
SSR के उत्तर में कुछ मामूली जोड़ :
ac Accept_nested_attributes_for आपको मूल ऑब्जेक्ट के नियंत्रक को बदलने की आवश्यकता नहीं है। तो अगर सही करने के लिए
name: "post_attachments[avatar][]"
सेवा
name: "post[post_attachments_attributes][][avatar]"
फिर ये सभी नियंत्रक परिवर्तन जैसे ये निरर्थक हो जाते हैं:
params[:post_attachments]['avatar'].each do |a|
@post_attachment = @post.post_attachments.create!(:avatar => a)
end
इसके अलावा, आपको PostAttachment.new
मूल ऑब्जेक्ट फॉर्म में जोड़ना चाहिए :
विचारों / पदों / _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 %>
यह अभिभावक के नियंत्रक में इस बदलाव को बेमानी करेगा:
@post_attachment = @post.post_attachments.build
अधिक जानकारी के लिए Rails फ़ील्ड्स देखें। ऐसा फ़ॉर्म दिखाई नहीं देगा, नेस्टेड फ़ॉर्म
आप रेल 5 का उपयोग करते हैं, तो बदलने Rails.application.config.active_record.belongs_to_required_by_default
से मूल्य true
के लिए false
(में config / initializers / new_framework_defaults.rb) एक बग के अंदर की वजह से accepts_nested_attributes_for (अन्यथा accepts_nested_attributes_for होगा आम तौर पर रेल 5 के तहत नहीं काम)।
संपादित करें 1:
विनाश के बारे में जोड़ने के लिए :
मॉडल / पोस्ट.आरबी में
class Post < ApplicationRecord
...
accepts_nested_attributes_for :post_attachments, allow_destroy: true
end
विचारों / पदों / _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 %>
इस तरह से आपको बस चाइल्ड ऑब्जेक्ट के नियंत्रक होने की आवश्यकता नहीं है ! मेरा मतलब है कि अब किसी PostAttachmentsController
की जरूरत नहीं है। माता-पिता ऑब्जेक्ट के नियंत्रक ( PostController
) के लिए, आप भी इसे लगभग नहीं बदलते हैं - केवल एक चीज जिसे आप वहां बदलते हैं, इस तरह से श्वेतसूचीबद्ध पाराम्स (बच्चे के ऑब्जेक्ट से संबंधित पार्म्स को शामिल करने की सूची) है:
def post_params
params.require(:post).permit(:title, :text,
post_attachments_attributes: ["avatar", "@original_filename", "@content_type", "@headers", "_destroy", "id"])
end
इसीलिए accepts_nested_attributes_for
यह इतना अद्भुत है।
<%= d.text_field :copyright, name: "album[diapos_attributes][][copyright]", class: 'form-field' %>
कॉपीराइट को केवल पिछले रिकॉर्ड के लिए लिखते हैं और उन सभी को नहीं।
इसके अलावा मैंने यह भी पता लगाया कि एकाधिक फ़ाइल अपलोड को कैसे अपडेट किया जाए और मैंने इसे थोड़ा सा रिफ्लेक्ट किया। यह कोड मेरा है लेकिन आपको बहाव मिलता है।
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
यहाँ मॉडल में मेरा दूसरा रिफ्लेक्टर है:
नियंत्रक:
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
मदरबोर्ड मॉडल में:
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
एसोसिएशन का उपयोग करते समय @post.post_attachments
आपको सेट करने की आवश्यकता नहीं है post_id
।