rails-formation 0.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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