potassium 5.2.3 → 6.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +22 -9
  3. data/.node-version +1 -0
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +26 -0
  6. data/docs/DSL.md +5 -5
  7. data/lib/potassium/assets/.circleci/config.yml.erb +102 -0
  8. data/lib/potassium/assets/.eslintrc.json +343 -0
  9. data/lib/potassium/assets/.rubocop.yml +515 -0
  10. data/lib/potassium/assets/.stylelintrc.json +46 -0
  11. data/lib/potassium/assets/Dockerfile.ci +1 -1
  12. data/lib/potassium/assets/Makefile.erb +6 -32
  13. data/lib/potassium/assets/README.yml +51 -7
  14. data/lib/potassium/assets/active_admin/admin-component.vue +35 -0
  15. data/lib/potassium/assets/active_admin/admin_application.js +14 -0
  16. data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +10 -0
  17. data/lib/potassium/assets/api/base_controller.rb +1 -3
  18. data/lib/potassium/assets/app/javascript/app.spec.js +14 -0
  19. data/lib/potassium/assets/app/uploaders/base_uploader.rb +13 -0
  20. data/lib/potassium/assets/app/uploaders/image_uploader.rb +5 -0
  21. data/lib/potassium/assets/bin/cibuild.erb +18 -1
  22. data/lib/potassium/assets/bin/setup.erb +1 -1
  23. data/lib/potassium/assets/config/database_mysql.yml.erb +2 -2
  24. data/lib/potassium/assets/config/database_postgresql.yml.erb +2 -2
  25. data/lib/potassium/assets/config/shrine.rb +33 -0
  26. data/lib/potassium/assets/docker-compose.ci.yml +1 -0
  27. data/lib/potassium/assets/lib/tasks/auto_annotate_models.rake +2 -1
  28. data/lib/potassium/assets/package.json +4 -1
  29. data/lib/potassium/cli/commands/create.rb +1 -0
  30. data/lib/potassium/cli_options.rb +6 -6
  31. data/lib/potassium/helpers/template-helpers.rb +4 -0
  32. data/lib/potassium/recipes/admin.rb +3 -3
  33. data/lib/potassium/recipes/annotate.rb +1 -1
  34. data/lib/potassium/recipes/ci.rb +1 -1
  35. data/lib/potassium/recipes/database_container.rb +5 -4
  36. data/lib/potassium/recipes/draper.rb +1 -1
  37. data/lib/potassium/recipes/file_storage.rb +15 -33
  38. data/lib/potassium/recipes/front_end.rb +128 -5
  39. data/lib/potassium/recipes/mailer.rb +5 -2
  40. data/lib/potassium/recipes/node.rb +21 -0
  41. data/lib/potassium/recipes/rack_cors.rb +18 -15
  42. data/lib/potassium/recipes/schedule.rb +1 -1
  43. data/lib/potassium/recipes/style.rb +21 -3
  44. data/lib/potassium/recipes/vue_admin.rb +124 -0
  45. data/lib/potassium/templates/application.rb +4 -2
  46. data/lib/potassium/version.rb +4 -3
  47. data/potassium.gemspec +6 -5
  48. data/spec/features/database_container_spec.rb +1 -1
  49. data/spec/features/file_storage_spec.rb +12 -16
  50. data/spec/features/front_end_spec.rb +74 -0
  51. data/spec/features/new_project_spec.rb +1 -1
  52. data/spec/features/node_spec.rb +28 -0
  53. data/spec/features/power_types_spec.rb +5 -16
  54. data/spec/features/vue_admin_spec.rb +47 -0
  55. data/spec/support/potassium_test_helpers.rb +23 -9
  56. metadata +56 -29
  57. data/lib/potassium/assets/.circleci/config.yml +0 -20
  58. data/lib/potassium/assets/active_admin/active_admin.js.coffee +0 -4
  59. data/lib/potassium/assets/active_admin/init_activeadmin_angular.rb +0 -8
  60. data/lib/potassium/assets/testing/paperclip.rb +0 -59
  61. data/lib/potassium/recipes/angular_admin.rb +0 -56
  62. data/spec/features/front_end.rb +0 -33
