rails_app_generator 0.0.5 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.vscode/settings.json +3 -0
  4. data/CHANGELOG.md +23 -0
  5. data/README.md +9 -0
  6. data/after_templates/README.md +3 -0
  7. data/after_templates/___base_template.rb +1 -0
  8. data/after_templates/___r7_hotwire.rb +1 -0
  9. data/after_templates/rag_bootstrap/application-yield.html.erb +5 -0
  10. data/after_templates/rag_bootstrap/application.html.erb +4 -0
  11. data/after_templates/rag_bootstrap/component-cards-fancy.css +84 -0
  12. data/after_templates/rag_bootstrap/component-cards-fancy.html +80 -0
  13. data/after_templates/rag_bootstrap/component-cards-staff.css +90 -0
  14. data/after_templates/rag_bootstrap/component-cards-staff.html +140 -0
  15. data/after_templates/rag_bootstrap/component-cards-styled.html +31 -0
  16. data/after_templates/rag_bootstrap/component-footer.html +34 -0
  17. data/after_templates/rag_bootstrap/component-hero.html +15 -0
  18. data/after_templates/rag_bootstrap/component-nav.html +36 -0
  19. data/after_templates/rag_bootstrap/custom-bootstrap-import.scss +5 -0
  20. data/after_templates/rag_bootstrap/custom-using-css.css +3 -0
  21. data/after_templates/rag_bootstrap/custom-using-scss.scss +5 -0
  22. data/after_templates/rag_bootstrap/manifest.js +3 -0
  23. data/after_templates/rag_bootstrap.rb +1 -0
  24. data/after_templates/rag_simple.rb +25 -0
  25. data/after_templates/rag_tailwind.rb +74 -0
  26. data/exe/rag +41 -0
  27. data/lib/rails_app_generator/add_on.rb +73 -0
  28. data/lib/rails_app_generator/addons/annotate.rb +15 -0
  29. data/lib/rails_app_generator/addons/continuous_integration.rb +14 -0
  30. data/lib/rails_app_generator/addons/devise.rb +50 -0
  31. data/lib/rails_app_generator/addons/docker.rb +14 -0
  32. data/lib/rails_app_generator/addons/docker_compose.rb +13 -0
  33. data/lib/rails_app_generator/addons/dotenv.rb +13 -0
  34. data/lib/rails_app_generator/addons/factory_bot.rb +19 -0
  35. data/lib/rails_app_generator/addons/foreman.rb +15 -0
  36. data/lib/rails_app_generator/addons/generators.rb +31 -0
  37. data/lib/rails_app_generator/addons/high_voltage.rb +15 -0
  38. data/lib/rails_app_generator/addons/inline_svg.rb +11 -0
  39. data/lib/rails_app_generator/addons/irbrc.rb +13 -0
  40. data/lib/rails_app_generator/addons/lograge.rb +13 -0
  41. data/lib/rails_app_generator/addons/pundit.rb +16 -0
  42. data/lib/rails_app_generator/addons/rspec.rb +17 -0
  43. data/lib/rails_app_generator/addons/rubocop.rb +13 -0
  44. data/lib/rails_app_generator/addons/scaffold.rb +15 -0
  45. data/lib/rails_app_generator/addons/services.rb +13 -0
  46. data/lib/rails_app_generator/addons/sidekiq.rb +18 -0
  47. data/lib/rails_app_generator/addons/stimulus.rb +15 -0
  48. data/lib/rails_app_generator/addons/stimulus_components.rb +33 -0
  49. data/lib/rails_app_generator/addons/tailwind.rb +22 -0
  50. data/lib/rails_app_generator/addons/views.rb +21 -0
  51. data/lib/rails_app_generator/app_builder.rb +7 -5
  52. data/lib/rails_app_generator/app_generator.rb +187 -99
  53. data/lib/rails_app_generator/context.rb +75 -0
  54. data/lib/rails_app_generator/dependencies.rb +34 -0
  55. data/lib/rails_app_generator/notes/a1.txt +1 -1
  56. data/lib/rails_app_generator/notes/a2.txt +1 -1
  57. data/lib/rails_app_generator/notes/kw01-b.txt +86 -0
  58. data/lib/rails_app_generator/notes/kw01.txt +91 -0
  59. data/lib/rails_app_generator/options/map_option_string.rb +2 -0
  60. data/lib/rails_app_generator/options/rails_options.rb +52 -32
  61. data/lib/rails_app_generator/starter.rb +17 -8
  62. data/lib/rails_app_generator/version.rb +1 -1
  63. data/lib/rails_app_generator.rb +5 -1
  64. data/package-lock.json +2 -2
  65. data/package.json +1 -1
  66. data/profiles/rag-add-some-pages.json +11 -0
  67. data/profiles/rag-bootstrap.json +12 -0
  68. data/profiles/rag-simple.json +11 -0
  69. data/profiles/rag-tailwind.json +12 -0
  70. data/templates/README.md.erb +43 -0
  71. data/templates/addons/annotate/auto_annotate_models.rake +60 -0
  72. data/templates/addons/continuous_integration/.github/workflows/build.yml.erb +49 -0
  73. data/templates/addons/devise/app/views/devise/confirmations/new.html.erb +24 -0
  74. data/templates/addons/devise/app/views/devise/passwords/edit.html.erb +34 -0
  75. data/templates/addons/devise/app/views/devise/passwords/new.html.erb +23 -0
  76. data/templates/addons/devise/app/views/devise/registrations/edit.html.erb +62 -0
  77. data/templates/addons/devise/app/views/devise/registrations/new.html.erb +45 -0
  78. data/templates/addons/devise/app/views/devise/sessions/new.html.erb +33 -0
  79. data/templates/addons/devise/app/views/devise/shared/_error_messages.html.erb +15 -0
  80. data/templates/addons/devise/app/views/devise/shared/_form_wrap.html.erb +5 -0
  81. data/templates/addons/devise/app/views/devise/shared/_links.html.erb +25 -0
  82. data/templates/addons/devise/app/views/devise/unlocks/new.html.erb +22 -0
  83. data/templates/addons/docker/.dockerignore.erb +51 -0
  84. data/templates/addons/docker/Dockerfile.erb +45 -0
  85. data/templates/addons/docker_compose/docker-compose.yml.erb +21 -0
  86. data/templates/addons/dotenv/.env.development.erb +3 -0
  87. data/templates/addons/foreman/.foreman.erb +1 -0
  88. data/templates/addons/foreman/Procfile.dev.erb +7 -0
  89. data/templates/addons/foreman/Procfile.erb +4 -0
  90. data/templates/addons/generators/lib/generators/rails/navigation/USAGE +6 -0
  91. data/templates/addons/generators/lib/generators/rails/navigation/navigation_generator.rb +16 -0
  92. data/templates/addons/generators/lib/generators/rails/scaffold_controller_generator.rb +12 -0
  93. data/templates/addons/high_voltage/config/initializers/high_voltage.rb +6 -0
  94. data/templates/addons/irbrc/.irbrc.erb +13 -0
  95. data/templates/addons/lograge/config/initializers/lograge.rb +5 -0
  96. data/templates/addons/pundit/app/controllers/authorized_controller.rb.erb +10 -0
  97. data/templates/addons/pundit/app/policies/application_policy.rb +57 -0
  98. data/templates/addons/rspec/spec/rails_helper.rb +26 -0
  99. data/templates/addons/rspec/spec/spec_helper.rb +61 -0
  100. data/templates/addons/rubocop/.rubocop.yml.erb +37 -0
  101. data/templates/addons/scaffold/lib/templates/erb/scaffold/_form.html.erb +39 -0
  102. data/templates/addons/scaffold/lib/templates/erb/scaffold/edit.html.erb +7 -0
  103. data/templates/addons/scaffold/lib/templates/erb/scaffold/index.html.erb +34 -0
  104. data/templates/addons/scaffold/lib/templates/erb/scaffold/new.html.erb +7 -0
  105. data/templates/addons/scaffold/lib/templates/erb/scaffold/show.html.erb +18 -0
  106. data/templates/addons/services/app/services/application_service.rb +15 -0
  107. data/templates/app_x/controllers/authorized_controller.rb.erb +10 -0
  108. data/templates/app_x/controllers/errors_controller.rb.erb +24 -0
  109. data/templates/app_x/javascript/images/checkmark.svg +1 -0
  110. data/templates/app_x/javascript/images/logo.svg +1 -0
  111. data/templates/app_x/javascript/stylesheets/components.scss +206 -0
  112. data/templates/app_x/views/errors/internal_error.html.erb +14 -0
  113. data/templates/app_x/views/errors/not_found.html.erb +14 -0
  114. data/templates/app_x/views/errors/unacceptable.html.erb +14 -0
  115. data/templates/app_x/views/layouts/application.html.erb.tt +30 -0
  116. data/templates/app_x/views/pages/home.html.erb.tt +20 -0
  117. data/templates/app_x/views/shared/_flashes.html.erb.tt +12 -0
  118. data/templates/app_x/views/shared/_footer.html.erb.tt +21 -0
  119. data/templates/app_x/views/shared/_navbar.html.erb.tt +55 -0
  120. data/templates/app_x/workers/application_worker.rb +5 -0
  121. metadata +207 -3
