質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

944閲覧

ruby exifrでexif情報取得時のNoMethodErrorを解消したいです

t.togashi

総合スコア22

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2019/08/11 03:01

前提・実現したいこと

ruby on railsで、災害情報(damages)を記録・収集できるアプリを制作中です。
アプリの機能として、投稿画像が撮影された場所がマップにプロットされるよう、実装を試みています。
画像のEXIFフォーマットから、exifrというgemを使用して緯度・経度を取得してデータベースに保存しようとしており、試しに画像を添付して投稿したところ、NoMethodErrorが発生しました。
このNoMethodErrorの発生理由と、エラー解消方法についてご教示いただきたいです。

発生している問題・エラーメッセージ

NoMethodError in DamagesController#create undefined method `getbyte' for #<EXIFR::JPEG::Reader:0x00007fa1ff6f3940>

該当のソースコード

DamagesController

1class DamagesController < ApplicationController 2 3 def index 4 @damages = Damage.all 5 end 6 7 def new 8 @damage = Damage.new 9 end 10 11 def create 12 require 'exifr/jpeg' 13 @exif = EXIFR::JPEG.new(damage_params[:image]) 14 @damage = Damage.new(damage_params.merge({latitude: @exif.gps_lat, longitude: @exif.gps_lng})) 15 16 if @damage.save 17 redirect_to damages_path, notice: "ユーザー「#{@damage.title}」を登録しました。" 18 else 19 render :new 20 end 21 22 end 23 24 def show 25 @damage = Damage.find(params[:id]) 26 end 27 28 def edit 29 @damage = Damage.find(params[:id]) 30 end 31 32 def update 33 @damage = Damage.find(params[:id]) 34 35 if @damage.update(damage_params) 36 redirect_to damages_path, notice: "ユーザー「#{@damage.title}」を更新しました。" 37 else 38 render :new 39 end 40 end 41 42 def destroy 43 @damage = Damage.find(params[:id]) 44 @damage.destroy 45 redirect_to damages_path, notice: "ユーザー「#{@damage.titile}」を削除しました。" 46 end 47 48 private 49 def damage_params 50 params.require(:damage).permit(:title, :place, :description, :amount, :image).merge(user_id: current_user.id) 51 end 52 53end

DamageModel

1class Damage < ApplicationRecord 2 belongs_to :user 3 has_one_attached :image 4end

form

1= form_with model: damage, local: true do |f| 2 .form-group 3 = f.label :title, 'タイトル' 4 = f.text_field :title, class: 'form-control' 5 .form-group 6 = f.label :place, '場所' 7 = f.text_field :place, class: 'form-control' 8 .form-group 9 = f.label :description, '内容' 10 = f.text_area :description, rows: 10, class: 'form-control' 11 .form-group 12 = f.label :amount, '被害額(円)' 13 = f.text_field :amount, class: 'form-control' 14 .form-group 15 = f.label :image, '写真' 16 = f.file_field :image, class: 'form-control' 17 = f.submit '登録する', class: 'btn btn-primary'

試したこと

エラー文で検索したのですが、'getbyte'に関する定義がないという文章そのものの意味以外の理解ができませんでした。

・画像の投稿には、Active Strageを使用しています。
・gem 'exifr'をインストール済みです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ruby

1undefined method `getbyte' for #<EXIFR::JPEG::Reader:0x00007fa1ff6f3940>

というのは、EXIFR::JPEG::Readerクラスのオブジェクトにgetbyteメソッドがないので、呼び出したらエラーになった、という意味です。

exifrのgemのソースはhttps://github.com/remvee/exifrにあるわけですが、そこでgithubの検索等を使ってgetbyteを探してみると、lib/exifr/jpeg.rbにあるのがわかります。

https://github.com/remvee/exifr/search?q=getbyte&unscoped_q=getbyte

該当するのは以下のところですね。

ruby

1 def examine(io) 2 io = Reader.new(io) 3 4 unless io.getbyte == 0xFF && io.getbyte == 0xD8 # SOI 5 raise MalformedJPEG, "no start of image marker found" 6 end

ここの io.getbyte しているところが怪しいのですが、この examine(io) が使われているところを調べると、 EXIFR::JPEG のinitializeで使っていることがわかります。この ioEXIFR::JPEG.new の引数になるわけですね。なので、結論としては、

ruby

1 @exif = EXIFR::JPEG.new(damage_params[:image])

のところの、引数の渡し方が良くない、ということになりそうです。

考えてみると、ActiveStorageは外部サービスにファイルを載せられるので、Railsが動いているサーバではファイルの中身の情報が直接見られないことがあるわけです。そのため、Railsのサーバ内までダウンロードしてくる必要がありそうです。

https://github.com/remvee/exifr のREADMEの例を見ると、だいたいファイル名を渡しているので、

  • ActiveStorageからダウンロードしてサーバ内にファイルとして保存する
  • そのファイルのパスを EXIFR::JPEG.new に渡す

とするか、引数としてはIOっぽいオブジェクトを受け付けるようなので、

  • ActiveStorageからダウンロードしたデータをStringIOにする
  • そのオブジェクトを EXIFR::JPEG.new に渡す

とすると良さそうです。

投稿2019/08/13 05:59

takahashim

総合スコア1877

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問