@@ -8,7 +8,7 @@ class Recipes::Schedule < Rails::AppBuilder
8
8
 
9
9
  def create
10
10
  if selected?(:schedule)
11
- gather_gem 'sidekiq-scheduler'
11
+ gather_gem 'sidekiq-scheduler', '>= 3.0.1'
12
12
  add_readme_section :internal_dependencies, :sidekiq_scheduler
13
13
  end
14
14
  template '../assets/sidekiq_scheduler.yml', 'config/sidekiq.yml', force: true
@@ -1,12 +1,30 @@
1
1
  class Recipes::Style < Rails::AppBuilder
2
2
  def create
3
- append_to_file ".gitignore", ".rubocop.yml\n"
4
- append_to_file ".gitignore", ".eslintrc.json\n"
5
- append_to_file ".gitignore", ".sscs-lint.yml\n"
3
+ add_linters
4
+ add_config_files
6
5
  add_readme_header :style_guide
7
6
  end
8
7
 
9
8
  def install
10
9
  create
11
10
  end
11
+
12
+ private
13
+
14
+ def add_linters
15
+ gather_gems(:development, :test) do
16
+ gather_gem 'rubocop', '~> 0.82.0'
17
+ gather_gem 'rubocop-performance'
18
+ gather_gem 'rubocop-rails'
19
+ gather_gem 'rubocop-rspec'
20
+ end
21
+ run 'bin/yarn add --dev stylelint eslint eslint-plugin-import'
22
+ run 'bin/yarn add --dev eslint-plugin-vue' if selected?(:front_end, :vue)
23
+ end
24
+
25
+ def add_config_files
26
+ copy_file '../assets/.rubocop.yml', '.rubocop.yml'
27
+ copy_file '../assets/.eslintrc.json', '.eslintrc.json'
28
+ copy_file '../assets/.stylelintrc.json', '.stylelintrc.json'
29
+ end
12
30
  end