@@ -0,0 +1,25 @@
1
+ <%- if controller_name != 'sessions' %>
2
+ <div class="flex flex-wrap"><%= link_to "Log in", new_session_path(resource_name), class: "block py-2 text-gray-700 underline hover:no-underline" %></div>
3
+ <% end -%>
4
+
5
+ <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
6
+ <%= link_to "Sign up", new_registration_path(resource_name), class: "block py-2 text-gray-700 underline hover:no-underline" %>
7
+ <% end -%>
8
+
9
+ <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
10
+ <%= link_to "Forgot your password?", new_password_path(resource_name), class: "block py-2 text-gray-700 underline hover:no-underline" %>
11
+ <% end -%>
12
+
13
+ <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
14
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name), class: "block py-2 text-gray-700 underline hover:no-underline"%>
15
+ <% end -%>
16
+
17
+ <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18
+ <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name), class: "block py-2 text-gray-700 underline hover:no-underline" %>
19
+ <% end -%>
20
+
21
+ <%- if devise_mapping.omniauthable? %>
22
+ <%- resource_class.omniauth_providers.each do |provider| %>
23
+ <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), class: "btn btn-default my-4" %>
24
+ <% end -%>
25
+ <% end -%>
@@ -0,0 +1,22 @@
1
+ <% content_for :devise_form do %>
2
+ <h2 class="pt-4 mb-8 text-4xl font-bold heading">Resend unlock instructions</h2>
3
+
4
+ <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
5
+ <%= render "devise/shared/error_messages", resource: resource %>
6
+
7
+ <div class="input-group">
8
+ <%= f.label :email, class: "label" %>
9
+ <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "input" %>
10
+ </div>
11
+
12
+ <div class="input-group">
13
+ <%= f.submit "Resend unlock instructions", class: "btn btn-default" %>
14
+ </div>
15
+ <% end %>
16
+
17
+ <hr class="mt-6 border"/>
18
+
19
+ <%= render "devise/shared/links" %>
20
+ <% end %>
21
+
22
+ <%= render "devise/shared/form_wrap" %>
@@ -0,0 +1,51 @@
1
+ .git
2
+ .gitignore
3
+ README.md
4
+
5
+ #
6
+ # OS X
7
+ #
8
+ .DS_Store
9
+ .AppleDouble
10
+ .LSOverride
11
+ # Icon must end with two \r
12
+ Icon
13
+ # Thumbnails
14
+ ._*
15
+ # Files that might appear on external disk
16
+ .Spotlight-V100
17
+ .Trashes
18
+ # Directories potentially created on remote AFP share
19
+ .AppleDB
20
+ .AppleDesktop
21
+ Network Trash Folder
22
+ Temporary Items
23
+ .apdisk
24
+
25
+ #
26
+ # Rails
27
+ #
28
+ .env
29
+ .env.sample
30
+ *.rbc
31
+ capybara-*.html
32
+ log
33
+ tmp
34
+ db/*.sqlite3
35
+ db/*.sqlite3-journal
36
+ public/system
37
+ coverage/
38
+ spec/tmp
39
+ **.orig
40
+
41
+ .bundle
42
+
43
+ .ruby-version
44
+ .ruby-gemset
45
+
46
+ .rvmrc
47
+
48
+ # if using bower-rails ignore default bower_components path bower.json files
49
+ vendor/assets/bower_components
50
+ *.bowerrc
51
+ bower.json
@@ -0,0 +1,45 @@
1
+ FROM ruby:3.0-slim as cache
2
+
3
+ RUN apt-get update -qq && apt-get install -y \
4
+ curl \
5
+ build-essential \
6
+ libpq-dev \
7
+ postgresql-client
8
+ RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
9
+
10
+ RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
11
+ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
12
+
13
+ RUN apt-get update -qq && apt-get install -y yarn
14
+
15
+ WORKDIR /bookstore
16
+ COPY Gemfile /<%= app_name %>/Gemfile
17
+ COPY Gemfile.lock /<%= app_name %>/Gemfile.lock
18
+ COPY package.json /<%= app_name %>/package.json
19
+ COPY yarn.lock /<%= app_name %>/yarn.lock
20
+
21
+ RUN bundle install --without development
22
+ RUN yarn install
23
+
24
+ FROM cache
25
+ COPY . /<%= app_name %>
26
+
27
+ ARG DATABASE_HOST=db
28
+ ARG RAILS_ENV=production
29
+
30
+ ENV DATABASE_HOST=$DATABASE_HOST
31
+ ENV RAILS_ENV=$RAILS_ENV
32
+
33
+ ENV RAILS_LOG_TO_STDOUT=true
34
+ ENV RAILS_SERVE_STATIC_FILES=true
35
+
36
+ RUN bundle exec rails assets:precompile
37
+
38
+ COPY entrypoint.sh /usr/bin/
39
+ RUN chmod +x /usr/bin/entrypoint.sh
40
+ ENTRYPOINT ["entrypoint.sh"]
41
+
42
+ EXPOSE 3000
43
+
44
+ # Start the main process.
45
+ CMD ["rails", "server", "-b", "0.0.0.0"]
@@ -0,0 +1,21 @@
1
+ version: "3"
2
+ services:
3
+ <%= app_name %>-db:
4
+ image: postgres
5
+ volumes:
6
+ - <%= app_name %>-data:/var/lib/postgresql/data
7
+ ports:
8
+ - 5432:5432
9
+ environment:
10
+ POSTGRES_PASSWORD: <%= app_name %>
11
+ POSTGRES_USER: <%= app_name %>
12
+
13
+ <%-if uses?(:sidekiq) -%>
14
+ <%= app_name %>-redis:
15
+ image: redis
16
+ ports:
17
+ - 6379:6379
18
+ <%- end -%>
19
+
20
+ volumes:
21
+ <%= app_name %>-data:
@@ -0,0 +1,3 @@
1
+ DATABASE_HOST=localhost
2
+ DATABASE_USERNAME=<%= app_name %>
3
+ DATABASE_PASSWORD=<%= app_name %>
@@ -0,0 +1 @@
1
+ procfile: Procfile.dev
@@ -0,0 +1,7 @@
1
+ <% if uses?(:docker_compose) -%>
2
+ docker: docker-compose up --scale <%= app_name %>=0
3
+ <% end -%>
4
+ <% if uses?(:sidekiq) -%>
5
+ sidekiq: bundle exec sidekiq
6
+ <% end -%>
7
+ web: bundle exec rails server -p 3000
@@ -0,0 +1,4 @@
1
+ web: rails server
2
+ <% if uses?(:sidekiq) -%>
3
+ worker: sidekiq
4
+ <% end -%>
@@ -0,0 +1,6 @@
1
+ Description:
2
+ This adds a link to the specified resource to your home page
3
+
4
+ Example:
5
+ bin/rails generate navigation resource
6
+
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ # Add Navigation bar to Rails application
5
+ class NavigationGenerator < Rails::Generators::NamedBase
6
+ def add_link
7
+ append_to_file 'app/views/shared/_navbar.html.erb',
8
+ after: '<!-- SZ Link Placeholder -->' do
9
+ <<-HTML
10
+
11
+ <%= link_to "#{plural_name.capitalize}", #{plural_name}_path, class: "block md:inline-block p-3 border-b-2 border-gray-100 md:border-none" %>
12
+ HTML
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
5
+
6
+ module Rails
7
+ module Generators
8
+ class ScaffoldControllerGenerator
9
+ hook_for :navigation, type: :boolean, default: true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ HighVoltage.configure do |config|
4
+ config.route_drawer = HighVoltage::RouteDrawers::Root
5
+ config.home_page = 'home'
6
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'irb/completion'
4
+ require 'irb/ext/save-history'
5
+
6
+ <%# https://docs.ruby-lang.org/en/2.2.0/IRB.html %>
7
+ IRB.conf[:SAVE_HISTORY] = 1000
8
+ IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-history"
9
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
10
+
11
+ <% if uses?(:factory_bot) -%>
12
+ include FactoryBot::Syntax::Methods
13
+ <% end -%>
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.configure do
4
+ config.lograge.enabled = true
5
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AuthorizedController < ApplicationController
4
+ include Pundit
5
+
6
+ before_action :authenticate_user!
7
+
8
+ after_action :verify_authorized, except: :index
9
+ after_action :verify_policy_scoped, only: :index
10
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Pundit ApplicationPolicy
4
+ class ApplicationPolicy
5
+ attr_reader :user, :record
6
+
7
+ def initialize(user, record)
8
+ raise Pundit::NotAuthorizedError, 'must be logged in' unless user
9
+
10
+ @user = user
11
+ @record = record
12
+ end
13
+
14
+ def index?
15
+ false
16
+ end
17
+
18
+ def show?
19
+ false
20
+ end
21
+
22
+ def create?
23
+ false
24
+ end
25
+
26
+ def new?
27
+ false
28
+ end
29
+
30
+ def update?
31
+ false
32
+ end
33
+
34
+ def edit?
35
+ false
36
+ end
37
+
38
+ def destroy?
39
+ false
40
+ end
41
+
42
+ # Pundit ApplicationPolicy - Scope
43
+ class Scope
44
+ attr_reader :user, :scope
45
+
46
+ def initialize(user, scope)
47
+ raise Pundit::NotAuthorizedError, 'must be logged in' unless user
48
+
49
+ @user = user
50
+ @scope = scope
51
+ end
52
+
53
+ def resolve
54
+ scope.all
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ ENV['RAILS_ENV'] ||= 'test'
5
+ require File.expand_path('../config/environment', __dir__)
6
+ # Prevent database truncation if the environment is production
7
+ abort('The Rails environment is running in production mode!') if Rails.env.production?
8
+ require 'rspec/rails'
9
+
10
+ Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
11
+
12
+ # Checks for pending migrations and applies them before tests are run.
13
+ # If you are not using ActiveRecord, you can remove these lines.
14
+ begin
15
+ ActiveRecord::Migration.maintain_test_schema!
16
+ rescue ActiveRecord::PendingMigrationError => e
17
+ puts e.to_s.strip
18
+ exit 1
19
+ end
20
+ RSpec.configure do |config|
21
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
22
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
23
+ config.use_transactional_fixtures = true
24
+ config.infer_spec_type_from_file_location!
25
+ config.filter_rails_from_backtrace!
26
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ config.expect_with :rspec do |expectations|
5
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
6
+ end
7
+
8
+ config.mock_with :rspec do |mocks|
9
+ mocks.verify_partial_doubles = true
10
+ end
11
+
12
+ config.shared_context_metadata_behavior = :apply_to_host_groups
13
+
14
+ # The settings below are suggested to provide a good initial experience
15
+ # with RSpec, but feel free to customize to your heart's content.
16
+ # This allows you to limit a spec run to individual examples or groups
17
+ # you care about by tagging them with `:focus` metadata. When nothing
18
+ # is tagged with `:focus`, all examples get run. RSpec also provides
19
+ # aliases for `it`, `describe`, and `context` that include `:focus`
20
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
21
+ config.filter_run_when_matching :focus
22
+
23
+ # Allows RSpec to persist some state between runs in order to support
24
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
25
+ # you configure your source control system to ignore this file.
26
+ config.example_status_persistence_file_path = 'spec/examples.txt'
27
+
28
+ # Limits the available syntax to the non-monkey patched syntax that is
29
+ # recommended. For more details, see:
30
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
31
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
32
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
33
+ config.disable_monkey_patching!
34
+
35
+ # Many RSpec users commonly either run the entire suite or an individual
36
+ # file, and it's useful to allow more verbose output when running an
37
+ # individual spec file.
38
+ if config.files_to_run.one?
39
+ # Use the documentation formatter for detailed output,
40
+ # unless a formatter has already been configured
41
+ # (e.g. via a command-line flag).
42
+ config.default_formatter = 'doc'
43
+ end
44
+
45
+ # Print the 10 slowest examples and example groups at the
46
+ # end of the spec run, to help surface which specs are running
47
+ # particularly slow.
48
+ config.profile_examples = 10
49
+
50
+ # Run specs in random order to surface order dependencies. If you find an
51
+ # order dependency and want to debug it, you can fix the order by providing
52
+ # the seed, which is printed after each run.
53
+ # --seed 1234
54
+ config.order = :random
55
+
56
+ # Seed global randomization in this process using the `--seed` CLI option.
57
+ # Setting this allows you to use `--seed` to deterministically reproduce
58
+ # test failures related to randomization by passing the same `--seed` value
59
+ # as the one that triggered the failure.
60
+ Kernel.srand config.seed
61
+ end
@@ -0,0 +1,37 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ Exclude:
4
+ - bin/*
5
+ - db/schema.rb
6
+ - db/migrate/*
7
+ - node_modules/**/*
8
+
9
+ Naming/AccessorMethodName:
10
+ Enabled: false
11
+
12
+ Metrics/MethodLength:
13
+ CountAsOne: ['array', 'heredoc']
14
+ IgnoredMethods: ['describe', 'context']
15
+
16
+ Metrics/BlockLength:
17
+ IgnoredMethods: ['describe', 'context']
18
+ Exclude:
19
+ - config/environments/*.rb
20
+ - '**/*.rake'
21
+
22
+ Layout/LineLength:
23
+ Max: 120
24
+
25
+ Layout/MultilineMethodCallIndentation:
26
+ EnforcedStyle: indented
27
+
28
+ Lint/EmptyBlock:
29
+ Exclude:
30
+ - spec/factories/*
31
+
32
+ Style/BlockDelimiters:
33
+ Exclude:
34
+ - spec/**/*
35
+
36
+ Style/Documentation:
37
+ Enabled: false
@@ -0,0 +1,39 @@
1
+ <%%= form_with(model: <%= model_resource_name %>) do |form| %>
2
+ <%% if <%= singular_table_name %>.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
5
+
6
+ <ul>
7
+ <%% <%= singular_table_name %>.errors.each do |error| %>
8
+ <li><%%= error.full_message %></li>
9
+ <%% end %>
10
+ </ul>
11
+ </div>
12
+ <%% end %>
13
+
14
+ <% attributes.each do |attribute| -%>
15
+ <div class="mb-6">
16
+ <% if attribute.password_digest? -%>
17
+ <%%= form.label :password, class: "label" %>
18
+ <%%= form.password_field :password, class: "input" %>
19
+ </div>
20
+ <div class="mb-6">
21
+ <%%= form.label :password_confirmation, class: "label" %>
22
+ <%%= form.password_field :password_confirmation, class: "input" %>
23
+ <% else %>
24
+ <%%= form.label :<%= attribute.column_name %>, class: "label" %>
25
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input" %>
26
+ <% end %>
27
+ </div>
28
+
29
+ <% end -%>
30
+ <div class="mt-2 flex justify-between items-center">
31
+ <%%= link_to 'Back', <%= index_helper %>_path, class: "btn btn-default" %>
32
+ <div class="flex">
33
+ <%%= form.button class: "btn btn-default" %>
34
+ <%% if form.object.persisted? %>
35
+ <%%= link_to 'Delete', form.object, class: "btn btn-default", method: :delete, data: { remote: true, confirm: "Are you sure?" }, class: "btn btn-warn" %>
36
+ <%% end %>
37
+ </div>
38
+ </div>
39
+ <%% end %>
@@ -0,0 +1,7 @@
1
+ <div class="container mx-auto my-8 px-4">
2
+ <h1 class="text-4xl">Editing <%= plural_table_name.titleize %></h1>
3
+
4
+ <div class="bg-white rounded shadow p-4">
5
+ <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
6
+ </div>
7
+ </div>
@@ -0,0 +1,34 @@
1
+ <div class="container mx-auto my-8 px-4">
2
+ <h1 class="text-4xl mb-2"><%= plural_table_name.titleize %></h1>
3
+ <%% if @<%= plural_table_name %>.exists? %>
4
+ <div class="bg-white rounded shadow p-3">
5
+ <table class="w-full">
6
+ <thead>
7
+ <tr>
8
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
9
+ <th class="p-3 uppercase text-left text-xs text-gray-700"><%= attribute.human_name %></th>
10
+ <% end -%>
11
+ <th class="p-3 uppercase text-left text-xs text-gray-700">Actions</th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
16
+ <tr class="group border-t border-gray-400 hover:bg-gray-100">
17
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
18
+ <td class="p-3"><%%= <%= singular_table_name %>.<%= attribute.column_name %> %></td>
19
+ <% end -%>
20
+ <td>
21
+ <%%= link_to "View", <%= singular_table_name %>, class: "btn btn-default" %>
22
+ <%%= link_to "Edit", edit_<%= singular_table_name %>_path(<%= singular_table_name %>), class: "btn
23
+ btn-default" %>
24
+ </td>
25
+ </tr>
26
+ <%% end %>
27
+ </tbody>
28
+ </table>
29
+ </div>
30
+ <%% end %>
31
+ <div class="mt-4">
32
+ <%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_route_name %>_path, class: "btn btn-default" %>
33
+ </div>
34
+ </div>
@@ -0,0 +1,7 @@
1
+ <div class="container mx-auto my-8 px-4">
2
+ <h1 class="text-4xl">New <%= plural_table_name.titleize %></h1>
3
+
4
+ <div class="bg-white rounded shadow p-4">
5
+ <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
6
+ </div>
7
+ </div>
@@ -0,0 +1,18 @@
1
+ <div class="container mx-auto my-8 px-4">
2
+ <h1 class="text-4xl"><%= plural_table_name.titleize %></h1>
3
+
4
+ <div class="bg-white rounded shadow p-4">
5
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
6
+ <p class="text-lg font-semibold"><%= attribute.human_name %>:</p>
7
+ <p class="leading-normal"><%%= @<%= singular_table_name %>.<%= attribute.name %> %></p>
8
+ <% end -%>
9
+ <div class="flex items-center justify-between mt-4">
10
+ <%%= link_to 'Back', <%= index_helper %>_path, class: "btn btn-default" %>
11
+ <div>
12
+ <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>), class: "btn btn-default" %>
13
+ <%%= link_to 'Destroy', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>), class: "btn btn-warn" %>
14
+ </div>
15
+ </div>
16
+ </div>
17
+
18
+ </div>
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Base application service object
4
+ class ApplicationService
5
+ def self.call(*args, &block)
6
+ instance = new(*args, &block)
7
+ instance.call
8
+ end
9
+
10
+ def call
11
+ raise NotImplementedError('Services must implement call')
12
+ end
13
+
14
+ private_class_method :new
15
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AuthorizedController < ApplicationController
4
+ include Pundit
5
+
6
+ before_action :authenticate_user!
7
+
8
+ after_action :verify_authorized, except: :index
9
+ after_action :verify_policy_scoped, only: :index
10
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ErrorsController < ApplicationController
4
+ def not_found
5
+ respond_to do |format|
6
+ format.html { render status: 404 }
7
+ format.json { render json: { error: 'Resource not found' }, status: 404 }
8
+ end
9
+ end
10
+
11
+ def unacceptable
12
+ respond_to do |format|
13
+ format.html { render status: 422 }
14
+ format.json { render json: { error: 'Params unacceptable' }, status: 422 }
15
+ end
16
+ end
17
+
18
+ def internal_error
19
+ respond_to do |format|
20
+ format.html { render status: 500 }
21
+ format.json { render json: { error: 'Internal server error' }, status: 500 }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1 @@
1
+ <svg fill="#fff" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M0 11l2-2 5 5L18 3l2 2L7 18z"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 92.81 122.88" style="enable-background:new 0 0 92.81 122.88" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;}</style><g><path class="st0" d="M66.69,101.35H26.68l-4.7,6.94h49.24L66.69,101.35L66.69,101.35z M17.56,114.81l-5.47,8.07H0l19.64-29.46 h-3.49c-4.76,0-8.66-3.9-8.66-8.66V8.66C7.5,3.9,11.39,0,16.15,0h61.22c4.76,0,8.66,3.9,8.66,8.66v76.1c0,4.76-3.9,8.66-8.66,8.66 h-3.4l18.83,29.04H80.45l-4.99-7.65H17.56L17.56,114.81z M62.97,67.66h10.48c1.14,0,2.07,0.93,2.07,2.07V80.2 c0,1.14-0.93,2.07-2.07,2.07H62.97c-1.14,0-2.07-0.93-2.07-2.07V69.72C60.9,68.59,61.83,67.66,62.97,67.66L62.97,67.66z M18.98,67.66h10.48c1.14,0,2.07,0.93,2.07,2.07V80.2c0,1.14-0.93,2.07-2.07,2.07H18.98c-1.14,0-2.07-0.93-2.07-2.07V69.72 C16.91,68.59,17.84,67.66,18.98,67.66L18.98,67.66z M25.1,16.7h42.81c4.6,0,8.36,3.76,8.36,8.37v13.17c0,4.6-3.76,8.36-8.36,8.36 H25.1c-4.6,0-8.36-3.76-8.36-8.36V25.07C16.74,20.47,20.5,16.7,25.1,16.7L25.1,16.7z M38.33,3.8h16.2C55.34,3.8,56,4.46,56,5.27 v6.38c0,0.81-0.66,1.47-1.47,1.47h-16.2c-0.81,0-1.47-0.66-1.47-1.47V5.27C36.85,4.46,37.51,3.8,38.33,3.8L38.33,3.8z"/></g></svg>