airslie-engineer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3845ee121169c0e4368a5f9b718ea104d35e1089891867f044514641b21746ba
4
+ data.tar.gz: a7cf566c986b3ba47595144d12748738d386ab8d93bd20ad87c1195fa3cf5337
5
+ SHA512:
6
+ metadata.gz: 580a40b11805629f416007b1045d18314fc1b26c3707558c87d551531a200345148bc823e55dfb093f48668e2f83877084d909f31e99d3c74ad81879fec91a9f
7
+ data.tar.gz: 2736a5837435728a4267619d86c545147be3269dec5a8d24469103f205931d0198483b70bccf64e676e586facf8bfc08da9eb18ec12874aa482a8405cd715813
@@ -0,0 +1,20 @@
1
+ Copyright 2019 Airslie Ltd
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,46 @@
1
+ [![Maintainability](https://api.codeclimate.com/v1/badges/112e9f4a7cda28bd73d7/maintainability)](https://codeclimate.com/github/airslie/engineer/maintainability)
2
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/112e9f4a7cda28bd73d7/test_coverage)](https://codeclimate.com/github/airslie/engineer/test_coverage)
3
+
4
+ # Engineer
5
+
6
+ This gem makes developing a Renalware plugin (a Rails engine) a little easier.
7
+ It does most of the standard Engine initialization including:
8
+
9
+ - appending the engine's `db/migrate`, `db/triggers`, `db/functions` and `db/views` paths to the
10
+ application's `config.paths` so that migrations across all engines and the app itself - and any
11
+ sql definition files referenced in migrations - can be found during a `db:migrate`
12
+ - loading any `config/locale/**/*.yml` that exist in the engine.
13
+ - more to follow..
14
+
15
+ ## Usage
16
+
17
+ In your Rails engine add the following to `lib/xxxx/engine.rb`:
18
+
19
+ ```ruby
20
+ class Engine < ::Rails::Engine
21
+ isolate_namespace Renalware::Xxxx
22
+ include Engineer::DefaultInitializers
23
+ ...
24
+ end
25
+ ```
26
+
27
+ ## Installation
28
+ Add this line to your application's Gemfile:
29
+
30
+ ```ruby
31
+ gem 'engineer'
32
+ ```
33
+
34
+ And then execute:
35
+ ```bash
36
+ $ bundle
37
+ ```
38
+
39
+ # Development Tasks
40
+
41
+ - [ ] Add tests
42
+ - [ ] Add a generator to bring in standard files for a new Renalware plugin
43
+ - [ ] Look for other Engine boiler-plate code we can move here.
44
+
45
+ ## License
46
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,29 @@
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 = "Engineer"
14
+ rdoc.options << "--line-numbers"
15
+ rdoc.rdoc_files.include("README.md")
16
+ rdoc.rdoc_files.include("lib/**/*.rb")
17
+ end
18
+
19
+ require "bundler/gem_tasks"
20
+
21
+ require "rake/testtask"
22
+
23
+ Rake::TestTask.new(:test) do |t|
24
+ t.libs << "test"
25
+ t.pattern = "test/**/*_test.rb"
26
+ t.verbose = false
27
+ end
28
+
29
+ task default: :test
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "engineer/railtie"
4
+ require "engineer/database/scenic"
5
+ require "engineer/database/initializers"
6
+ require "engineer/locale/initializers"
7
+ require "engineer/default_initializers"
8
+ require "engineer/seed_extensions"
9
+
10
+ module Engineer
11
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Engineer
4
+ module Database
5
+ #
6
+ # Add db/migrate, db/views, db/triggers and db/functions folders to app.config.paths so they
7
+ # can be resolved during migration
8
+ # Be sure sure to append to any existing entries in #paths, because other engines, and
9
+ # the app itself, will add their paths too.
10
+ # This step is especially important for the Scenic gem; sql view definitions in db/views
11
+ # are referenced by filename from migrations, and we need to be able to locate those files.
12
+ # The Scenic issue is a bit more too it see scenic.rb for more info.
13
+ # Note that a common but way more kludgy approach to this problem is to copy the migrations
14
+ # views etc from each gen into the host app with a rake task. This is a slicker a less
15
+ # error-proone solution.
16
+ #
17
+ class AppendEnginePaths
18
+ attr_reader :app, :engine_config
19
+
20
+ def initialize(app:, engine_config:)
21
+ @app = app
22
+ @engine_config = engine_config
23
+ end
24
+
25
+ def call
26
+ append_migration_paths
27
+ append_other_paths
28
+ end
29
+
30
+ # db/migrate paths are handled rather differently.
31
+ # Prevent duplicate migrations if we are db:migrating at the engine level (eg when
32
+ # running tests) rather than the host app.
33
+ def append_migration_paths
34
+ if running_in_dummy_app? || running_outside_of_engine?
35
+ add_engine_db_path_to_app("migrate")
36
+ end
37
+ end
38
+
39
+ def append_other_paths
40
+ %w(views functions triggers).each do |sub_folder|
41
+ add_engine_db_path_to_app(sub_folder)
42
+ end
43
+ end
44
+
45
+ def add_engine_db_path_to_app(sub_folder)
46
+ key = "db/#{sub_folder}"
47
+ path_to_db_things_in_engine = Rails.root.join(engine_config.root, "db", sub_folder)
48
+ app_config = app.config
49
+ app_config.paths[key] ||= []
50
+ app_config.paths[key] << path_to_db_things_in_engine
51
+ end
52
+
53
+ def running_in_dummy_app?
54
+ Dir.pwd.ends_with?("dummy")
55
+ end
56
+
57
+ def running_outside_of_engine?
58
+ app.root.to_s.match(engine_config.root.to_s + File::SEPARATOR).nil?
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./append_engine_paths"
4
+
5
+ module Engineer
6
+ module Database
7
+ class Initializers
8
+ attr_reader :klass
9
+
10
+ def initialize(klass)
11
+ @klass = klass
12
+ end
13
+
14
+ def add
15
+ klass.initializer :"append_migrations_in_#{klass.name.underscore.tr("/", "_")}" do |app|
16
+ AppendEnginePaths.new(app: app, engine_config: config).call
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Engineer
4
+ module Database
5
+ # The scenic gem supports loading SQL view definition files from a db/views folder but only
6
+ # supports one folder (it looks in app.config.paths["db/views"] and takes the last one) which
7
+ # works fine if you are using a rake task to copy all your views from various engines into the
8
+ # host app. But this a bit issues prone and it is much nicer to add each engine's db/views
9
+ # folder to app.config.paths (we do this in the Engineer::Database::Initializers class provided
10
+ # the engine includes the appropriate file) and then here we override the Scenic
11
+ # Definition#to_sql method and when a view definition file is requested, search all db/views
12
+ # paths - which may search in several engines and host app itself - and hopefully find the file
13
+ # we are looking for. In theory that file should be in the same engine/app that its
14
+ # corresponding migration is in... though we can't verify that and its unlikely
15
+ # We raise an error if we find two matching files i.e. a view definition file of the same name
16
+ # in two gems.
17
+ module ResolveScenicViewsAnywhere
18
+ def to_sql
19
+ view_definition_file = find_view_definition_among_all_possible_paths
20
+
21
+ File.read(view_definition_file).tap do |content|
22
+ if content.empty?
23
+ raise "Define view query in #{path} before migrating."
24
+ end
25
+ end
26
+ end
27
+
28
+ def find_view_definition_among_all_possible_paths
29
+ found_files = all_full_paths.select{ |path| File.exist?(path) }
30
+ if found_files.length > 1
31
+ raise "More than one view definition matches the name #{filename}\n #{found_files}"
32
+ end
33
+
34
+ found_files.first
35
+ end
36
+
37
+ def all_full_paths
38
+ app = Rails.application
39
+ return super unless defined?(app) && app.present?
40
+
41
+ app.config.paths["db/views"].map { |path| File.join(path, filename) }
42
+ end
43
+ end
44
+
45
+ if defined?(Scenic)
46
+ Scenic::Definition.send(:prepend, ResolveScenicViewsAnywhere)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Engineer
6
+ module Database
7
+ module SeedHelper
8
+ def log(msg, type: :full)
9
+ case type
10
+ when :full
11
+ print "-----> #{msg}"
12
+ if block_given?
13
+ ms = Benchmark.ms { yield }
14
+ milliseconds = "#{ms.to_i}ms"
15
+ print "\r-----> #{milliseconds.ljust(8, ' ')} #{msg}"
16
+ end
17
+ print "\n"
18
+ when :sub
19
+ puts " #{msg}"
20
+ else
21
+ raise "Unknown type #{type}"
22
+ end
23
+ end
24
+
25
+ def log_section(title)
26
+ log "-" * 80
27
+ log title
28
+ log "-" * 80
29
+ end
30
+
31
+ def without_papertrail_versioning_for(klass)
32
+ raise ArgumentError unless klass.is_a? Class
33
+ klass.paper_trail.disable
34
+ yield
35
+ klass.paper_trail.enable
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Engineer
4
+ module DefaultInitializers
5
+ def self.included(klass)
6
+ Database::Initializers.new(klass).add
7
+ Locale::Initializers.new(klass).add
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Add an initializer to pull in the Engine's locale yml files.
5
+ #
6
+ module Engineer
7
+ module Locale
8
+ class Initializers
9
+ def initialize(klass)
10
+ @klass = klass
11
+ end
12
+
13
+ def add
14
+ klass.initializer :"add_locals_in_#{klass.name.underscore.tr("/", "_")}" do |app|
15
+ # Because we have a different binding here we can't call private Initializers
16
+ # members so instead explicitly call a class method on ourselves passing in the
17
+ # variables we need.
18
+ Engineer::Locale::Initializers.add_engine_locale_files(app, config)
19
+ end
20
+ end
21
+
22
+ def self.add_engine_locale_files(app, engine_config)
23
+ engine_locale_files = Dir[engine_config.root.join("config", "locales", "**", "*.{rb,yml}")]
24
+ i18n = app.config.i18n
25
+ i18n.load_path += engine_locale_files
26
+ i18n.default_locale = "en-GB"
27
+ i18n.fallbacks = [:en]
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :klass
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Engineer
4
+ class Railtie < ::Rails::Railtie
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Engineer
4
+ module SeedExtensions
5
+ def load_demo_seed
6
+ require root.join("demo_data/seeds")
7
+ end
8
+ end
9
+ end
10
+
11
+ Rails::Engine.prepend(Engineer::SeedExtensions)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Engineer
4
+ VERSION = "1.0.0"
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # desc "Explaining what the task does"
4
+ # task :engineer do
5
+ # # Task goes here
6
+ # end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: airslie-engineer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Airslie Ltd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-11 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: 5.2.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.2.2
27
+ description: Making Renalware plugin development easier
28
+ email:
29
+ - dev@airslie.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - lib/engineer.rb
38
+ - lib/engineer/database/append_engine_paths.rb
39
+ - lib/engineer/database/initializers.rb
40
+ - lib/engineer/database/scenic.rb
41
+ - lib/engineer/database/seed_helper.rb
42
+ - lib/engineer/default_initializers.rb
43
+ - lib/engineer/locale/initializers.rb
44
+ - lib/engineer/railtie.rb
45
+ - lib/engineer/seed_extensions.rb
46
+ - lib/engineer/version.rb
47
+ - lib/tasks/engineer_tasks.rake
48
+ homepage: https://github.com/airslie/engineer
49
+ licenses:
50
+ - MIT
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.7.6
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Making Renalware plugin development easier
72
+ test_files: []