@@ -0,0 +1,124 @@
1
+ class Recipes::VueAdmin < Rails::AppBuilder
2
+ def ask
3
+ if selected?(:admin_mode)
4
+ vue_admin = answer(:vue_admin) do
5
+ Ask.confirm "Do you want Vue support for ActiveAdmin?"
6
+ end
7
+ set(:vue_admin, vue_admin)
8
+ set(:front_end, :vue) if vue_admin
9
+ end
10
+ end
11
+
12
+ def create
13
+ recipe = self
14
+ if selected?(:vue_admin)
15
+ after(:admin_install) do
16
+ recipe.add_vue_admin
17
+ end
18
+ end
19
+ end
20
+
21
+ def install
22
+ active_admin = load_recipe(:admin)
23
+ if active_admin.installed?
24
+ add_vue_admin
25
+ info "VueAdmin installed"
26
+ else
27
+ info "VueAdmin can't be installed because Active Admin isn't installed."
28
+ end
29
+ end
30
+
31
+ def installed?
32
+ dir_exist?("app/assets/javascripts/admin")
33
+ end
34
+
35
+ def add_vue_admin
36
+ add_vue_component_library
37
+ add_component_integration
38
+ copy_file '../assets/active_admin/init_activeadmin_vue.rb',
39
+ 'config/initializers/init_activeadmin_vue.rb'
40
+ copy_file '../assets/active_admin/admin_application.js',
41
+ 'app/javascript/packs/admin_application.js',
42
+ force: true
43
+ empty_directory 'app/javascript/components'
44
+ copy_file '../assets/active_admin/admin-component.vue',
45
+ 'app/javascript/components/admin-component.vue',
46
+ force: true
47
+ end
48
+
49
+ def add_component_integration
50
+ line = "class CustomFooter < ActiveAdmin::Component"
51
+ initializer = "config/initializers/active_admin.rb"
52
+ gsub_file initializer, /(#{Regexp.escape(line)})/mi do |_match|
53
+ <<~HERE
54
+ require "vue_component.rb"
55
+ AUTO_BUILD_ELEMENTS=[:admin_component, :template, :slot]
56
+ component_creator(AUTO_BUILD_ELEMENTS)
57
+
58
+ #{line}
59
+ HERE
60
+ end
61
+ end
62
+
63
+ def add_vue_component_library
64
+ lib_component_path = "lib/vue_component.rb"
65
+ class_definitions =
66
+ <<~HERE
67
+ #{vue_component}
68
+ #{component_builder}
69
+ HERE
70
+ File.open(lib_component_path, "w") { |file| file.write(class_definitions) }
71
+ end
72
+
73
+ def vue_component
74
+ <<~HERE
75
+ class VueComponent < Arbre::Component
76
+ builder_method :root
77
+ def tag_name
78
+ :root
79
+ end
80
+
81
+ def initialize(*)
82
+ super
83
+ end
84
+
85
+ def build(attributes = {})
86
+ super(process_attributes(attributes))
87
+ end
88
+
89
+ def process_attributes(attributes)
90
+ vue_attributes = {}
91
+ attributes.each do |key, value|
92
+ dasherized_key = key.to_s.dasherize
93
+ if value.is_a?(String)
94
+ vue_attributes[dasherized_key] = value
95
+ elsif !dasherized_key.index(':').nil? && dasherized_key.index(':').zero?
96
+ vue_attributes[dasherized_key] = value.to_json
97
+ else
98
+ vue_attributes[":" + dasherized_key] = value.to_json
99
+ end
100
+ end
101
+ vue_attributes
102
+ end
103
+ end
104
+ HERE
105
+ end
106
+
107
+ def component_builder
108
+ <<~HERE
109
+ def component_creator(auto_build_elements)
110
+ auto_build_elements.each do |element|
111
+ as_string=element.to_s
112
+ camelized_element = as_string.camelize
113
+ Object.const_set(camelized_element,Class.new(VueComponent))
114
+ Object.const_get(camelized_element).class_eval do
115
+ builder_method as_string.to_sym
116
+ def tag_name
117
+ self.class.to_s.underscore
118
+ end
119
+ end
120
+ end
121
+ end
122
+ HERE
123
+ end
124
+ end
@@ -1,4 +1,5 @@
1
1
  set :app_name, app_name
2
+ set :node_version, node_version
2
3
  set :titleized_app_name, get(:app_name).titleize
3
4
  set :underscorized_app_name, get(:app_name).underscore
4
5
  set :dasherized_app_name, get(:app_name).dasherize
@@ -20,7 +21,7 @@ run_action(:asking) do
20
21
  ask :devise
21
22
  ask :admin
22
23
  ask :front_end
23
- ask :angular_admin
24
+ ask :vue_admin
24
25
  ask :mailer
25
26
  ask :background_processor
26
27
  ask :schedule
@@ -47,6 +48,7 @@ run_action(:recipe_loading) do
47
48
  create :annotate
48
49
  create :data_migrate
49
50
  create :listen
51
+ create :node
50
52
  create :ruby
51
53
  create :yarn
52
54
  create :editorconfig
@@ -58,7 +60,7 @@ run_action(:recipe_loading) do
58
60
  create :better_errors
59
61
  create :devise
60
62
  create :admin
61
- create :angular_admin
63
+ create :vue_admin
62
64
  create :seeds
63
65
  create :error_reporting
64
66
  create :pundit
@@ -1,8 +1,9 @@
1
1
  module Potassium
2
- VERSION = "5.2.3"
3
- RUBY_VERSION = "2.5.5"
4
- RAILS_VERSION = "~> 5.2.1"
2
+ VERSION = "6.0.0"
3
+ RUBY_VERSION = "2.7.0"
4
+ RAILS_VERSION = "~> 6.0.2"
5
5
  RUBOCOP_VERSION = "~> 0.65.0"
6
6
  POSTGRES_VERSION = "11.3"
7
7
  MYSQL_VERSION = "5.7"
8
+ NODE_VERSION = "12"
8
9
  end
@@ -18,16 +18,17 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "bundler", "~> 2.0"
22
+ spec.add_development_dependency "pry", "~> 0.10.3"
22
23
  spec.add_development_dependency "rake", "~> 10.0"
23
24
  spec.add_development_dependency "rspec", "~> 3.4.0"
24
- spec.add_development_dependency "pry", "~> 0.10.3"
25
+ spec.add_development_dependency "rspec_junit_formatter"
25
26
  spec.add_development_dependency "rubocop", Potassium::RUBOCOP_VERSION
26
27
  spec.add_development_dependency "rubocop-rspec"
27
- spec.add_runtime_dependency "rails", Potassium::RAILS_VERSION
28
+ spec.add_runtime_dependency "gems", "~> 0.8"
28
29
  spec.add_runtime_dependency "gli", "~> 2.12.2"
29
30
  spec.add_runtime_dependency "inquirer", "~> 0.2"
30
- spec.add_runtime_dependency "gems", "~> 0.8"
31
- spec.add_runtime_dependency "semantic", "~> 1.4"
32
31
  spec.add_runtime_dependency "levenshtein", "~> 0.2"
32
+ spec.add_runtime_dependency "rails", Potassium::RAILS_VERSION
33
+ spec.add_runtime_dependency "semantic", "~> 1.4"
33
34
  end
@@ -28,7 +28,7 @@ RSpec.describe "DatabaseContainer" do
28
28
  .to include("DB_PORT=$(make services-port SERVICE=#{service_name} PORT=#{db_port})")
29
29
  expect(env_file).to include("DB_HOST=127.0.0.1")
30
30
  expect(File.exist?("#{project_path}/Makefile")).to be true
31
- expect(setup_file).to include("make services-up")
31
+ expect(setup_file).to include("docker-compose up -d")
32
32
  end
33
33
  end
34
34
  end
@@ -34,39 +34,35 @@ RSpec.describe "File Storage" do
34
34
  end
35
35
  end
36
36
 
37
- context "when selecting paperclip" do
37
+ context "when selecting shrine" do
38
38
  before :all do
39
39
  drop_dummy_database
40
40
  remove_project_directory
41
- create_dummy_project(storage: :paperclip)
41
+ create_dummy_project(storage: :shrine)
42
42
  end
43
43
 
44
- it "adds the Paperclip gem to Gemfile" do
45
- gemfile_content = IO.read("#{project_path}/Gemfile")
46
- expect(gemfile_content).to include("gem 'paperclip'")
47
- end
48
-
49
- it "adds the aws-sdk-s3 gem to Gemfile" do
44
+ it "adds the aws-sdk-s3, shrine and marcel gems to Gemfile" do
50
45
  gemfile_content = IO.read("#{project_path}/Gemfile")
51
46
  expect(gemfile_content).to include("gem 'aws-sdk-s3'")
47
+ expect(gemfile_content).to include("gem 'shrine'")
48
+ expect(gemfile_content).to include("gem 'marcel'")
52
49
  end
53
50
 
54
51
  it "adds brief to README file" do
55
52
  content = IO.read("#{project_path}/README.md")
56
- expect(content).to include("Paperclip")
53
+ expect(content).to include("Shrine")
57
54
  end
58
55
 
59
- it "adds local file storage path to gitignore" do
60
- content = IO.read("#{project_path}/.gitignore")
61
- expect(content).to include("/public/system/*")
56
+ it "adds shrine initializer" do
57
+ expect(File.exist?("#{project_path}/config/initializers/shrine.rb")).to be true
62
58
  end
63
59
 
64
- it "adds paperclip_defaults config to production" do
65
- content = IO.read("#{project_path}/config/environments/production.rb")
66
- expect(content).to include("config.paperclip_defaults")
60
+ it "adds base_uploader and image_uploader" do
61
+ expect(File.exist?("#{project_path}/app/uploaders/base_uploader.rb")).to be true
62
+ expect(File.exist?("#{project_path}/app/uploaders/image_uploader.rb")).to be true
67
63
  end
68
64
 
69
- it "adds S3 bucket ENV var" do
65
+ it "adds S3 bucket ENV vars" do
70
66
  content = IO.read("#{project_path}/.env.development")
71
67
  expect(content).to include("S3_BUCKET=")
72
68
  end
@@ -0,0 +1,74 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Front end" do
4
+ before :all do
5
+ drop_dummy_database
6
+ remove_project_directory
7
+ end
8
+
9
+ let(:application_css_path) { "#{project_path}/app/javascript/css/application.css" }
10
+ let(:gemfile) { IO.read("#{project_path}/Gemfile") }
11
+ let(:node_modules_file) { IO.read("#{project_path}/package.json") }
12
+ let(:application_js_file) { IO.read("#{project_path}/app/javascript/packs/application.js") }
13
+ let(:layout_file) { IO.read("#{project_path}/app/views/layouts/application.html.erb") }
14
+ let(:application_css_file) { IO.read(application_css_path) }
15
+ let(:tailwind_config_file) { IO.read("#{project_path}/tailwind.config.js") }
16
+ let(:rails_css_file) { IO.read("#{project_path}/app/assets/stylesheets/application.css") }
17
+
18
+ it "creates a project without a front end framework" do
19
+ remove_project_directory
20
+ create_dummy_project("front_end" => "None")
21
+ expect(gemfile).to include('webpacker')
22
+ expect(File).not_to exist(application_css_path)
23
+ end
24
+
25
+ context "with vue" do
26
+ before(:all) do
27
+ remove_project_directory
28
+ create_dummy_project("front_end" => "vue")
29
+ end
30
+
31
+ it "creates a project with vue in compiler mode as frontend framework" do
32
+ expect(gemfile).to include('webpacker')
33
+ expect(node_modules_file).to include("\"vue\"")
34
+ expect(application_js_file).to include('vue/dist/vue.esm')
35
+ expect(application_js_file).to include("el: '#vue-app'")
36
+ expect(layout_file).to include('id="vue-app"')
37
+ end
38
+
39
+ it "creates a project with only one js pack tag" do
40
+ expect(layout_file.scan("javascript_pack_tag").length).to eq(1)
41
+ end
42
+
43
+ it "creates a vue project with client css" do
44
+ expect(application_js_file).to include("import '../css/application.css';")
45
+ expect(layout_file).to include("<%= stylesheet_pack_tag 'application' %>")
46
+ expect(rails_css_file).not_to include('*= require_tree', '*= require_self')
47
+ end
48
+
49
+ it "creates a vue project with tailwindcss" do
50
+ expect(node_modules_file).to include("\"tailwindcss\"")
51
+ expect(application_css_file).to include(
52
+ "@import 'tailwindcss/base';",
53
+ "@import 'tailwindcss/components';"
54
+ )
55
+ expect(tailwind_config_file).to include('module.exports')
56
+ end
57
+ end
58
+
59
+ context "with angular" do
60
+ before(:all) do
61
+ remove_project_directory
62
+ create_dummy_project("front_end" => "angular")
63
+ end
64
+
65
+ it "creates a project without vue as front end framework" do
66
+ expect(gemfile).to include('webpacker')
67
+ expect(node_modules_file).to include("\"@angular/core\"")
68
+ end
69
+
70
+ it "creates application_js_file for tailwind without vue" do
71
+ expect(application_js_file).to include("import '../css/application.css';")
72
+ end
73
+ end
74
+ end
@@ -29,7 +29,7 @@ RSpec.describe "A new project" do
29
29
  it "configures the correct ruby version" do
30
30
  ruby_version_file = IO.read("#{project_path}/.ruby-version")
31
31
 
32
- expect(ruby_version_file).to eq("2.5")
32
+ expect(ruby_version_file).to eq("2.7")
33
33
  end
34
34
 
35
35
  it "setup ssl" do
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Node" do
4
+ let(:version) { "12" }
5
+
6
+ before(:all) do
7
+ drop_dummy_database
8
+ remove_project_directory
9
+ create_dummy_project
10
+ end
11
+
12
+ it "adds engine with node version to package.json" do
13
+ package_json_path = "#{project_path}/package.json"
14
+ expect(File).to be_file(package_json_path)
15
+ json_file = File.read(package_json_path)
16
+ js_package = JSON.parse(json_file)
17
+ expect(js_package).to have_key("engines")
18
+ expect(js_package["engines"]).to have_key("node")
19
+ expect(js_package["engines"]["node"]).to eq("#{version}.x")
20
+ end
21
+
22
+ it "adds .node-version with correct version" do
23
+ node_version_path = "#{project_path}/.node-version"
24
+ expect(File).to be_file(node_version_path)
25
+ node_version_file = File.read(node_version_path)
26
+ expect(node_version_file).to eq(version)
27
+ end
28
+ end
@@ -17,21 +17,10 @@ RSpec.describe "PowerTypes" do
17
17
  expect(readme).to include("Power-Types")
18
18
  end
19
19
 
20
- it "adds commands directory" do
21
- commands_directory = "#{project_path}/app/commands"
22
- expect(File.directory?(commands_directory)).to eq(true)
23
- end
24
-
25
- it "adds services directory" do
26
- services_directory = "#{project_path}/app/services"
27
- expect(File.directory?(services_directory)).to eq(true)
28
- end
29
- it "adds utils directory" do
30
- utils_directory = "#{project_path}/app/utils"
31
- expect(File.directory?(utils_directory)).to eq(true)
32
- end
33
- it "adds values directory" do
34
- values_directory = "#{project_path}/app/values"
35
- expect(File.directory?(values_directory)).to eq(true)
20
+ it "adds every power type directory" do
21
+ [:commands, :services, :observers, :utils, :values].each do |type|
22
+ commands_directory = "#{project_path}/app/#{type}"
23
+ expect(File.directory?(commands_directory)).to eq(true)
24
+ end
36
25
  end
37
26
  end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+ require "pry"
3
+ RSpec.describe "VueAdmin" do
4
+ before(:all) do
5
+ drop_dummy_database
6
+ remove_project_directory
7
+ create_dummy_project(:vue_admin => true, "admin" => true, "devise" => true)
8
+ end
9
+
10
+ it "adds component integration to active admin initializer" do
11
+ admin_initializer_path = "#{project_path}/config/initializers/active_admin.rb"
12
+ expect(File).to be_file(admin_initializer_path)
13
+ initializer_file = File.read(admin_initializer_path)
14
+ expect(initializer_file).to include("AUTO_BUILD_ELEMENTS")
15
+ end
16
+
17
+ it "adds layout tags to active admin layout initializer" do
18
+ initializer_path = "#{project_path}/config/initializers/init_activeadmin_vue.rb"
19
+ expect(File).to be_file(initializer_path)
20
+ end
21
+
22
+ it "adds vue_component to library" do
23
+ vue_component_lib_path = "#{project_path}/lib/vue_component.rb"
24
+ expect(File).to be_file(vue_component_lib_path)
25
+ vue_component_lib = File.read(vue_component_lib_path)
26
+ expect(vue_component_lib).to include("VueComponent")
27
+ end
28
+
29
+ it "adds admin_application pack to packs" do
30
+ application_pack_path = "#{project_path}/app/javascript/packs/admin_application.js"
31
+ expect(File).to be_file(application_pack_path)
32
+ end
33
+
34
+ it "adds admin_component to vue components" do
35
+ application_pack_path = "#{project_path}/app/javascript/components/admin-component.vue"
36
+ expect(File).to be_file(application_pack_path)
37
+ end
38
+
39
+ it "installs vue to project" do
40
+ package_json_path = "#{project_path}/package.json"
41
+ expect(File).to be_file(package_json_path)
42
+ json_file = File.read(package_json_path)
43
+ js_package = JSON.parse(json_file)
44
+ expect(js_package).to have_key("dependencies")
45
+ expect(js_package["dependencies"]).to have_key("vue")
46
+ end
47
+ end