masaya7 / museum_app

0 stars 0 forks source link

投稿された画像に'額縁.png'を合成して、index.htmlに表示したい #55

Open masaya7 opened 1 year ago

masaya7 commented 1 year ago

実現したいこと

投稿された画像に'額縁.png'を合成して、index.htmlに表示したい

実現に向けて考えていること

コード

デバッグしたもの

  ↳ app/controllers/posts_controller.rb:16:in `create'
  Post Create (0.7ms)  INSERT INTO "posts" ("image", "body", "user_id", "created_at", "updated_at", "status", "title", "compose_image") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["image", "hipo.jpg"], ["body", "ssss"], ["user_id", 1], ["created_at", "2023-08-27 14:21:30.008567"], ["updated_at", "2023-08-27 14:21:30.008567"], ["status", 0], ["title", "sssss"], ["compose_image", nil]]
  ↳ app/controllers/posts_controller.rb:16:in `create'
[38, 45] in ~/workspace/runteq/museum_app/app/models/post.rb
    38|     # 合成した画像を保存する
    39|     output_path = Rails.root.join("public/uploads/post/image/#{Time.now.to_i}.png").to_s
    40|     result.write(output_path)
    41|   
    42|     self.compose_image = output_path # 合成した画像のパスをインスタンス変数に保存
=>  43|     binding.break
    44|   end
    45| end
=>#0    Post#add_frame at ~/workspace/runteq/museum_app/app/models/post.rb:43
  #1    block {|target=#<Post:0x000000010a5b0968 id: 16, image:..., value=16, block=nil|} in make_lambda at ~/workspace/runteq/museum_app/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.6/lib/active_support/callbacks.rb:400
  # and 121 frames (use `bt' command for all frames)
(ruby) input_path
"/Users/usuimasaya/workspace/runteq/museum_app/public/uploads/tmp/1693146089-339719031158506-0001-9060/hipo.jpg"
(ruby) frame_path
"app/assets/images/額縁.png"
(ruby) image 
#<MiniMagick::Image:0x0000000109597540
 @info=
  #<MiniMagick::Image::Info:0x00000001095974a0
   @info=
    {"raw:%m %w %h %b"=>"JPEG 200 200 8.3Ki",
     "format"=>"JPEG",
     "width"=>200,
     "height"=>200,
     "dimensions"=>[200, 200],
     "size"=>8535,
     "human_size"=>"8.3Ki"},
   @path="/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-lse547.jpg">,
 @path="/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-lse547.jpg",
 @tempfile=#<File:/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-lse547.jpg (closed)>>
(ruby) MiniMagick::Image.open(frame_path)
#<MiniMagick::Image:0x00000001061435a0
 @info=
  #<MiniMagick::Image::Info:0x0000000106143550
   @info={},
   @path="/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-1pfbk4.png">,
 @path="/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-1pfbk4.png",
 @tempfile=#<File:/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-1pfbk4.png (closed)>>
(rdbg) result
#<MiniMagick::Image:0x000000010955b8d8
 @info=
  #<MiniMagick::Image::Info:0x000000010955b8b0
   @info={},
   @path="/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-6t6qyw.jpeg">,
 @path="/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-6t6qyw.jpeg",
 @tempfile=#<File:/var/folders/jm/2s2t39653ws9p0n_nygtfw8h0000gn/T/mini_magick20230827-77263-6t6qyw.jpeg (closed)>>
(ruby) output_path
"/Users/usuimasaya/workspace/runteq/museum_app/public/uploads/post/image/1693146090.png"
(ruby) self.compose_image
"/Users/usuimasaya/workspace/runteq/museum_app/public/uploads/post/image/1693146090.png"
(rdbg) exit

imageuploder.rb

class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  process resize_to_limit: [200, 200]

  # Choose what kind of storage to use for this uploader:
  if Rails.env.development?
    storage :file
  elsif Rails.env.test?
    storage :file
  else
    storage :fog
  end

  # 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
    'sample.jpg'
  end

  # Add an allowlist 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
end

