NoMethodError (undefined method `[]' for #<ImageUploader::UploadedFile:0x007fa12d1def68>):
app/models/photo.rb:7:in `original_created_at'
app/models/photo.rb:11:in `overwrite_created_at_date'
app/controllers/photos_controller.rb:9:in `create'class Photo < ApplicationRecord belongs_to :album before_save :overwrite_created_at_date include ImageUploader::Attachment.new(:image)
def original_created_at DateTime.strptime(self.image[:large].data["metadata"]["exif"]["DateTimeOriginal"], "%Y:%m:%d %H:%M:%S") end
def overwrite_created_at_date self.created_at = self.original_created_at endend
#...
def create @photo = @album.photos.create(photo_params) @photo.album = @album
if @photo.save respond_to do |format| format.js { render layout: false, content_type: 'text/javascript' } end else flash.now[:alert] = 'Error while uploading photo.' endend
#...
require "image_processing/mini_magick"
class ImageUploader < Shrine include ImageProcessing::MiniMagick
plugin :add_metadata plugin :remove_attachment plugin :validation_helpers plugin :pretty_location plugin :processing plugin :versions
Attacher.validate do validate_mime_type_inclusion ['image/jpeg', 'image/png', 'image/gif'] end
add_metadata :exif do |io| MiniMagick::Image.new(io.path).exif end
process(:store) do |io, context| thumb = resize_to_limit!(io.download, 300, 300) small = resize_to_limit!(io.download, 461, 307) medium = resize_to_limit!(io.download, 864, 576) large = resize_to_limit!(io.download, 1440, 960)
{ original: io, large: large, medium: medium, small: small, thumb: thumb } endend#...
def show
@album = Album.find(params[:id])
# Where created_at corresponds to the DateTime the photo was taken on the camera @photos = @album.photos.order("created_at DESC")end
#...require 'active_record'
require "shrine"
require "shrine/storage/file_system"
require "tmpdir"
require "open-uri"
require 'byebug'
require 'mini_magick'
require "image_processing/mini_magick"
# Configure Shrine
Shrine.plugin :activerecord
Shrine.storages = {
cache: Shrine::Storage::FileSystem.new(Dir.tmpdir, prefix: "cache"),
store: Shrine::Storage::FileSystem.new(Dir.tmpdir, prefix: "store"),
}
# Uploader
class PhotoUploader < Shrine
# plugins and uploading logic
include ImageProcessing::MiniMagick
plugin :add_metadata
# plugin :remove_attachment
plugin :validation_helpers
plugin :pretty_location
# plugin :processing
# plugin :versions
plugin :determine_mime_type # <===== 1. Missing this plugin for mime type validation to work
Attacher.validate do
validate_mime_type_inclusion ['image/jpeg', 'image/png', 'image/gif']
end
# 2. You can use your method to extract all Exif data from image and store in the database record
# or only extract needed information i.e. `DateTimeOriginal`
add_metadata :original_created_at do |io|
MiniMagick::Image.new(io.path).exif["DateTimeOriginal"]
end
# 3. When processing images I suggest to resize image from largest to smallest in order and
# use the previous size to generate the next size. Doing this preserves the details, uses less memory,
# and is faster. This may have changed since I tested it.
# I commented this out to simplify test script but this is how I suggest to do it.
# process(:store) do |io, context|
# io = io.download
# large = resize_to_limit!(io, 1440, 960)
# medium = resize_to_limit!(large, 864, 576)
# small = resize_to_limit!(medium, 461, 307)
# thumb = resize_to_limit!(small, 300, 300)
# { original: io, large: large, medium: medium, small: small, thumb: thumb }
# end
end
# Setup database and run migration
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Migration.verbose = false
ActiveRecord::Migration.create_table(:photos) do |t|
t.text :image_data
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
# Model
class Photo < ActiveRecord::Base
include PhotoUploader::Attachment.new(:image)
before_create :overwrite_created_at # only overwrite on create, not on every save
# 2. The image_data metadata is simplified because I only store one timestamp and not the whole Exif data.
def overwrite_created_at
self.created_at = DateTime.strptime(self.image.data["metadata"]["original_created_at"], "%Y:%m:%d %H:%M:%S")
end
# before_save :overwrite_created_at_date # <======= 4. This will overwrite created_at during every save. You only want to do this one time on create shown above.
# def original_created_at
# DateTime.strptime(self.image.data["metadata"]["exif"]["DateTimeOriginal"], "%Y:%m:%d %H:%M:%S")
# end
# def overwrite_created_at_date
# self.created_at = self.original_created_at
# end
end
file = File.new("../test/fixtures/test_big_image.jpg")
photo = Photo.create(image: open(file))
puts JSON(photo.reload.image_data)
# Result =>
# {
# "id" => "photo/1/image/8b592f8cbde40cab0110ff0b62dabefe.jpg",
# "storage" => "store",
# "metadata" => {
# "filename"=>"test_big_image.jpg",
# "size" => 2290163,
# "mime_type" => "image/jpeg",
# "original_created_at" => "2008:03:25 20:48:31"
# }
# }
puts photo.inspect
# Result =>
#<Photo id: 1, image_data: "{\"id\":\"photo/1/image/8b592f8cbde40cab0110ff0b62dab...", created_at: "2008-03-25 20:48:31", updated_at: "2018-01-09 02:10:30">
def original_created_at
DateTime.strptime(self.image[:large].data["metadata"]["exif"]["DateTimeOriginal"], "%Y:%m:%d %H:%M:%S")
end
def original_created_at
DateTime.strptime(self.image.data["metadata"]["exif"]["DateTimeOriginal"], "%Y:%m:%d %H:%M:%S")
end
def original_created_at
DateTime.strptime(self.image.metadata["exif"]["DateTimeOriginal"], "%Y:%m:%d %H:%M:%S")
end
DateTime.strptime(self.image.exif["DateTimeOriginal"], "%Y:%m:%d %H:%M:%S")
end
self.created_at = self.original_created_at if image_attacher.changed?
end
class ImageUploader < Shrine
add_metadata(:exif) { |io| exif(io) }
add_metadata :created_at do |io|
date_time_original = exif(io)["DateTimeOriginal"]
DateTime.strptime(date_time_original, "%Y:%m:%d %H:%M:%S").iso8601 if date_time_original
end
def exif(io)
MiniMagick::Image.new(io.path).exif
end
end
# app/models/photo.rb
class Photo < ApplicationRecord
# ...
before_save :overwrite_created_at_date
def overwrite_created_at_date
self.created_at = Time.iso8601(image.created_at) if image_attacher.changed? && image.created_at
end
end
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/107bbe7d-77bd-4500-82d1-e67d37860b22%40googlegroups.com.--
You received this message because you are subscribed to the Google Groups "Shrine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine+unsubscribe@googlegroups.com.
To post to this group, send email to ruby-...@googlegroups.com.