学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

【民泊5.1】【Windows】写真アップロード(paperclip)

ImageMagickをインストールします。


ダウンロードは以下のサイトからできます。
ww.npackd.appspot.com


インストールは以下の手順でお願いします。
途中、「install legacy utilities」と「install development」にチェックを入れて下さい。
mrradiology.hatenablog.jp


続いてGnuWinのインストールを行います。
ダウンロードは以下のサイトからできます。
sourceforge.net


インストールは以下の手順でお願いします。
mrradiology.hatenablog.jp




記述追加 GemFile(66行目)

gem 'paperclip', '~> 5.1.0'



GemFile

source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.7', '>= 5.0.7.1'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

#bootstrap
gem 'bootstrap-sass', '~> 3.4.1'

#デバイス
gem 'devise', '~>4.2'

#Gravatar
gem 'gravtastic'

#フラッシュメッセージ
gem 'toastr-rails', '~> 1.0'

#日本語化
gem 'rails-i18n'

#画像アップロード
gem 'paperclip', '~> 5.1.0'



コマンド
bundle


記述追加 config\environments\development.rb(3行目)

Paperclip.options[:command_path] = "C:\Program Files\ImageMagick-7.0.10-Q16;C:\Program Files (x86)\GetGnuWin32\bin"



config\environments\development.rb

Rails.application.configure do

  #画像アップロード
 Paperclip.options[:command_path] = "C:\Program Files\ImageMagick-7.0.10-Q16;C:\Program Files (x86)\GetGnuWin32\bin"

  # Settings specified here will take precedence over those in config/application.rb.

  # In the development environment your application's code is reloaded on
  # every request. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports.
  config.consider_all_requests_local = true

  # Enable/disable caching. By default caching is disabled.
  if Rails.root.join('tmp/caching-dev.txt').exist?
    config.action_controller.perform_caching = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => 'public, max-age=172800'
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

  # Don't care if the mailer can't send.
  # trueに変更
  config.action_mailer.raise_delivery_errors = true

  config.action_mailer.perform_caching = false

  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log

  # Raise an error on page load if there are pending migrations.
  config.active_record.migration_error = :page_load

  # Debug mode disables concatenation and preprocessing of assets.
  # This option may cause significant delays in view rendering with a large
  # number of complex assets.
  config.assets.debug = true

  # Suppress logger output for asset requests.
  config.assets.quiet = true

  # Raises error for missing translations
  # config.action_view.raise_on_missing_translations = true

  # Use an evented file watcher to asynchronously detect changes in source code,
  # routes, locales, etc. This feature depends on the listen gem.
  # config.file_watcher = ActiveSupport::EventedFileUpdateChecker

  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

  #Gメールの設定
  config.action_mailer.delivery_method = :smtp

  config.action_mailer.smtp_settings = {
    address: "smtp.gmail.com",
    port: 587,
    enable_starttls_auto: true,
    authentication: "plain",
    user_name: 'win.rails.learn@gmail.com',
    password: 'vusopllqzbyvvahk'
  }

end



「config\initializers」フォルダに「paperclip_media_type_spoof_detector_override.rb」ファイルを新規作成します。


config\initializers\paperclip_media_type_spoof_detector_override.rb(新規作成したファイル)

require 'paperclip/media_type_spoof_detector'

module Paperclip
  class MediaTypeSpoofDetector
    def spoofed?
        false
    end
  end
end



コマンド
写真モデルを作成します。
rails g model Photo room:references


コマンド
rails g paperclip photo image


更新
db\migrate\20200628021623_add_attachment_image_to_photos.rb
1行目に[5.0]の記述を追加して下さい。

class AddAttachmentImageToPhotos < ActiveRecord::Migration[5.0]
  def self.up
    change_table :photos do |t|
      t.attachment :image
    end
  end

  def self.down
    remove_attachment :photos, :image
  end
end



コマンド マイグレーション適用
rails db:migrate


app\models\room.rb
「has_many :photos」の記述を追加します。(3行目)

class Room < ApplicationRecord
  belongs_to :user
  has_many :photos

  validates :home_type, presence: true
  validates :room_type, presence: true
  validates :accommodate, presence: true
  validates :bed_room, presence: true
  validates :bath_room, presence: true

end



記述追加 app\models\photo.rb(4・5行目)

class Photo < ApplicationRecord
  belongs_to :room

  has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }
  validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/

end



記述追加 config\routes.rb
「resources :photos, only: [:create, :destroy]」の記述を追加してます。(19行目)

  resources :rooms, except: [:edit] do
    member do
      get 'listing'
      get 'pricing'
      get 'description'
      get 'photo_upload'
      get 'amenities'
      get 'location'
    end
    resources :photos, only: [:create, :destroy]

  end



config\routes.rb

