pg_cron 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +25 -0
  3. data/CHANGELOG.md +56 -0
  4. data/Gemfile +8 -0
  5. data/Gemfile.lock +121 -0
  6. data/LICENSE +21 -0
  7. data/README.md +54 -0
  8. data/Rakefile +16 -0
  9. data/bin/console +15 -0
  10. data/bin/increment-version +37 -0
  11. data/bin/release-gem +32 -0
  12. data/bin/setup +8 -0
  13. data/lib/generators/pg_cron/job/USAGE +19 -0
  14. data/lib/generators/pg_cron/job/job_generator.rb +116 -0
  15. data/lib/generators/pg_cron/job/templates/db/migrate/create_job.erb +5 -0
  16. data/lib/generators/pg_cron/job/templates/db/migrate/update_job.erb +5 -0
  17. data/lib/generators/pg_cron/migration_helper.rb +48 -0
  18. data/lib/generators/pg_cron/name_helper.rb +29 -0
  19. data/lib/generators/pg_cron/version_helper.rb +53 -0
  20. data/lib/pg_cron/adapters/postgres/connection.rb +26 -0
  21. data/lib/pg_cron/adapters/postgres/jobs.rb +48 -0
  22. data/lib/pg_cron/adapters/postgres/query_executor.rb +37 -0
  23. data/lib/pg_cron/adapters/postgres.rb +116 -0
  24. data/lib/pg_cron/command_recorder.rb +50 -0
  25. data/lib/pg_cron/configuration.rb +37 -0
  26. data/lib/pg_cron/definition.rb +74 -0
  27. data/lib/pg_cron/job.rb +68 -0
  28. data/lib/pg_cron/railtie.rb +22 -0
  29. data/lib/pg_cron/schema_dumper.rb +35 -0
  30. data/lib/pg_cron/statements.rb +126 -0
  31. data/lib/pg_cron/version.rb +5 -0
  32. data/lib/pg_cron/version.rb.erb +5 -0
  33. data/lib/pg_cron.rb +44 -0
  34. data/lib/tasks/pg_cron/down.rake +21 -0
  35. data/lib/tasks/pg_cron/schedule_all_jobs.rake +33 -0
  36. data/lib/tasks/pg_cron/schedule_job.rake +12 -0
  37. data/lib/tasks/pg_cron/unschedule_job.rake +12 -0
  38. data/lib/tasks/pg_cron/up.rake +25 -0
  39. data/lib/tasks/pg_cron/utils.rb +124 -0
  40. data/spec/dummy/.gitignore +71 -0
  41. data/spec/dummy/.ruby-version +1 -0
  42. data/spec/dummy/README.md +24 -0
  43. data/spec/dummy/Rakefile +6 -0
  44. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  45. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  46. data/spec/dummy/app/models/application_record.rb +3 -0
  47. data/spec/dummy/app/models/concerns/.keep +0 -0
  48. data/spec/dummy/bin/rails +4 -0
  49. data/spec/dummy/bin/rake +4 -0
  50. data/spec/dummy/bin/setup +33 -0
  51. data/spec/dummy/config/application.rb +40 -0
  52. data/spec/dummy/config/boot.rb +3 -0
  53. data/spec/dummy/config/credentials.yml.enc +1 -0
  54. data/spec/dummy/config/database.yml +86 -0
  55. data/spec/dummy/config/environment.rb +5 -0
  56. data/spec/dummy/config/environments/development.rb +58 -0
  57. data/spec/dummy/config/environments/production.rb +96 -0
  58. data/spec/dummy/config/environments/test.rb +49 -0
  59. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  60. data/spec/dummy/config/initializers/backtrace_silencers.rb +8 -0
  61. data/spec/dummy/config/initializers/cors.rb +16 -0
  62. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  63. data/spec/dummy/config/initializers/inflections.rb +16 -0
  64. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  65. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  66. data/spec/dummy/config/locales/en.yml +33 -0
  67. data/spec/dummy/config/puma.rb +43 -0
  68. data/spec/dummy/config/routes.rb +3 -0
  69. data/spec/dummy/config.ru +6 -0
  70. data/spec/dummy/db/pg_cron_jobs/dummy_job.yml +3 -0
  71. data/spec/dummy/db/seeds.rb +7 -0
  72. data/spec/dummy/lib/tasks/.keep +0 -0
  73. data/spec/dummy/log/.keep +0 -0
  74. data/spec/dummy/public/robots.txt +1 -0
  75. data/spec/dummy/tmp/.keep +0 -0
  76. data/spec/dummy/vendor/.keep +0 -0
  77. data/spec/pg_cron/configuration_spec.rb +20 -0
  78. data/spec/pg_cron/fx_coexistence_spec.rb +53 -0
  79. data/spec/pg_cron/statements_spec.rb +9 -0
  80. data/spec/spec_helper.rb +6 -0
  81. metadata +245 -0
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgCron
4
+ # Migration methods for pg_cron schedules, following F(x)'s conventions
5
+ # exactly: a name, an optional `version` naming a file in db/cron, an optional
6
+ # `sql_definition` that takes its place, and `revert_to_version` so a rollback
7
+ # restores the previous definition instead of dropping the job outright.
8
+ #
9
+ # Replaces schedule_pg_cron_job / unschedule_pg_cron_job / update_pg_cron_job,
10
+ # which took only a name and read a YAML file. Those had no versioning, so a
11
+ # changed schedule left no record of what it had been and a rollback could
12
+ # only delete the job.
13
+ module Statements
14
+ # Create a new cron job.
15
+ #
16
+ # @param name [String, Symbol] The job's name. pg_cron keys on jobname, so
17
+ # this is its identity — scheduling over an existing name replaces it.
18
+ # @param version [Integer] The version number, used to find the definition
19
+ # file in `db/cron`. Defaults to `1`.
20
+ # @param sql_definition [String] The SQL for the job. An error is raised if
21
+ # `sql_definition` and `version` are both set, as they are mutually
22
+ # exclusive.
23
+ # @return [void]
24
+ #
25
+ # @example Create from `db/cron/drain_juicefs_events_v01.sql`
26
+ # create_cron_job(:drain_juicefs_events, version: 1)
27
+ #
28
+ # @example Create from provided SQL string
29
+ # create_cron_job(:drain_juicefs_events, sql_definition: <<~SQL)
30
+ # SELECT cron.schedule(
31
+ # 'drain_juicefs_events',
32
+ # '* * * * *',
33
+ # $$SELECT juicefs_index_events(500)$$
34
+ # );
35
+ # SQL
36
+ #
37
+ def create_cron_job(name, version: nil, sql_definition: nil, revert_to_version: nil)
38
+ validate_cron_version_and_sql_definition_exclusive!(version, sql_definition)
39
+ version ||= 1
40
+
41
+ return unless PgCron.database.pg_cron_enabled?
42
+
43
+ PgCron.database.create_job(resolve_cron_sql_definition(sql_definition, name, version))
44
+ end
45
+
46
+ # Drop a cron job by name.
47
+ #
48
+ # @param name [String, Symbol] The job's name.
49
+ # @param revert_to_version [Integer] Used to reverse this on
50
+ # `rake db:rollback`; passed as `version` to {#create_cron_job}.
51
+ # @return [void]
52
+ #
53
+ def drop_cron_job(name, revert_to_version: nil)
54
+ return unless PgCron.database.pg_cron_enabled?
55
+
56
+ PgCron.database.drop_job(name)
57
+ end
58
+
59
+ # Update a cron job.
60
+ #
61
+ # One statement, not unschedule-then-schedule: cron.schedule() against an
62
+ # existing jobname REPLACES that job. Dropping first would leave a window in
63
+ # which the schedule does not exist, and on a frequently-firing job that
64
+ # window is a missed run.
65
+ #
66
+ # @param name [String, Symbol] The job's name.
67
+ # @param version [Integer] The version number, used to find the definition
68
+ # file in `db/cron`.
69
+ # @param sql_definition [String] The SQL for the job.
70
+ # @param revert_to_version [Integer] The version to roll back to.
71
+ # @return [void]
72
+ #
73
+ def update_cron_job(name, version: nil, sql_definition: nil, revert_to_version: nil)
74
+ validate_cron_version_or_sql_definition_present!(version, sql_definition)
75
+ validate_cron_version_and_sql_definition_exclusive!(version, sql_definition)
76
+
77
+ return unless PgCron.database.pg_cron_enabled?
78
+
79
+ PgCron.database.update_job(name, resolve_cron_sql_definition(sql_definition, name, version))
80
+ end
81
+
82
+ private
83
+
84
+ # THE `cron_` ON THESE THREE NAMES IS LOAD-BEARING. Do not tidy it away.
85
+ #
86
+ # This module and F(x)'s Statements are both included into the SAME object,
87
+ # ActiveRecord::ConnectionAdapters::AbstractAdapter, and we are included
88
+ # second — so anything here with a name F(x) also uses SHADOWS F(x)'s copy
89
+ # for every migration in the application, not just for ours.
90
+ #
91
+ # All three helpers below were lifted from F(x) under F(x)'s own names, and
92
+ # `resolve_sql_definition` differs from it by one argument: F(x) passes the
93
+ # object kind (:function, :trigger, :view) as a fourth. So with this gem
94
+ # loaded, every create_function / create_trigger / update_function in the
95
+ # host application died on
96
+ #
97
+ # ArgumentError: wrong number of arguments (given 4, expected 3)
98
+ #
99
+ # before it reached the database, and the two validators were a matching
100
+ # arity away from doing the same. Nothing was wrong with the caller's SQL;
101
+ # the two DSLs simply could not both be in the room.
102
+ #
103
+ # Prefixed rather than made arity-tolerant, because "works as long as F(x)
104
+ # keeps that signature" is the same bug with a longer fuse. A name that is
105
+ # ours cannot collide at all.
106
+ VERSION_OR_SQL_DEFINITION_REQUIRED = "version or sql_definition must be specified"
107
+ private_constant :VERSION_OR_SQL_DEFINITION_REQUIRED
108
+
109
+ VERSION_AND_SQL_DEFINITION_EXCLUSIVE = "sql_definition and version cannot both be set"
110
+ private_constant :VERSION_AND_SQL_DEFINITION_EXCLUSIVE
111
+
112
+ def validate_cron_version_or_sql_definition_present!(version, sql_definition)
113
+ raise ArgumentError, VERSION_OR_SQL_DEFINITION_REQUIRED, caller if version.nil? && sql_definition.nil?
114
+ end
115
+
116
+ def validate_cron_version_and_sql_definition_exclusive!(version, sql_definition)
117
+ raise ArgumentError, VERSION_AND_SQL_DEFINITION_EXCLUSIVE, caller if version.present? && sql_definition.present?
118
+ end
119
+
120
+ def resolve_cron_sql_definition(sql_definition, name, version)
121
+ return sql_definition.strip_heredoc if sql_definition
122
+
123
+ PgCron::Definition.job(name: name, version: version).to_sql
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgCron
4
+ VERSION = "2.0.0"
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgCron
4
+ VERSION = "<%= version %>"
5
+ end
data/lib/pg_cron.rb ADDED
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Definition first: Configuration reads Definition::DIRECTORY in its class body,
4
+ # so requiring it later raises NameError at boot.
5
+ require "pg_cron/definition"
6
+ require "pg_cron/job"
7
+ require "pg_cron/adapters/postgres"
8
+ require "pg_cron/configuration"
9
+ require "pg_cron/schema_dumper"
10
+ require "pg_cron/statements"
11
+ require "pg_cron/command_recorder"
12
+ require "pg_cron/railtie" if defined?(::Rails::Railtie)
13
+
14
+ module PgCron
15
+ def self.load
16
+ # Make PgCron::Statements available during migrations
17
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.include PgCron::Statements
18
+
19
+ # Make PgCron::Statements reversible for migration rollbacks
20
+ ActiveRecord::Migration::CommandRecorder.include PgCron::CommandRecorder
21
+
22
+ # Teach the schema dumper about cron jobs. Without this db/schema.rb carries
23
+ # every table and none of the schedules, so a db:schema:load database comes
24
+ # up silently missing them.
25
+ ActiveRecord::SchemaDumper.prepend PgCron::SchemaDumper
26
+ end
27
+
28
+ # The adapter cron statements run through.
29
+ #
30
+ # Was a SECOND connection, opened via ActiveRecord::Base.postgresql_connection
31
+ # against a database named `postgres`, and reconnected by hand. Two problems:
32
+ # postgresql_connection was removed in Rails 8, and the separate database was
33
+ # wrong for this setup anyway — cron.job lives in whatever cron.database_name
34
+ # points at, which is the application's own database, so the application's own
35
+ # connection is the one that can see it.
36
+ #
37
+ # It also has to be that connection for a second reason: pg_cron puts
38
+ # row-level security on cron.job filtering by username, so jobs created on a
39
+ # different connection as a different role are invisible to the app and to the
40
+ # schema dumper.
41
+ def self.connection
42
+ configuration.adapter
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "utils"
4
+
5
+ namespace :pg_cron do
6
+ desc "Tear down pg_cron PSQL extension for your development environment"
7
+ task :down, [:pg_cron_version] => :environment do |_t, args|
8
+ puts "Tearing down pg_cron"
9
+ validate_rails_environment
10
+ validate_homebrew_is_installed
11
+ validate_psql_is_running_with_brew
12
+ if pg_cron_is_installed(args[:pg_cron_version] || DEFAULT_PG_CRON_VERSION)
13
+ drop_extension
14
+ remove_pg_cron_from_shared_preload_libraries
15
+ restart_psql_service
16
+ end
17
+ rescue StandardError => e
18
+ puts "Something went wrong while tearing down pg_cron"
19
+ puts e
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :pg_cron do
4
+ desc "Schedule every job in db/cron at its highest version"
5
+ task schedule_all_jobs: :environment do |_t, _args|
6
+ latest_job_versions.each do |name, version|
7
+ ActiveRecord::Base.connection.create_cron_job(name, version: version)
8
+ end
9
+ puts "All the pg_cron jobs were successfully scheduled"
10
+ rescue StandardError => e
11
+ puts "Something went wrong while scheduling the pg_cron jobs"
12
+ puts e
13
+ end
14
+
15
+ private
16
+
17
+ # Definitions are db/cron/<name>_v<NN>.sql, so a job with several versions has
18
+ # several files and only the HIGHEST is current. Globbing filenames the way
19
+ # this task did for YAML would schedule every historical version in turn and
20
+ # leave whichever sorted last in place.
21
+ def latest_job_versions
22
+ directory = Rails.root.join("db", PgCron::Definition::DIRECTORY)
23
+
24
+ Dir.glob("*_v*.sql", base: directory).each_with_object({}) do |file, latest|
25
+ match = file.match(/\A(?<name>.+)_v(?<version>\d+)\.sql\z/)
26
+ next unless match
27
+
28
+ name = match[:name]
29
+ version = match[:version].to_i
30
+ latest[name] = version if version > latest.fetch(name, 0)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :pg_cron do
4
+ desc "Schedule a job"
5
+ task :schedule_job, [:job_name] => :environment do |_t, args|
6
+ ActiveRecord::Base.connection.schedule_pg_cron_job(args[:job_name])
7
+ puts "The pg_cron job #{args[:job_name]} was successfully scheduled"
8
+ rescue StandardError => e
9
+ puts "Something went wrong while scheduling the pg_cron job with name #{args[:job_name]}"
10
+ puts e
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :pg_cron do
4
+ desc "Unschedule a job"
5
+ task :unschedule_job, [:job_name] => :environment do |_t, args|
6
+ ActiveRecord::Base.connection.unschedule_pg_cron_job(args[:job_name])
7
+ puts "The pg_cron job #{args[:job_name]} was successfully unscheduled"
8
+ rescue StandardError => e
9
+ puts "Something went wrong while unscheduling the pg_cron job with name #{args[:job_name]}"
10
+ puts e
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "utils"
4
+
5
+ namespace :pg_cron do
6
+ desc "Install and enable pg_cron PSQL extension for your development environment"
7
+ task :up, [:pg_cron_version] => :environment do |_t, args|
8
+ puts "Setting up pg_cron"
9
+ validate_rails_environment
10
+ validate_homebrew_is_installed
11
+ validate_latest_psql_is_installed
12
+ validate_psql_is_running_with_brew
13
+ if !pg_cron_is_installed(args[:pg_cron_version] || DEFAULT_PG_CRON_VERSION)
14
+ install_pg_cron
15
+ add_pg_cron_to_shared_preload_libraries
16
+ restart_psql_service
17
+ create_extension
18
+ else
19
+ restart_psql_service
20
+ end
21
+ rescue StandardError => e
22
+ puts "Something went wrong while setting up pg_cron"
23
+ puts e
24
+ end
25
+ end
@@ -0,0 +1,124 @@
1
+ # rubocop:disable Style/SpecialGlobalVars
2
+
3
+ DEFAULT_PG_CRON_VERSION = "1.3.0".freeze
4
+
5
+ def validate_homebrew_is_installed
6
+ `brew --version`
7
+ raise "This rake task only support Darwin based OS" unless $?.success?
8
+ end
9
+
10
+ def validate_psql_is_running_with_brew
11
+ fetch_psql_brew_service_version.present?
12
+ end
13
+
14
+ def fetch_psql_brew_service_version
15
+ psql_services = `brew services list | grep "started" | grep "postgresql"`
16
+ psql_services.split(" ").first.strip
17
+ end
18
+
19
+ def validate_rails_environment
20
+ raise "This rake task should only be used in development" unless Rails.env.development?
21
+ end
22
+
23
+ # rubocop:disable Style/GuardClause
24
+ # rubocop:disable Layout/LineLength
25
+ def validate_latest_psql_is_installed
26
+ `brew list postgresql`
27
+ unless $?.success?
28
+ raise "Due to pg_cron compilation issues the postgresql brew package is needed, please install the latest psql brew package: brew install postgresql"
29
+ end
30
+ end
31
+ # rubocop:enable Style/GuardClause
32
+ # rubocop:enable Layout/LineLength
33
+
34
+ def pg_cron_is_installed(requested_version)
35
+ result = PgCron.connection.execute <<-SQL
36
+ SELECT
37
+ extversion
38
+ FROM
39
+ pg_extension
40
+ WHERE
41
+ extname='pg_cron'
42
+ SQL
43
+
44
+ extension_version = result.first&.dig("extversion")
45
+ parsed_extension_version = extension_version ? parse_pg_cron_version(extension_version) : nil
46
+ parsed_requested_version = parse_pg_cron_version(requested_version)
47
+ parsed_extension_version == parsed_requested_version
48
+ end
49
+
50
+ def parse_pg_cron_version(version)
51
+ major_minor_tuple = version.split(".").first(2)
52
+ { major: major_minor_tuple[0], minor: major_minor_tuple[1] }
53
+ end
54
+
55
+ # rubocop:disable Layout/LineLength
56
+ def install_pg_cron
57
+ latest_pg_cron_path = `brew --prefix postgresql`.strip
58
+ compilation_path = "#{latest_pg_cron_path}/bin:$PATH"
59
+ pg_cron_version = DEFAULT_PG_CRON_VERSION
60
+ `cd /tmp && \
61
+ curl -s -L https://github.com/citusdata/pg_cron/archive/refs/tags/v#{pg_cron_version}.zip --output pg_cron.zip && \
62
+ unzip -u pg_cron.zip && \
63
+ cd pg_cron-#{pg_cron_version} && \
64
+ PATH=#{compilation_path} make && PATH=#{compilation_path} sudo make install && \
65
+ cp $(brew --prefix postgresql)/share/postgresql/extension/pg_cron* $(brew --prefix #{fetch_psql_brew_service_version})/share/#{fetch_psql_brew_service_version}/extension/ && \
66
+ rm -rf pg_cron*
67
+ `
68
+ end
69
+ # rubocop:enable Layout/LineLength
70
+
71
+ def add_pg_cron_to_shared_preload_libraries
72
+ psql_config_file_path = PgCron.connection.execute("SHOW config_file").first&.dig("config_file")
73
+ config_file_content = ""
74
+ File.open(psql_config_file_path, "r") do |file|
75
+ file.each_line do |line|
76
+ if line.match(/(#\s*)?shared_preload_libraries =.*/)
77
+ libraries = line.split("=").last.match(/'.*'/).to_a.first.gsub("'", "").split(",").map(&:strip).filter do |s|
78
+ s != "pg_cron"
79
+ end
80
+ libraries << "pg_cron"
81
+ line = "shared_preload_libraries = '#{libraries.join(",")}' \n"
82
+ end
83
+
84
+ config_file_content << line
85
+ end
86
+ end
87
+
88
+ File.atomic_write(psql_config_file_path, "/tmp") { |file| file.write config_file_content }
89
+ end
90
+
91
+ def remove_pg_cron_from_shared_preload_libraries
92
+ psql_config_file_path = PgCron.connection.execute("SHOW config_file").first&.dig("config_file")
93
+ config_file_content = ""
94
+ File.open(psql_config_file_path, "r") do |file|
95
+ file.each_line do |line|
96
+ if line.match(/(#\s*)?shared_preload_libraries =.*/)
97
+ libraries = line.split("=").last.match(/'.*'/).to_a.first.gsub("'", "").split(",").map(&:strip).filter do |s|
98
+ s != "pg_cron"
99
+ end
100
+ line = "shared_preload_libraries = '#{libraries.join(",")}' \n"
101
+ line.prepend("#") if libraries.empty?
102
+ end
103
+
104
+ config_file_content << line
105
+ end
106
+ end
107
+
108
+ File.atomic_write(psql_config_file_path, "/tmp") { |file| file.write config_file_content }
109
+ end
110
+
111
+ def create_extension
112
+ PgCron.connection.enable_extension("pg_cron")
113
+ end
114
+
115
+ def restart_psql_service
116
+ `brew services restart #{fetch_psql_brew_service_version}`
117
+ sleep 1 # Prevent timing issues
118
+ end
119
+
120
+ def drop_extension
121
+ PgCron.connection.disable_extension("pg_cron")
122
+ end
123
+
124
+ # rubocop:enable Style/SpecialGlobalVars
@@ -0,0 +1,71 @@
1
+ # Rails
2
+
3
+ *.rbc
4
+ capybara-*.html
5
+ .rspec
6
+ /db/*.sqlite3
7
+ /db/*.sqlite3-journal
8
+ /db/*.sqlite3-[0-9]*
9
+ /public/system
10
+ /coverage/
11
+ /spec/tmp
12
+ *.orig
13
+ rerun.txt
14
+ pickle-email-*.html
15
+
16
+ # Ignore all logfiles and tempfiles.
17
+ /log/*
18
+ /tmp/*
19
+ !/log/.keep
20
+ !/tmp/.keep
21
+
22
+ # TODO Comment out this rule if you are OK with secrets being uploaded to the repo
23
+ config/initializers/secret_token.rb
24
+ config/master.key
25
+
26
+ # Only include if you have production secrets in this file, which is no longer a Rails default
27
+ # config/secrets.yml
28
+
29
+ # dotenv, dotenv-rails
30
+ # TODO Comment out these rules if environment variables can be committed
31
+ .env
32
+ .env.*
33
+
34
+ ## Environment normalization:
35
+ /.bundle
36
+ /vendor/bundle
37
+
38
+ # these should all be checked in to normalize the environment:
39
+ # Gemfile.lock, .ruby-version, .ruby-gemset
40
+
41
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
42
+ .rvmrc
43
+
44
+ # if using bower-rails ignore default bower_components path bower.json files
45
+ /vendor/assets/bower_components
46
+ *.bowerrc
47
+ bower.json
48
+
49
+ # Ignore pow environment settings
50
+ .powenv
51
+
52
+ # Ignore Byebug command history file.
53
+ .byebug_history
54
+
55
+ # Ignore node_modules
56
+ node_modules/
57
+
58
+ # Ignore precompiled javascript packs
59
+ /public/packs
60
+ /public/packs-test
61
+ /public/assets
62
+
63
+ # Ignore yarn files
64
+ /yarn-error.log
65
+ yarn-debug.log*
66
+ .yarn-integrity
67
+
68
+ # Ignore uploaded files in development
69
+ /storage/*
70
+ !/storage/.keep
71
+ /public/uploads
@@ -0,0 +1 @@
1
+ 2.7.4
@@ -0,0 +1,24 @@
1
+ # README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative "config/application"
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::API
2
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ class ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
File without changes
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../config/application', __dir__)
3
+ require_relative "../config/boot"
4
+ require "rails/commands"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../config/boot"
3
+ require "rake"
4
+ Rake.application.run
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ require "fileutils"
3
+
4
+ # path to your application root.
5
+ APP_ROOT = File.expand_path('..', __dir__)
6
+
7
+ def system!(*args)
8
+ system(*args) || abort("\n== Command #{args} failed ==")
9
+ end
10
+
11
+ FileUtils.chdir APP_ROOT do
12
+ # This script is a way to set up or update your development environment automatically.
13
+ # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14
+ # Add necessary setup steps to this file.
15
+
16
+ puts '== Installing dependencies =='
17
+ system! 'gem install bundler --conservative'
18
+ system('bundle check') || system!('bundle install')
19
+
20
+ # puts "\n== Copying sample files =="
21
+ # unless File.exist?('config/database.yml')
22
+ # FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
23
+ # end
24
+
25
+ puts "\n== Preparing database =="
26
+ system! 'bin/rails db:prepare'
27
+
28
+ puts "\n== Removing old logs and tempfiles =="
29
+ system! 'bin/rails log:clear tmp:clear'
30
+
31
+ puts "\n== Restarting application server =="
32
+ system! 'bin/rails restart'
33
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "boot"
2
+
3
+ require "rails"
4
+ # Pick the frameworks you want:
5
+ require "active_model/railtie"
6
+ # require "active_job/railtie"
7
+ require "active_record/railtie"
8
+ # require "active_storage/engine"
9
+ require "action_controller/railtie"
10
+ # require "action_mailer/railtie"
11
+ # require "action_mailbox/engine"
12
+ # require "action_text/engine"
13
+ require "action_view/railtie"
14
+ # require "action_cable/engine"
15
+ # require "sprockets/railtie"
16
+ # require "rails/test_unit/railtie"
17
+
18
+ # Require the gems listed in Gemfile, including any gems
19
+ # you've limited to :test, :development, or :production.
20
+ Bundler.require(*Rails.groups)
21
+
22
+ module Dummy
23
+ class Application < Rails::Application
24
+ # Initialize configuration defaults for originally generated Rails version.
25
+ config.load_defaults 6.1
26
+
27
+ # Configuration for the application, engines, and railties goes here.
28
+ #
29
+ # These settings can be overridden in specific environments using the files
30
+ # in config/environments, which are processed later.
31
+ #
32
+ # config.time_zone = "Central Time (US & Canada)"
33
+ # config.eager_load_paths << Rails.root.join("extras")
34
+
35
+ # Only loads a smaller set of middleware suitable for API only apps.
36
+ # Middleware like session, flash, cookies can be added back manually.
37
+ # Skip views, helpers and assets when generating a new resource.
38
+ config.api_only = true
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2
+
3
+ require "bundler/setup" # Set up gems listed in the Gemfile.
@@ -0,0 +1 @@
1
+ 3Y2y6yJJt66Phu+Yrv75qlm7edlJxbzIJuKJckgv0Zof/JfCUNXYJqfi1qx2IKMiKrptpTq8j/MrdhqYIw3Tnol4/Rd7+QYlVBZ2fLDh5CUxcqonj0rE3Xzxm9iXm5H8UQtee2GAfQibhLUalF7FbYx9/92UZ36hKfnAdIO75y9gXR5KkiwXSjvOUExA/4RMIsC+QngYpiC1J3JP3aIbymW+KSv0XGbMN5XQDs7/gENUsfTi936UCVz7TmCyz84zdGjwIpKBX1IPDyCIDxs3sb/ndV/TvlSBON9aE/f4juGl4nDAT9GPSPLEjJ0kfrIFs65JWhLceJVPfjIiWqSIUWFCxuFvtdGp4dCmriJhuedjef0PhXIZm2HsWmrRY5w44B28RhGubc/f9/pTZKDqd2UTY839I0SP+i9H--PGXsXE4chMSqSuEV--joWbNc15jbK1ds0sFOcjJw==