لنفرض لدينا تطبيق ذو البنية التالية:

نموذج للتدوينات Post ونموذج آخر للصور Image العلاقة بينهما (كل تدوينة واحدة تمتلك عدة صورة - Post has_may: images)
نموذج الصور يحتوي على صورة واحدة image والتي هي paperclip attachment.
الذي نريده حاليا هو معرفة طريقة لرفع عدة صور مباشرة عند إنشاء التدوينة وهذا ما سيتم توضيحه ضمن هذه التدوينة وفقا للخطوات التالية:

1- إنشاء تطبيق Rails
2- تنصيب الجيم papperclip ضمن التطبيق
3- توليد نموذج Post
4- توليد نموذج Image
5- تخصيص controller & views

1- إنشاء تطبيق Rails

عبر تنفيذ التعليمة التالية:

rails new demo_app

2- تنصيب الجيم papperclip ضمن التطبيق

  • الجيم paperclip تعتمد على imagemagick لذا يجب تنصيبها ضمن نظام التشغيل ليمكن استخدامها
sudo apt-get install imagemagick -y
  • إضافة الجيم papperclip إلى ملف Gemfile
gem 'paperclip'

ثم نطبق تعليمة bundle install

3- توليد نموذج Post

rails g scaffold post title:string body:text  --skip-assets

app/models/post.rb

class Post < ApplicationRecord
	has_many :images, :dependent => :destroy
end

4- توليد نموذج Image

rails g model Image image:attachment post_id:integer
rake db:migrate

app/models/image.rb

class Image < ApplicationRecord
	belongs_to :post

	# paperclip attachment
	has_attached_file :image,
       :path => ":rails_root/public/images/:id/:filename",
       :url  => "/images/:id/:filename"
       styles: { large: '1200x600>', thumb: '200x120>' }
       #paperclip validation
      validates_attachment :image,presence: true,
      content_type: { content_type: ["image/jpeg", "image/gif", "image/png"]},
      size: { in: 0..3.megabytes }	
end

4- تخصيص controller & views

الفكرة حاليا تتخلص بالتالي:

  • تمرير جميع الصور المراد رفعها دفعة واحدة عبر حقل input إلى مصفوقة ولتكن images[] وذلك ضمن الفورم الخاص بالنموذج Post كالتالي:

app/views/posts/_form.html.erb

<%= form_for @post, :html => { :class => 'form-horizontal', multipart: true } do |f| %>
  <div class="control-group">
    <%= f.label :title, :class => 'control-label' %>
    <div class="controls">
      <%= f.text_field :title, :class => 'text_field' %>
    </div>
  </div>
  <div class="control-group">
    <%= f.label :body, :class => 'control-label' %>
    <div class="controls">
      <%= f.area_field :body, :class => 'text_field' %>
    </div>
  </div>

  <div class="control-group">
    <%= f.label :images, :class => 'control-label' %>
    <div class="controls">
      <%= file_field_tag "images[]", type: :file, multiple: true %>
    </div>
  </div>

  <div class="form-actions">
    <%= f.submit nil, :class => 'btn btn-primary' %>
  </div>
<% end %>

تم إضافة خاصية HTML5 multipart إلى الفورم لكي نتمكن من تحديد عدة عناصر(صور) ضمن input وتخزينها ضمن المصفوفة images[] وتمريرها إلى post_controller

ايضا استخدمنا التابع file_field_tag لان images[] ليست Post attribute من معاملات النموذج Post

  • اخيرا تمرير مصفوفة الصور إلى create ضمن post_controller.rb لإنشائها بعد حفظ post

app/controllers/post_controller.rb

def create
  @post = Post.new(post_params)

  respond_to do |format|
    if @post.save
     
      if params[:images]
        params[:images].each { |image|
          @post.images.create(image: image)
        }
      end

      format.html { redirect_to @post, notice: 'Post was successfully created.' }
      format.json { render json: @post, status: :created, location: @post }
    else
      format.html { render action: "new" }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

الوسوم:

التصنيفات:

آخر تعديل: