rails-formation 0.0.0.1

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 (37) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +19 -0
  3. data/bin/formation +8 -0
  4. data/lib/rails-formation/cli/api_adapter.rb +15 -0
  5. data/lib/rails-formation/cli/file_adapter.rb +18 -0
  6. data/lib/rails-formation/cli/processor.rb +40 -0
  7. data/lib/rails-formation/formatters/factories/column.rb +63 -0
  8. data/lib/rails-formation/formatters/factories/default_value.rb +27 -0
  9. data/lib/rails-formation/formatters/factories/value.rb +78 -0
  10. data/lib/rails-formation/formatters/factory.rb +38 -0
  11. data/lib/rails-formation/formatters/migration.rb +45 -0
  12. data/lib/rails-formation/formatters/migrations/column.rb +33 -0
  13. data/lib/rails-formation/formatters/migrations/index.rb +30 -0
  14. data/lib/rails-formation/formatters/model.rb +42 -0
  15. data/lib/rails-formation/formatters/models/validation.rb +41 -0
  16. data/lib/rails-formation/formatters/models/validations/base.rb +62 -0
  17. data/lib/rails-formation/formatters/models/validations/comparsion.rb +31 -0
  18. data/lib/rails-formation/formatters/models/validations/confirmation.rb +19 -0
  19. data/lib/rails-formation/formatters/models/validations/exclusion.rb +25 -0
  20. data/lib/rails-formation/formatters/models/validations/format.rb +31 -0
  21. data/lib/rails-formation/formatters/models/validations/inclusion.rb +25 -0
  22. data/lib/rails-formation/formatters/models/validations/length.rb +58 -0
  23. data/lib/rails-formation/formatters/models/validations/numericality.rb +59 -0
  24. data/lib/rails-formation/formatters/models/validations/presence.rb +19 -0
  25. data/lib/rails-formation/formatters/models/validations/uniqueness.rb +58 -0
  26. data/lib/rails-formation/formatters/rubygem.rb +24 -0
  27. data/lib/rails-formation/formatters/rubygems/gem.rb +56 -0
  28. data/lib/rails-formation/formatters/seed.rb +30 -0
  29. data/lib/rails-formation/formatters/seeds/row.rb +19 -0
  30. data/lib/rails-formation/templates/factory.rb.tt +7 -0
  31. data/lib/rails-formation/templates/migration.rb.tt +16 -0
  32. data/lib/rails-formation/templates/model.rb.tt +7 -0
  33. data/lib/rails-formation/templates/seeds.rb.tt +3 -0
  34. data/lib/rails-formation/version.rb +6 -0
  35. data/lib/rails_formation.rb +99 -0
  36. data/rails-formation.gemspec +39 -0
  37. metadata +182 -0
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Models
6
+ module Validations
7
+ class Format < RailsFormation::Formatters::Models::Validations::Base
8
+ def to_s
9
+ "validates :#{column_name}, format: { #{extra_options.join(', ')} }"
10
+ end
11
+
12
+ private
13
+
14
+ def extra_options
15
+ base_options | extra_validation_options
16
+ end
17
+
18
+ def extra_validation_options
19
+ options = []
20
+
21
+ options << "with: #{validation_options['format_value']}" if validation_options['format_matcher'] == 'with'
22
+
23
+ options << "without: #{validation_options['format_value']}" if validation_options['format_matcher'] == 'without'
24
+
25
+ options
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Models
6
+ module Validations
7
+ class Inclusion < RailsFormation::Formatters::Models::Validations::Base
8
+ def to_s
9
+ "validates :#{column_name}, inclusion: { #{extra_options.join(', ')} }"
10
+ end
11
+
12
+ private
13
+
14
+ def extra_options
15
+ base_options | extra_validation_options
16
+ end
17
+
18
+ def extra_validation_options
19
+ ["in: #{validation_options['in']}"]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Models
6
+ module Validations
7
+ class Length < RailsFormation::Formatters::Models::Validations::Base
8
+ def to_s
9
+ "validates :#{column_name}, length: { #{extra_options.join(', ')} }"
10
+ end
11
+
12
+ private
13
+
14
+ def extra_options
15
+ base_options | extra_validation_options
16
+ end
17
+
18
+ def extra_validation_options
19
+ options = []
20
+
21
+ options << "is: #{validation_options['length_value']}" if exact_length?
22
+
23
+ options << "minimum: #{validation_options['length_min_value']}" if min_length?
24
+
25
+ options << "maximum: #{validation_options['length_max_value']}" if max_length?
26
+
27
+ options << "in: #{validation_options['length_min_value']}..#{validation_options['length_max_value']}" if range_length?
28
+
29
+ options
30
+ end
31
+
32
+ def exact_length?
33
+ validation_options['length_operator_type'] == 'value' &&
34
+ !validation_options['length_value'].nil?
35
+ end
36
+
37
+ def min_length?
38
+ validation_options['length_operator_type'] == 'range' &&
39
+ validation_options['length_max_value'].to_i.zero? &&
40
+ validation_options['length_min_value'].to_i.positive?
41
+ end
42
+
43
+ def max_length?
44
+ validation_options['length_operator_type'] == 'range' &&
45
+ validation_options['length_min_value'].to_i.zero? &&
46
+ validation_options['length_max_value'].to_i.positive?
47
+ end
48
+
49
+ def range_length?
50
+ validation_options['length_operator_type'] == 'range' &&
51
+ validation_options['length_min_value'].to_i.positive? &&
52
+ validation_options['length_max_value'].to_i.positive?
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Models
6
+ module Validations
7
+ class Numericality < RailsFormation::Formatters::Models::Validations::Base
8
+ def to_s
9
+ "validates :#{column_name}, numericality: { #{extra_options.join(', ')} }"
10
+ end
11
+
12
+ private
13
+
14
+ def extra_options
15
+ base_options | extra_validation_options
16
+ end
17
+
18
+ def extra_validation_options
19
+ options = []
20
+
21
+ if validation_options['numericality_operator'] == 'greater_than'
22
+ options << "greater_than: #{validation_options['numericality_value']}"
23
+ end
24
+
25
+ options << 'only_integer: true' if validation_options['numericality_operator'] == 'only_integer'
26
+
27
+ if validation_options['numericality_operator'] == 'greater_than_or_equal_to'
28
+ options << "greater_than_or_equal_to: #{validation_options['numericality_value']}"
29
+ end
30
+
31
+ if validation_options['numericality_operator'] == 'equal_to'
32
+ options << "equal_to: #{validation_options['numericality_value']}"
33
+ end
34
+
35
+ if validation_options['numericality_operator'] == 'less_than'
36
+ options << "less_than: #{validation_options['numericality_value']}"
37
+ end
38
+
39
+ if validation_options['numericality_operator'] == 'less_than_or_equal_to'
40
+ options << "less_than_or_equal_to: #{validation_options['numericality_value']}"
41
+ end
42
+
43
+ if validation_options['numericality_operator'] == 'other_than'
44
+ options << "other_than: #{validation_options['numericality_value']}"
45
+ end
46
+
47
+ options << "in: #{validation_options['numericality_value']}" if validation_options['numericality_operator'] == 'in'
48
+
49
+ options << 'odd: true' if validation_options['numericality_operator'] == 'odd'
50
+
51
+ options << 'even: true' if validation_options['numericality_operator'] == 'even'
52
+
53
+ options
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Models
6
+ module Validations
7
+ class Presence < RailsFormation::Formatters::Models::Validations::Base
8
+ def to_s
9
+ if base_options.any?
10
+ "validates :#{column_name}, presence: { #{base_options.join(', ')} }"
11
+ else
12
+ "validates :#{column_name}, presence: true"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Models
6
+ module Validations
7
+ class Uniqueness < RailsFormation::Formatters::Models::Validations::Base
8
+ def to_s
9
+ if extra_options.any?
10
+ "validates :#{column_name}, uniqueness: { #{extra_options.join(', ')} }"
11
+ else
12
+ "validates :#{column_name}, uniqueness: true"
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def extra_options
19
+ base_options | extra_validation_options
20
+ end
21
+
22
+ def extra_validation_options
23
+ options = []
24
+
25
+ options << 'case_sensitive: false' unless case_sensitive?
26
+
27
+ options << scope unless blank_scope?
28
+
29
+ options
30
+ end
31
+
32
+ def case_sensitive?
33
+ validation_options['uniqueness_case_sensitive'].to_i == 1
34
+ end
35
+
36
+ def blank_scope?
37
+ validation_options['uniqueness_scope'].nil? ||
38
+ validation_options['uniqueness_scope'].reject(&:empty?).size.zero?
39
+ end
40
+
41
+ def scope
42
+ return [] if validation_options['uniqueness_scope'].nil?
43
+
44
+ sanitized_scope = validation_options['uniqueness_scope'].reject(&:empty?)
45
+
46
+ return [] if sanitized_scope.size.zero?
47
+
48
+ if sanitized_scope.size == 1
49
+ "scope: :#{sanitized_scope.first}"
50
+ else
51
+ "scope: [#{sanitized_scope.map { |s| ":#{s}" }.join(', ')}]"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'rubygems/gem'
4
+
5
+ module RailsFormation
6
+ module Formatters
7
+ class Rubygem < Thor::Group
8
+ include Thor::Actions
9
+
10
+ argument :gem
11
+ argument :gemfile_path
12
+
13
+ def apply_to_gemfile
14
+ gem_definition = ::RailsFormation::Formatters::Rubygems::Gem.new(gem, gemfile_path)
15
+
16
+ insert_into_file gemfile_path, gem_definition.to_s, gem_definition.options
17
+ end
18
+
19
+ def self.source_root
20
+ __dir__
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Rubygems
6
+ class Gem
7
+ def initialize(config, gemfile_path)
8
+ @config = config
9
+ @gemfile_path = gemfile_path
10
+ end
11
+
12
+ def to_s
13
+ if create_group?
14
+ "#{groups_def} #{base_definition}end"
15
+ elsif insert_after?
16
+ " #{base_definition}"
17
+ else
18
+ base_definition
19
+ end
20
+ end
21
+
22
+ def insert_after?
23
+ !groups_def.nil?
24
+ end
25
+
26
+ def options
27
+ if !create_group? && insert_after?
28
+ { after: groups_def }
29
+ else
30
+ {}
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def base_definition
37
+ "gem '#{@config['name']}', '#{@config['version']}'\n"
38
+ end
39
+
40
+ def create_group?
41
+ return false if groups_def.nil?
42
+
43
+ !File.read(@gemfile_path).include?(groups_def.gsub("\n", ''))
44
+ end
45
+
46
+ def groups_def
47
+ return if @config.fetch('groups', []).size.zero?
48
+
49
+ groups_def = @config['groups'].map { |name| ":#{name}" }.join(', ')
50
+
51
+ "group #{groups_def} do\n"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'seeds/row'
4
+
5
+ module RailsFormation
6
+ module Formatters
7
+ class Seed < Thor::Group
8
+ include Thor::Actions
9
+
10
+ argument :seeds_configuration
11
+ argument :seeds_path
12
+
13
+ def update_seeds
14
+ template('../templates/seeds.rb.tt', seeds_path)
15
+ end
16
+
17
+ def self.source_root
18
+ __dir__
19
+ end
20
+
21
+ private
22
+
23
+ def seeds
24
+ seeds_configuration.map do |config|
25
+ RailsFormation::Formatters::Seeds::Row.new(config).to_s
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ module Formatters
5
+ module Seeds
6
+ class Row
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def to_s
12
+ factory = "FactoryBot.create(:#{@config.fetch('factory_name')})"
13
+
14
+ "#{@config.fetch('count')}.times { #{factory} }"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :<%= factory_name %> do
3
+ <% columns.each do |column| -%>
4
+ <%= column %>
5
+ <% end -%>
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ class Create<%= table_name.capitalize %> < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :<%= table_name %> do |t|
4
+ <% columns.each do |column| -%>
5
+ <%= column %>
6
+ <% end -%>
7
+ <% if timestamps? -%>
8
+ t.timestamps
9
+ <% end -%>
10
+ end
11
+
12
+ <% indices.each do |index| -%>
13
+ <%= index %>
14
+ <% end -%>
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ class <%= class_name %> < ApplicationRecord
2
+ <% if validations.any? -%>
3
+ <% validations.each do |validation| -%>
4
+ <%= validation %>
5
+ <% end -%>
6
+ <% end -%>
7
+ end
@@ -0,0 +1,3 @@
1
+ <%- seeds.each do |seed| -%>
2
+ <%= seed %>
3
+ <% end -%>
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsFormation
4
+ VERSION = '0.0.0.1'
5
+ RAILS_VERSION = '7.0.2.3'
6
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'rails-formation/formatters/migration'
5
+ require 'rails-formation/formatters/rubygem'
6
+ require 'rails-formation/formatters/model'
7
+ require 'rails-formation/formatters/factory'
8
+ require 'rails-formation/formatters/seed'
9
+ require 'rails-formation/cli/file_adapter'
10
+ require 'rails-formation/cli/api_adapter'
11
+ require 'rails-formation/cli/processor'
12
+ require 'rails-formation/version'
13
+
14
+ module RailsFormation
15
+ RailsNotInstalled = Class.new(StandardError)
16
+
17
+ class << self
18
+ def apply(template)
19
+ verify_rails_installation
20
+ generate_project(template)
21
+ bundle_and_install_gems(template.fetch('rubygems', []))
22
+ create_and_run_migrations(template.fetch('migrations', []))
23
+ create_factories(template.fetch('factories', []))
24
+ create_and_build_models(template.fetch('models', []))
25
+ insert_seeds(template.fetch('seeds', []))
26
+ end
27
+
28
+ private
29
+
30
+ def verify_rails_installation
31
+ return if system("gem list ^rails$ --version #{RailsFormation::RAILS_VERSION} -i")
32
+
33
+ raise RailsNotInstalled, "Please install Rails #{RailsFormation::RAILS_VERSION} and retry"
34
+ end
35
+
36
+ def generate_project(template)
37
+ system "rails _#{RailsFormation::RAILS_VERSION}_ new #{template['name']} -d=postgresql"
38
+ Dir.chdir(template['name'])
39
+ end
40
+
41
+ def bundle_and_install_gems(rubygems)
42
+ return if rubygems.size.zero?
43
+
44
+ gemfile_path = File.join(Dir.pwd, 'Gemfile')
45
+
46
+ rubygems.each do |config|
47
+ ::RailsFormation::Formatters::Rubygem.new([config, gemfile_path]).invoke_all
48
+ end
49
+
50
+ system 'bundle install'
51
+
52
+ rubygems.each do |config|
53
+ config.fetch('install_commands', []).map { |command| system(command) }
54
+ end
55
+ end
56
+
57
+ def create_and_run_migrations(migrations)
58
+ return if migrations.size.zero?
59
+
60
+ migrations.each do |config|
61
+ table_name = config.fetch('table')
62
+ migration_name = "#{Time.now.strftime('%Y%m%d%H%M%S')}_create_#{table_name}.rb"
63
+ migration_path = File.join(Dir.pwd, 'db', 'migrate', migration_name)
64
+ ::RailsFormation::Formatters::Migration.new([config, migration_path]).invoke_all
65
+ sleep(1)
66
+ end
67
+
68
+ system('./bin/rails db:create')
69
+ system('./bin/rails db:migrate')
70
+ end
71
+
72
+ def create_factories(factories)
73
+ factories.each do |config|
74
+ factory_name = "#{config.fetch('name')}.rb"
75
+ factory_path = File.join(Dir.pwd, 'spec', 'factories', factory_name)
76
+ ::RailsFormation::Formatters::Factory.new([config, factory_path]).invoke_all
77
+ end
78
+ end
79
+
80
+ def create_and_build_models(models)
81
+ models.each do |config|
82
+ model_name = "#{config.fetch('name').downcase}.rb"
83
+ model_path = File.join(Dir.pwd, 'app', 'models', model_name)
84
+
85
+ ::RailsFormation::Formatters::Model.new([config, model_path]).invoke_all
86
+ end
87
+ end
88
+
89
+ def insert_seeds(seeds)
90
+ return if seeds.size.zero?
91
+
92
+ seeds_path = File.join(Dir.pwd, 'db', 'seeds.rb')
93
+
94
+ ::RailsFormation::Formatters::Seed.new([seeds, seeds_path]).invoke_all
95
+
96
+ system('./bin/rails db:seed')
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rails-formation/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'rails-formation'
9
+ spec.authors = ['Paweł Dąbrowski']
10
+ spec.email = ['contact@paweldabrowski.com']
11
+ spec.license = 'MIT'
12
+ spec.version = RailsFormation::VERSION.dup
13
+
14
+ spec.summary = 'Templates for Rails bootstraping'
15
+ spec.description = spec.summary
16
+ spec.homepage = 'https://railsformation.com'
17
+ spec.files = Dir['CHANGELOG.md', 'LICENSE', 'README.md', 'rails-formation.gemspec', 'bin/*', 'lib/**/*',
18
+ 'config/*.yml']
19
+ spec.bindir = 'bin'
20
+ spec.executables = ['formation']
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
24
+ spec.metadata['changelog_uri'] = 'https://github.com/pdabrowski6/rails-formation/blob/master/CHANGELOG.md'
25
+ spec.metadata['source_code_uri'] = 'https://github.com/pdabrowski6/rails-formation'
26
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/pdabrowski6/rails-formation/issues'
27
+ spec.metadata['rubygems_mfa_required'] = 'true'
28
+
29
+ spec.required_ruby_version = '>= 2.7.0'
30
+
31
+ spec.add_runtime_dependency 'ffaker', '~> 2.20.0'
32
+ spec.add_runtime_dependency 'thor', '~> 1.2.1'
33
+
34
+ spec.add_development_dependency 'bundler'
35
+ spec.add_development_dependency 'rake'
36
+ spec.add_development_dependency 'rspec'
37
+ spec.add_development_dependency 'rubocop'
38
+ spec.add_development_dependency 'timecop'
39
+ end