mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 01:31:39 -05:00
Use shrine to upload files instead of ActiveStorage
This commit is contained in:
parent
d99e6d6f50
commit
e00f614b9a
14 changed files with 64 additions and 26 deletions
16
Gemfile
16
Gemfile
|
|
@ -5,31 +5,31 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||||
|
|
||||||
ruby '3.2.3'
|
ruby '3.2.3'
|
||||||
gem 'bootsnap', require: false
|
gem 'bootsnap', require: false
|
||||||
|
gem 'chartkick'
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
|
gem 'geocoder'
|
||||||
|
gem 'importmap-rails'
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
gem 'pundit'
|
gem 'pundit'
|
||||||
gem 'rails'
|
gem 'rails'
|
||||||
|
gem 'shrine', '~> 3.5'
|
||||||
|
gem 'sidekiq'
|
||||||
|
gem 'sidekiq-cron'
|
||||||
gem 'sprockets-rails'
|
gem 'sprockets-rails'
|
||||||
gem 'stimulus-rails'
|
gem 'stimulus-rails'
|
||||||
gem 'tailwindcss-rails'
|
gem 'tailwindcss-rails'
|
||||||
gem 'turbo-rails'
|
gem 'turbo-rails'
|
||||||
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
|
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
|
||||||
gem 'importmap-rails'
|
|
||||||
gem 'chartkick'
|
|
||||||
gem 'geocoder'
|
|
||||||
gem 'sidekiq'
|
|
||||||
gem 'sidekiq-cron'
|
|
||||||
|
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'debug', platforms: %i[mri mingw x64_mingw]
|
gem 'debug', platforms: %i[mri mingw x64_mingw]
|
||||||
|
gem 'dotenv-rails'
|
||||||
gem 'factory_bot_rails'
|
gem 'factory_bot_rails'
|
||||||
gem 'ffaker'
|
gem 'ffaker'
|
||||||
gem 'rspec-rails'
|
|
||||||
gem 'dotenv-rails'
|
|
||||||
gem 'pry-byebug'
|
gem 'pry-byebug'
|
||||||
gem 'pry-rails'
|
gem 'pry-rails'
|
||||||
|
gem 'rspec-rails'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
|
|
||||||
10
Gemfile.lock
10
Gemfile.lock
|
|
@ -75,6 +75,8 @@ GEM
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
mutex_m
|
mutex_m
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
|
addressable (2.8.6)
|
||||||
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
ast (2.4.2)
|
ast (2.4.2)
|
||||||
attr_extras (7.1.0)
|
attr_extras (7.1.0)
|
||||||
base64 (0.2.0)
|
base64 (0.2.0)
|
||||||
|
|
@ -88,6 +90,7 @@ GEM
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
concurrent-ruby (1.2.3)
|
concurrent-ruby (1.2.3)
|
||||||
connection_pool (2.4.1)
|
connection_pool (2.4.1)
|
||||||
|
content_disposition (1.0.0)
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
date (3.3.4)
|
date (3.3.4)
|
||||||
debug (1.9.2)
|
debug (1.9.2)
|
||||||
|
|
@ -105,6 +108,8 @@ GEM
|
||||||
dotenv-rails (3.1.0)
|
dotenv-rails (3.1.0)
|
||||||
dotenv (= 3.1.0)
|
dotenv (= 3.1.0)
|
||||||
railties (>= 6.1)
|
railties (>= 6.1)
|
||||||
|
down (5.4.2)
|
||||||
|
addressable (~> 2.8)
|
||||||
drb (2.2.1)
|
drb (2.2.1)
|
||||||
erubi (1.12.0)
|
erubi (1.12.0)
|
||||||
et-orbi (1.2.11)
|
et-orbi (1.2.11)
|
||||||
|
|
@ -189,6 +194,7 @@ GEM
|
||||||
pry (>= 0.10.4)
|
pry (>= 0.10.4)
|
||||||
psych (5.1.2)
|
psych (5.1.2)
|
||||||
stringio
|
stringio
|
||||||
|
public_suffix (5.0.5)
|
||||||
puma (6.4.2)
|
puma (6.4.2)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pundit (2.3.1)
|
pundit (2.3.1)
|
||||||
|
|
@ -285,6 +291,9 @@ GEM
|
||||||
ruby-progressbar (1.13.0)
|
ruby-progressbar (1.13.0)
|
||||||
shoulda-matchers (6.2.0)
|
shoulda-matchers (6.2.0)
|
||||||
activesupport (>= 5.2.0)
|
activesupport (>= 5.2.0)
|
||||||
|
shrine (3.5.0)
|
||||||
|
content_disposition (~> 1.0)
|
||||||
|
down (~> 5.1)
|
||||||
sidekiq (7.2.2)
|
sidekiq (7.2.2)
|
||||||
concurrent-ruby (< 2)
|
concurrent-ruby (< 2)
|
||||||
connection_pool (>= 2.3.0)
|
connection_pool (>= 2.3.0)
|
||||||
|
|
@ -372,6 +381,7 @@ DEPENDENCIES
|
||||||
rspec-rails
|
rspec-rails
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
|
shrine (~> 3.5)
|
||||||
sidekiq
|
sidekiq
|
||||||
sidekiq-cron
|
sidekiq-cron
|
||||||
simplecov
|
simplecov
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -15,13 +15,14 @@ class ImportsController < ApplicationController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
files = import_params[:files].reject(&:blank?)
|
files = import_params[:files].reject(&:blank?)
|
||||||
|
|
||||||
import_ids = files.map do |file|
|
import_ids = files.map do |file|
|
||||||
import = current_user.imports.create(
|
import = current_user.imports.create(
|
||||||
name: file.original_filename,
|
name: file.original_filename,
|
||||||
source: params[:import][:source]
|
source: params[:import][:source]
|
||||||
)
|
)
|
||||||
|
|
||||||
import.file.attach(file)
|
import.update(raw_data: JSON.parse(File.read(file)))
|
||||||
import.id
|
import.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ImportJob < ApplicationJob
|
class ImportJob < ApplicationJob
|
||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(user_id, import_id)
|
def perform(user_id, import_id)
|
||||||
user = User.find(user_id)
|
user = User.find(user_id)
|
||||||
import = user.imports.find(import_id)
|
import = user.imports.find(import_id)
|
||||||
file = import.file
|
|
||||||
|
|
||||||
sleep 3 # It takes time to process uploaded file
|
|
||||||
|
|
||||||
result = parser(import.source).new(import).call
|
result = parser(import.source).new(import).call
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Import < ApplicationRecord
|
class Import < ApplicationRecord
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_many :points, dependent: :destroy
|
has_many :points, dependent: :destroy
|
||||||
|
|
||||||
has_one_attached :file
|
include ImportUploader::Attachment(:raw)
|
||||||
|
|
||||||
enum source: { google: 0, owntracks: 1 }
|
enum source: { google: 0, owntracks: 1 }
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class GoogleMaps::TimelineParser
|
class GoogleMaps::TimelineParser
|
||||||
attr_reader :import, :json
|
attr_reader :import
|
||||||
|
|
||||||
def initialize(import)
|
def initialize(import)
|
||||||
@import = import
|
@import = import
|
||||||
@json = JSON.parse(import.file.download)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
|
|
@ -38,7 +37,7 @@ class GoogleMaps::TimelineParser
|
||||||
private
|
private
|
||||||
|
|
||||||
def parse_json
|
def parse_json
|
||||||
json['timelineObjects'].flat_map do |timeline_object|
|
import.raw_data['timelineObjects'].flat_map do |timeline_object|
|
||||||
if timeline_object['activitySegment'].present?
|
if timeline_object['activitySegment'].present?
|
||||||
if timeline_object['activitySegment']['startLocation'].blank?
|
if timeline_object['activitySegment']['startLocation'].blank?
|
||||||
next if timeline_object['activitySegment']['waypointPath'].blank?
|
next if timeline_object['activitySegment']['waypointPath'].blank?
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ class OwnTracks::ExportParser
|
||||||
|
|
||||||
def initialize(import)
|
def initialize(import)
|
||||||
@import = import
|
@import = import
|
||||||
@json = JSON.parse(import.file.download)
|
@json = import.raw_data
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
|
|
@ -32,7 +32,7 @@ class OwnTracks::ExportParser
|
||||||
doubles = points_data.size - points
|
doubles = points_data.size - points
|
||||||
processed = points + doubles
|
processed = points + doubles
|
||||||
|
|
||||||
{ raw_points: points_data.size, points: points, doubles: doubles, processed: processed }
|
{ raw_points: points_data.size, points:, doubles:, processed: }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
@ -40,8 +40,8 @@ class OwnTracks::ExportParser
|
||||||
def parse_json
|
def parse_json
|
||||||
points = []
|
points = []
|
||||||
|
|
||||||
json.keys.each do |user|
|
json.each_key do |user|
|
||||||
json[user].keys.each do |devise|
|
json[user].each_key do |devise|
|
||||||
json[user][devise].each { |point| points << OwnTracks::Params.new(point).call }
|
json[user][devise].each { |point| points << OwnTracks::Params.new(point).call }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
5
app/uploaders/import_uploader.rb
Normal file
5
app/uploaders/import_uploader.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ImportUploader < Shrine
|
||||||
|
# plugins and uploading logic
|
||||||
|
end
|
||||||
13
config/shrine.rb
Normal file
13
config/shrine.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'shrine'
|
||||||
|
require 'shrine/storage/file_system'
|
||||||
|
|
||||||
|
Shrine.storages = {
|
||||||
|
cache: Shrine::Storage::FileSystem.new('public', prefix: 'uploads/cache'), # temporary
|
||||||
|
store: Shrine::Storage::FileSystem.new('public', prefix: 'uploads') # permanent
|
||||||
|
}
|
||||||
|
|
||||||
|
Shrine.plugin :activerecord # loads Active Record integration
|
||||||
|
Shrine.plugin :cached_attachment_data # enables retaining cached file across form redisplays
|
||||||
|
Shrine.plugin :restore_cached_data # extracts metadata for assigned cached files
|
||||||
5
db/migrate/20240425200155_add_raw_data_to_imports.rb
Normal file
5
db/migrate/20240425200155_add_raw_data_to_imports.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddRawDataToImports < ActiveRecord::Migration[7.1]
|
||||||
|
def change
|
||||||
|
add_column :imports, :raw_data, :jsonb
|
||||||
|
end
|
||||||
|
end
|
||||||
3
db/schema.rb
generated
3
db/schema.rb
generated
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.1].define(version: 2024_04_04_154959) do
|
ActiveRecord::Schema[7.1].define(version: 2024_04_25_200155) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
|
|
@ -51,6 +51,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_04_04_154959) do
|
||||||
t.integer "raw_points", default: 0
|
t.integer "raw_points", default: 0
|
||||||
t.integer "doubles", default: 0
|
t.integer "doubles", default: 0
|
||||||
t.integer "processed", default: 0
|
t.integer "processed", default: 0
|
||||||
|
t.jsonb "raw_data"
|
||||||
t.index ["source"], name: "index_imports_on_source"
|
t.index ["source"], name: "index_imports_on_source"
|
||||||
t.index ["user_id"], name: "index_imports_on_user_id"
|
t.index ["user_id"], name: "index_imports_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory :import do
|
factory :import do
|
||||||
user
|
user
|
||||||
name { 'APRIL_2013.json' }
|
name { 'APRIL_2013.json' }
|
||||||
source { 1 }
|
source { 1 }
|
||||||
|
raw_data { JSON.parse(File.read('spec/fixtures/files/owntracks/export.json')) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe OwnTracks::ExportParser do
|
RSpec.describe OwnTracks::ExportParser do
|
||||||
describe '#call' do
|
describe '#call' do
|
||||||
subject(:parser) { described_class.new(import).call }
|
subject(:parser) { described_class.new(import).call }
|
||||||
|
|
||||||
let(:file_path) { 'spec/fixtures/files/owntracks/export.json' }
|
|
||||||
let(:file) { fixture_file_upload(file_path) }
|
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
let(:import) { create(:import, user: user, file: file, name: File.basename(file.path)) }
|
let(:import) { create(:import, user:, name: 'owntracks_export.json') }
|
||||||
|
|
||||||
context 'when file exists' do
|
context 'when file exists' do
|
||||||
it 'creates points' do
|
it 'creates points' do
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue