scintilla 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b6e8fc9cfcb9971c82a90394104d367363f7e62873d78ef13d6e8b0694f09cf0
4
+ data.tar.gz: 0e9361a281b9c76a925a8aaea47a74b10329fec94690e71f416a7b78124aed7d
5
+ SHA512:
6
+ metadata.gz: 924c10b4ca1f65502a00be12eee89b2401027ade9c456295fdc4bedbd093d73e8215381ce1887742deab83d8f002f0528e019c6c78150446c48de2487fd63eba
7
+ data.tar.gz: 22a9afa92d4fb5efde8551456a81f01520956ec38b7c459550f74d8e20545d4a5b64d583e804b42cdd48b6e11c9840f485e80ae2dc128cc94f88f763b6bdc5de
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Andrea Schiavini
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
1
+ # Scintilla
2
+
3
+ `TL;DR`: Scintilla allows running one-time scripts in your Rails application, mimicking
4
+ the behaviour of Rails migrations.
5
+
6
+ It relies on an ActiveRecord model (`ScintillaScript`) to keep track of already ran
7
+ scripts (consider it the equivalent of the `schema_migrations` table).
8
+
9
+ It offers a rake task, `scintilla:run`, to run scripts. Integrating it with your
10
+ deployment flow is up to you.
11
+
12
+ ## Usage
13
+
14
+ ### Generating a new Scintilla script
15
+
16
+ `> rails g scintilla do_something_useful`
17
+
18
+ This will create a timestamped file under `db/scintilla`, like
19
+ `20200324_do_something_useful.rb`. You will need to edit this file and fill the
20
+ `do_the_stuff` method with the code you want to run.
21
+
22
+ ### Running Scintilla scripts
23
+
24
+ `> rails scintilla:run`
25
+
26
+ This will, in turn:
27
+
28
+ - check the script files under `db/scintilla`;
29
+ - for each of them, check if it has already been ran (a `Scintilla::Script` record is
30
+ present on DB), and only require the ones that still need to be ran;
31
+ - run the missing scintilla scripts, and create `Scintilla::Script` records on DB for each
32
+ of them.
33
+
34
+ ## Installation
35
+
36
+ Add this line to your application's Gemfile:
37
+
38
+ ```ruby
39
+ gem 'scintilla'
40
+ ```
41
+
42
+ And then execute:
43
+
44
+ ```bash
45
+ $ rails scintilla:install:migrations
46
+ $ rails db:migrate
47
+ ```
48
+
49
+ ## Contributing
50
+
51
+ Feel free to open issues and PRs, fork the project as you want ;)
52
+
53
+
54
+ ## License
55
+
56
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'Scintilla'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
20
+ load 'rails/tasks/engine.rake'
21
+
22
+ load 'rails/tasks/statistics.rake'
23
+
24
+ require 'bundler/gem_tasks'
25
+
26
+ require 'rake/testtask'
27
+
28
+ Rake::TestTask.new(:test) do |t|
29
+ t.libs << 'test'
30
+ t.pattern = 'test/**/*_test.rb'
31
+ t.verbose = false
32
+ end
33
+
34
+ task default: :test
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/scintilla .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class ApplicationController < ActionController::Base
5
+ protect_from_forgery with: :exception
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ module ApplicationHelper
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class ApplicationJob < ActiveJob::Base
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class ApplicationMailer < ActionMailer::Base
5
+ default from: 'from@example.com'
6
+ layout 'mailer'
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class ScintillaScript < ApplicationRecord
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Scintilla</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "scintilla/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ Scintilla::Engine.routes.draw do
4
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateScintillaScintillaScripts < ActiveRecord::Migration[6.0]
4
+ def change
5
+ create_table :scintilla_scintilla_scripts do |t|
6
+ t.string :filename
7
+ t.datetime :ran_at
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ This generator creates a scintilla script under db/scintilla
3
+
4
+ Example:
5
+ rails generate scintilla DoSomething
6
+
7
+ This will create:
8
+ db/scintilla/<timestamp>_do_something.rb
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'fileutils'
5
+
6
+ class ScintillaGenerator < Rails::Generators::NamedBase
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ def create_scintilla_file
10
+ dir = Rails.root.join 'db', 'scintilla'
11
+ FileUtils.mkdir_p dir
12
+ file = Rails.root.join 'db', 'scintilla', "#{Time.zone.now.strftime('%Y%m%d')}_#{name.gsub(/\.rb$/, '').underscore}.rb"
13
+ copy_file 'empty_scintilla_script.erb', file
14
+
15
+ gsub_file file, 'KlassName', name.camelize
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ class KlassName < Scintilla::Runnable
2
+ def initialize
3
+ @file_name = Scintilla::Runner.script_name(__FILE__, false)
4
+ end
5
+
6
+ def do_the_stuff
7
+ # put your logic here
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'scintilla/engine'
4
+ Dir[Scintilla::Engine.root + 'app/models/**/*.rb'].collect { |f| require f }
5
+
6
+ require 'scintilla/runner'
7
+ require 'scintilla/runnable'
8
+
9
+ module Scintilla
10
+ # Your code goes here...
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Scintilla
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class Runnable
5
+ attr_accessor :file_name
6
+
7
+ # Runs the script, unless already ran.
8
+ #
9
+ # @return [<Scintilla::ScintillaScript>] the created ScintillaScript on DB, only if
10
+ # script has ran successfully.
11
+ #
12
+ def run
13
+ if ScintillaScript.exists?(filename: file_name)
14
+ puts "#{file_name} already ran, skipping..."
15
+ else
16
+ puts "Running #{file_name}..."
17
+ do_the_stuff
18
+ ScintillaScript.create(filename: file_name, ran_at: Time.zone.now)
19
+ end
20
+ end
21
+
22
+ def do_the_stuff
23
+ raise 'Implement this in every Scintilla::Runner subclass...'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ class Runner
5
+ def self.run
6
+ scripts.each(&:run)
7
+ end
8
+
9
+ # Get the list of scripts to be ran.
10
+ #
11
+ # @param [<Boolean>] conditional_require whether to only require
12
+ # scripts that still haven't ran. Defaults to true.
13
+ #
14
+ # @return [<Array<Scintilla::Runnable>>] the list of Runnable objects
15
+ # to be ran.
16
+ #
17
+ def self.scripts(conditional_require = true)
18
+ scripts = require_scripts(conditional_require)
19
+ scripts.sort.inject([]) do |scripts_to_run, filename|
20
+ klass = script_name(filename, true).camelize.constantize
21
+ scripts_to_run << klass.new
22
+ end
23
+ end
24
+
25
+ # Requires the scripts in the db/scintilla path, to allow loading
26
+ # them for execution.
27
+ #
28
+ # @param [<Boolean>] conditional_require whether to only require
29
+ # scripts that still haven't ran. This is useful if
30
+ # older scripts contain references to no longer present
31
+ # classes, and to boost performances. Set it to false
32
+ # for debugging purposes.
33
+ #
34
+ def self.require_scripts(conditional_require)
35
+ scripts = Dir[Rails.root.join('db', 'scintilla', '*.rb')]
36
+ if conditional_require
37
+ scripts.reject! { |f| ScintillaScript.exists?(filename: script_name(f, false)) }
38
+ end
39
+ scripts.each { |f| require f }
40
+ end
41
+ private_class_method :require_scripts
42
+
43
+ # Extract script_name from file_name, removing timestamp and optionally
44
+ # removing extension.
45
+ #
46
+ # @param [<String>] full_file_path the full file path, e.g. /a/b/c.rb
47
+ # @param [<Boolean>] without_extension remove extension from file name.
48
+ # Defaults to false
49
+ #
50
+ # @return [<String>] the script name, e.g. c.rb
51
+ #
52
+ def self.script_name(full_file_path, without_extension = false)
53
+ name = File.basename(full_file_path).gsub(/^\d+_/, '') # remove timestamp
54
+ name = name.gsub(/\.rb$/, '') if without_extension
55
+ name
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scintilla
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :scintilla do
4
+ desc 'Run Scintilla scripts'
5
+ task run: :environment do
6
+ Scintilla::Runner.run
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scintilla
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrea Schiavini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Scintilla allows running scripts only once, mimicking the behaviour of
42
+ Rails migrations
43
+ email:
44
+ - metalelf0@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - MIT-LICENSE
50
+ - README.md
51
+ - Rakefile
52
+ - app/assets/config/scintilla_manifest.js
53
+ - app/assets/stylesheets/scintilla/application.css
54
+ - app/controllers/scintilla/application_controller.rb
55
+ - app/helpers/scintilla/application_helper.rb
56
+ - app/jobs/scintilla/application_job.rb
57
+ - app/mailers/scintilla/application_mailer.rb
58
+ - app/models/scintilla/application_record.rb
59
+ - app/models/scintilla/scintilla_script.rb
60
+ - app/views/layouts/scintilla/application.html.erb
61
+ - config/routes.rb
62
+ - db/migrate/20200323165014_create_scintilla_scintilla_scripts.rb
63
+ - lib/generators/scintilla/USAGE
64
+ - lib/generators/scintilla/scintilla_generator.rb
65
+ - lib/generators/scintilla/templates/empty_scintilla_script.erb
66
+ - lib/generators/scintilla/templates/empty_scintilla_script.erb.tmp
67
+ - lib/scintilla.rb
68
+ - lib/scintilla/engine.rb
69
+ - lib/scintilla/runnable.rb
70
+ - lib/scintilla/runner.rb
71
+ - lib/scintilla/version.rb
72
+ - lib/tasks/scintilla_tasks.rake
73
+ homepage: https://github.com/metalelf0/scintilla
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.7.6
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Scintilla is a library for one-time scripts on Rails
97
+ test_files: []