mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 01:01: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'
|
||||
gem 'bootsnap', require: false
|
||||
gem 'chartkick'
|
||||
gem 'devise'
|
||||
gem 'geocoder'
|
||||
gem 'importmap-rails'
|
||||
gem 'pg'
|
||||
gem 'puma'
|
||||
gem 'pundit'
|
||||
gem 'rails'
|
||||
gem 'shrine', '~> 3.5'
|
||||
gem 'sidekiq'
|
||||
gem 'sidekiq-cron'
|
||||
gem 'sprockets-rails'
|
||||
gem 'stimulus-rails'
|
||||
gem 'tailwindcss-rails'
|
||||
gem 'turbo-rails'
|
||||
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
|
||||
gem 'debug', platforms: %i[mri mingw x64_mingw]
|
||||
gem 'dotenv-rails'
|
||||
gem 'factory_bot_rails'
|
||||
gem 'ffaker'
|
||||
gem 'rspec-rails'
|
||||
gem 'dotenv-rails'
|
||||
gem 'pry-byebug'
|
||||
gem 'pry-rails'
|
||||
gem 'rspec-rails'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
|
|
|||
10
Gemfile.lock
10
Gemfile.lock
|
|
@ -75,6 +75,8 @@ GEM
|
|||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
tzinfo (~> 2.0)
|
||||
addressable (2.8.6)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
ast (2.4.2)
|
||||
attr_extras (7.1.0)
|
||||
base64 (0.2.0)
|
||||
|
|
@ -88,6 +90,7 @@ GEM
|
|||
coderay (1.1.3)
|
||||
concurrent-ruby (1.2.3)
|
||||
connection_pool (2.4.1)
|
||||
content_disposition (1.0.0)
|
||||
crass (1.0.6)
|
||||
date (3.3.4)
|
||||
debug (1.9.2)
|
||||
|
|
@ -105,6 +108,8 @@ GEM
|
|||
dotenv-rails (3.1.0)
|
||||
dotenv (= 3.1.0)
|
||||
railties (>= 6.1)
|
||||
down (5.4.2)
|
||||
addressable (~> 2.8)
|
||||
drb (2.2.1)
|
||||
erubi (1.12.0)
|
||||
et-orbi (1.2.11)
|
||||
|
|
@ -189,6 +194,7 @@ GEM
|
|||
pry (>= 0.10.4)
|
||||
psych (5.1.2)
|
||||
stringio
|
||||
public_suffix (5.0.5)
|
||||
puma (6.4.2)
|
||||
nio4r (~> 2.0)
|
||||
pundit (2.3.1)
|
||||
|
|
@ -285,6 +291,9 @@ GEM
|
|||
ruby-progressbar (1.13.0)
|
||||
shoulda-matchers (6.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
shrine (3.5.0)
|
||||
content_disposition (~> 1.0)
|
||||
down (~> 5.1)
|
||||
sidekiq (7.2.2)
|
||||
concurrent-ruby (< 2)
|
||||
connection_pool (>= 2.3.0)
|
||||
|
|
@ -372,6 +381,7 @@ DEPENDENCIES
|
|||
rspec-rails
|
||||
rubocop-rails
|
||||
shoulda-matchers
|
||||
shrine (~> 3.5)
|
||||
sidekiq
|
||||
sidekiq-cron
|
||||
simplecov
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -15,13 +15,14 @@ class ImportsController < ApplicationController
|
|||
|
||||
def create
|
||||
files = import_params[:files].reject(&:blank?)
|
||||
|
||||
import_ids = files.map do |file|
|
||||
import = current_user.imports.create(
|
||||
name: file.original_filename,
|
||||
source: params[:import][:source]
|
||||
)
|
||||
|
||||
import.file.attach(file)
|
||||
import.update(raw_data: JSON.parse(File.read(file)))
|
||||
import.id
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ImportJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(user_id, import_id)
|
||||
user = User.find(user_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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Import < ApplicationRecord
|
||||
belongs_to :user
|
||||
has_many :points, dependent: :destroy
|
||||
|
||||
has_one_attached :file
|
||||
include ImportUploader::Attachment(:raw)
|
||||
|
||||
enum source: { google: 0, owntracks: 1 }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GoogleMaps::TimelineParser
|
||||
attr_reader :import, :json
|
||||
attr_reader :import
|
||||
|
||||
def initialize(import)
|
||||
@import = import
|
||||
@json = JSON.parse(import.file.download)
|
||||
end
|
||||
|
||||
def call
|
||||
|
|
@ -38,7 +37,7 @@ class GoogleMaps::TimelineParser
|
|||
private
|
||||
|
||||
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']['startLocation'].blank?
|
||||
next if timeline_object['activitySegment']['waypointPath'].blank?
|
||||
|
|
@ -61,7 +60,7 @@ class GoogleMaps::TimelineParser
|
|||
end
|
||||
elsif timeline_object['placeVisit'].present?
|
||||
if timeline_object['placeVisit']['location']['latitudeE7'].present? &&
|
||||
timeline_object['placeVisit']['location']['longitudeE7'].present?
|
||||
timeline_object['placeVisit']['location']['longitudeE7'].present?
|
||||
{
|
||||
latitude: timeline_object['placeVisit']['location']['latitudeE7'].to_f / 10**7,
|
||||
longitude: timeline_object['placeVisit']['location']['longitudeE7'].to_f / 10**7,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class OwnTracks::ExportParser
|
|||
|
||||
def initialize(import)
|
||||
@import = import
|
||||
@json = JSON.parse(import.file.download)
|
||||
@json = import.raw_data
|
||||
end
|
||||
|
||||
def call
|
||||
|
|
@ -32,7 +32,7 @@ class OwnTracks::ExportParser
|
|||
doubles = points_data.size - points
|
||||
processed = points + doubles
|
||||
|
||||
{ raw_points: points_data.size, points: points, doubles: doubles, processed: processed }
|
||||
{ raw_points: points_data.size, points:, doubles:, processed: }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -40,8 +40,8 @@ class OwnTracks::ExportParser
|
|||
def parse_json
|
||||
points = []
|
||||
|
||||
json.keys.each do |user|
|
||||
json[user].keys.each do |devise|
|
||||
json.each_key do |user|
|
||||
json[user].each_key do |devise|
|
||||
json[user][devise].each { |point| points << OwnTracks::Params.new(point).call }
|
||||
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.
|
||||
|
||||
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
|
||||
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 "doubles", default: 0
|
||||
t.integer "processed", default: 0
|
||||
t.jsonb "raw_data"
|
||||
t.index ["source"], name: "index_imports_on_source"
|
||||
t.index ["user_id"], name: "index_imports_on_user_id"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :import do
|
||||
user
|
||||
name { 'APRIL_2013.json' }
|
||||
source { 1 }
|
||||
raw_data { JSON.parse(File.read('spec/fixtures/files/owntracks/export.json')) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe OwnTracks::ExportParser do
|
||||
describe '#call' do
|
||||
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(: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
|
||||
it 'creates points' do
|
||||
|
|
|
|||
Loading…
Reference in a new issue