Rails.application.routes.draw do

  #ルートをpages#homeに設定
  root 'pages#home'

  get 'pages/home'

  resources :users, only: [:show]

  resources :rooms, except: [:edit] do
    member do
      get 'listing'
      get 'pricing'
      get 'description'
      get 'photo_upload'
      get 'amenities'
      get 'location'
    end
    resources :photos, only: [:create, :destroy]
  end

  devise_for :users,
  path: '',
  path_names: {sign_in: 'login', sign_out: 'logout', edit: 'profile', sign_up: 'registration'},
  controllers: {registrations: 'registrations'}
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end



「app\controllers」フォルダに「photos_controller.rb」ファイルを新規作成します。


app\controllers\photos_controller.rb(新規作成したファイル)

class PhotosController < ApplicationController

    def create
      @room = Room.find(params[:room_id])
  
      if params[:images]

        params[:images].each do |img|
          @room.photos.create(image: img)
        end
  
        @photos = @room.photos
        redirect_back(fallback_location: request.referer, notice: "保存しました。")
      end
    end
  
end



更新 app\controllers\rooms_controller.rb
「photo_update()」メソッドに「@photos = @room.photos」追加したり(37行目)、「before_action :is_authorised」に「:photo_upload」を追加(4行目)しています。
また、「is_authorised」メソッドの記述(65行目)により部屋登録者以外はアクセスできないようにしています。
内容をそのまま置き換えてください。

class RoomsController < ApplicationController
  before_action :set_room, except: [:index, :new, :create]
  before_action :authenticate_user!, except: [:show]
  before_action :is_authorised, only: [:listing, :pricing, :description, :photo_upload, :amenities, :location, :update]

  def index
     @rooms = current_user.rooms
  end

  def new
    @room = current_user.rooms.build
  end

  def create
    @room = current_user.rooms.build(room_params)
    if @room.save
      redirect_to listing_room_path(@room), notice: "保存しました。"
    else
      flash[:alert] = "問題が発生しました。"
      render :new
    end
  end

  def show
  end

  def listing
  end

  def pricing
  end

  def description
  end

  def photo_upload
      @photos = @room.photos
  end

  def amenities
  end

  def location
  end

  def update

    new_params = room_params
    new_params = room_params.merge(active: true) if is_ready_room

    if @room.update(new_params)
      flash[:notice] = "保存しました。"
    else
      flash[:alert] = "問題が発生しました。"
    end
    redirect_back(fallback_location: request.referer)
  end

  private

    def set_room
      @room = Room.find(params[:id])
    end

    def is_authorised
      redirect_to root_path, alert: "権限がありません。" unless current_user.id == @room.user_id
    end

    def is_ready_room
      !@room.active && !@room.price.blank? && !@room.listing_name.blank? && !@room.photos.blank? && !@room.address.blank?
    end

    def room_params
      params.require(:room).permit(:home_type, :room_type, :accommodate, :bed_room, :bath_room, :listing_name, :summary, :address, :is_tv, :is_kitchen, :is_air, :is_heating, :is_internet, :price, :active)
    end

end



更新 app\views\rooms\photo_upload.html.erb
ファイルを置き換えてください。

<div class="row">
  <div class="col-md-3">
    <%= render 'room_menu' %>
  </div>
  <div class="col-md-9">
    <div class="panel panel-default">

      <div class="panel-heading">
       お写真
      </div>

      <div class="panel-body">
        <div class="container">
          <div class="row">
            <div class="col-md-offset-3 col-md-6">
              <!-- PHOTOS UPLOAD GOES HERE -->

              <%= form_for @room, url: room_photos_path(@room), method: 'post', html: {multipart: true} do |f| %>
                <div class="row">
                  <div class="form-group">
                    <span class="btn btn-default btn-file text-babu">
                      <i class="fa fa-cloud-upload" aria-hidden="true"></i>
                      写真を選択
                      <%= file_field_tag "images[]", type: :file, multiple: true %>
                    </span>
                  </div>
                </div>

                <div class="text-center">
                  <%= f.submit "写真追加", class: "btn btn-normal" %>
                </div>

              <% end %>

            </div>
          </div>
          <div id="photos"><%= render 'photos/photos_list' %></div>

        </div>
      </div>
    </div>
  </div>
</div>



「app\views」フォルダに「photos」フォルダを新規作成します。
作成した「photos」フォルダに「_photos_list.html.erb」ファイルを新規作成します。



app\views\photos\_photos_list.html.erb(新規作成したファイル)

<% if @photos.count > 0 %>
  <br/><br/>

  <div class="row">
    <% @photos.each do |photo| %>
      <div class="col-md-4">
        <div class="panel panel-default">
          <div class="panel-heading preview">
            <%= image_tag photo.image.url() %>
          </div>
        </div>
      </div>
    <% end %>
  </div>
<% end %>



ブラウザ確認
登録したお部屋に写真をアップロードしてみます。
一度ターミナルを起動しなおして下さい。
http://localhost:3000/rooms/1/photo_upload


写真をアップロード
写真をアップロード


アップロード成功
アップロード成功