index.html.erb

<h3 class="page-header"></h3>
<ul class="post-group">
  <% @posts.each do |post| %>
    <ul class="post-group-item">
      <div class="item-left">
        <li class="image">
          <div class="frame-image">
            <%= image_tag post.compose_image.url , size: "120x160", class: "content-image" %>
          </div>
        </li>
      </div>
      <div class="item-right">
        <li class="title">
          <%="題名:" + post.title.truncate(15) %>
        </li>
        <li class="body">
          <%= post.body.truncate(100) %>
          <%= link_to "詳しく読む", post_path(post.id) %>
        </li>
        <li class="button">
          <%= render "posts/btn", post: post %>
        </li>
      </div>
    </ul>
  <% end %>
  <%= paginate @posts, theme: 'bootstrap-5' %>
</ul>

postscontroller

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  def index
    @posts = Post.published.order(created_at: :desc).page(params[:page]).per(10)
  end

  def show;end

  def new
    @post =Post.new
  end

  def create
    @post = current_user.posts.build(new_post_params)
    if @post.save
      redirect_to index_path
    else
      @post = Post.new(new_post_params)
      flash.now[:danger] = "未入力があります。写真、題名、投稿内容すべて入力してください。下書きにするときも何か入れてください"
      render 'new'
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:body, :image, :status, :title, :empathy,:compose_image)
  end

  def new_post_params
    params.require(:post).permit(:body, :image, :title,:status,:compose_image)
  end
end

post.rb

class Post < ApplicationRecord
  mount_uploader :image, ImageUploader
  after_create :add_frame

  belongs_to :user, foreign_key: "user_id", class_name: "User"
  has_many :empathies
  has_one_attached :image
  attr_accessor :composed_image_path

  validates :title, presence: true, length: { maximum: 50 }
  validates :body, presence: true, length: { maximum: 4000 }
  validates :image, presence: true

  enum status: { published: 0, draft: 1 }

  def empathize_by?(user)
    empathies.where(user_id: user.id).exists?
  end

  private

  def add_frame
    # 投稿画像のパス
    input_path = image.path
    # 額縁画像のパス
    frame_path = 'app/assets/images/額縁.png'

    # 投稿画像を読み込む
    image = MiniMagick::Image.open(input_path)
    # 額縁画像を読み込む
    frame = MiniMagick::Image.open(frame_path)

    # 投稿画像と額縁画像を合成する
    result = image.composite(frame) do |c|
      c.compose "Over"
    end

    # 合成した画像を保存する
    output_path = Rails.root.join("public/uploads/post/image/#{Time.now.to_i}.png").to_s
    result.write(output_path)

    self.compose_image = output_path # 合成した画像のパスをインスタンス変数に保存
    binding.break
  end
end
tmtkzk0823 commented 1 year ago

こちら、現状で、

  1. 合成はできている(データは保存できている)が、index.htmlに表示ができない。
  2. 合成ができておらず(合成したデータが保存できていない)かつ、index.htmlに表示もできていない。

1.2どちらの状況か教えていただいてもよろしいですか?

masaya7 commented 1 year ago

ご返信遅くなり申し訳ございません。 1の合成はできているが表示できない状況です。

postモデルで以下の通り合成した画像が保存できています。合成された画像も確認しました。 しかし、当初の想定であったcompose_imageカラムには保存されていないです。

(ruby) self.compose_image
"/Users/usuimasaya/workspace/runteq/museum_app/public/uploads/post/image/1693146090.png"
tmtkzk0823 commented 1 year ago

ありがとうございます。 画像を合成ができているのであれば、posts_controller.rbcreateアクションに記載してある @post = current_user.posts.build(new_post_params)の@postに期待した画像の値が入っているかdebugしてみると良さそうです。

期待した値が無ければ、ストロングパラメーター(new_post_params)の:compose_imageに画像の値を渡すにはどうしたらいいか考えてみるといいかもです。

masaya7 commented 1 year ago

ありがとうございます。 new_post_paramsに値を入れ、表示することができました。