kadim 0.2.3 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 342513d50a550f796aac7141643367bb7c1af74a6220e389035e1bc632f3ebc8
4
- data.tar.gz: 75f898d15c78b273e6c7c3935af4070cf638e6da3fe665595e60ddb87560cd94
3
+ metadata.gz: cfb2766e697bcfdfec4e606aca5398f9f4ff673d3cd06daf91bc415609d3fe94
4
+ data.tar.gz: 1e2a9a1cc54e158157492e54db31b7391d31ab8cf5bbb96fc910198c3337a118
5
5
  SHA512:
6
- metadata.gz: e225bfef348b53e94eebcaf93337c7ad5ab08e0b5ef51ecfa23b1b7805b25465288fee316574fdcfda29f99e38166189320cff24627d4d386422751c60db0a74
7
- data.tar.gz: fd2b37bff6edab8c130c4b99c1bc87f42e863d0d00c0a6bd8e2d9ca79c0556a9d349609b3729c4e24ba671eac8fa8f4b17f97529be51b4d75a547e7b8eaceaae
6
+ metadata.gz: 742c0dc9e953a303c4105e16bb5e9a32c41d19949046dd309f913071e9fdbfd806ac5f21df4793e84cc1273a8bda348eb3b56dda8e0fb34184f5277dfd406a7d
7
+ data.tar.gz: f9d5722c64dc28cac554d1bce33ad942e6fc9140e9b0189191556852fc6d20d2868f62f133899bf674b436a773136c012015aa83c7abc11a136b4c5a64ad2df2
data/README.md CHANGED
@@ -1,48 +1,70 @@
1
1
  # kadim*
2
2
  Admin is all about CRUD, right?
3
3
 
4
- My biggest experience with admins is with RailsAdmin. I currently work with an application that makes extensive use of
5
- it and all my peers hate having to customize anything on it, me too!
4
+ My biggest experience with admins is with [RailsAdmin](https://github.com/sferik/rails_admin). I currently work with an
5
+ application that makes extensive use of it and all my peers hate having to customize anything on it, me too!
6
6
 
7
- If I have used administrate or trestle? Yes, I've tried it, but isn't reinventing the wheel super cool? In fact I
8
- believe a less DSL-focused admin would be better.
7
+ I also tried [administrate](https://github.com/thoughtbot/administrate) and
8
+ [trestle](https://github.com/TrestleAdmin/trestle), I think they are a move forward, but reinventing the wheel is super
9
+ cool, right? The true is that I want more Rails and less DSL.
9
10
 
10
- I just got annoyed at just criticizing existing solutions and decided to get my hands dirty to put my vision into
11
- practice.
12
-
13
- ** kadim: derived from "cadim", an expression from the brazillian mineiro dialect that means "a little bit".*
11
+ **kadim: derived from "cadim", an expression from the brazillian mineiro dialect that means "a little bit".*
14
12
 
15
13
  ## Usage
16
- In the current incarnation, it's very crud (no pun intended) and there is no configuration, everything works by
17
- convention.
14
+ In the current incarnation, it's very crud (no pun intended). We just dynamically scaffold_controller your models using
15
+ all it's attributes and ActiveStorage relations inside `tmp/kadim` and load everything in memory, including views. This
16
+ allows you to run kadim in environments with ephemeral file systems, like [heroku](https://www.heroku.com/).
17
+
18
+ Just follow the [Installation](#installation) section and access http://localhost:3000/kadim
18
19
 
19
- For each model of your application will be generated a controller and their views, using the Rails generator
20
- scaffold_controller, using all columns present in your model. Relations, ActiveStorage attachments and other
21
- ActiveRecord methods added by gems are ignored.
20
+ ### ActiveStorage support
21
+ If we detect that you have S3, GCS or Azure Storage configured we will use
22
+ [Direct Uploads](https://edgeguides.rubyonrails.org/active_storage_overview.html#direct-uploads) by default. If you are
23
+ using GCS and uploading biiiig files, the `resumable` option is perfect:
22
24
 
23
- Files are generated in `tmp/kadim` and loaded into memory, including views. This also has the advantage of allowing the
24
- gem to work in environments with ephemeral file systems.
25
+ ```ruby
26
+ # config/initializers/kadim.rb
27
+ Kadim.configure do |config|
28
+ config.upload_type = :resumable
29
+ end
30
+ ```
25
31
 
26
- ## Customization
32
+ upload_type accepts the following options:
33
+ - :local - Uses ActiveStorage [Disk Service](https://edgeguides.rubyonrails.org/active_storage_overview.html#disk-service)
34
+ - :direct - Uses ActiveStorage [Direct Upload](https://edgeguides.rubyonrails.org/active_storage_overview.html#direct-uploads)
35
+ - :resumable - Uses [activestorage-resumable gem](https://rubygems.org/gems/activestorage-resumable) to implement [Resumable Uploads](https://cloud.google.com/storage/docs/performing-resumable-uploads) (supports only GCS)
27
36
 
28
- You can manually copy kadim files and put them in the same path within your application. You will probably want to do
29
- this with the main kadim controller, to add safety rules, etc.
37
+ ## Customization / generators
30
38
 
31
- You also provide two generators to make this task easier.
39
+ ### kadim:host
32
40
 
33
- ```bash
34
- rails g kadim:host
35
- rails g kadim:host:scaffold_controller ModelName
36
- ```
41
+ Usage: `rails g kadim:host`
42
+
43
+ Hosts the base files of kadim inside your application, allowing you to customize from the base controller to the
44
+ layouts with the Ruby on Rails you know and love.
45
+
46
+ The following folders will be copied recursively to your application:
47
+ - app/assets/javascripts/kadim
48
+ - app/assets/stylesheets/kadim
49
+ - app/controllers/kadim
50
+ - app/helpers/kadim
51
+ - app/views/kadim
52
+ - app/views/layouts/kadim
53
+
54
+ It's pretty simple stuff, just take a look: https://github.com/fnix/kadim/tree/master/app
55
+
56
+ ### kadim:scaffold_controller
57
+
58
+ Usage: `rails g kadim:scaffold_controller NAME [field:type field:type] [options]`
37
59
 
38
- The first one copies the basic kadim infrastructure to your application, ie the
39
- [main controller](app/controllers/kadim/application_controller.rb), the
40
- [main view](app/views/kadim/application/index.html.erb) and its [layout](app/views/layouts/kadim/application.html.erb),
41
- a [helper](app/helpers/kadim/application_helper.rb) and [assets](app/assets/).
60
+ Hosts on your application the files generated in runtime by `kadim` for the giving resource. This generator is a thin
61
+ layer over the Rails scaffold_controller and accepts the same arguments.
42
62
 
43
- The second copies the files that kadim dynamically generates into your application, allowing you to have full control
44
- over controller and views implementation. This generator is a thin layer over the Rails scaffold_controller, but it only
45
- accepts the model name as a parameter, for attributes all fields of the model are used.
63
+ For example, using `credit_card` for NAME, the following files wil be generated on your application:
64
+ - Controller: app/controllers/kadim/credit_cards_controller.rb
65
+ - Test: test/controllers/kadim/credit_cards_controller_test.rb
66
+ - Views: app/views/kadim/credit_cards/index.html.erb [...]
67
+ - Helper: app/helpers/kadim/credit_cards_helper.rb
46
68
 
47
69
  ## Installation
48
70
  Add this line to your application's Gemfile:
@@ -71,7 +93,7 @@ And access http://localhost:3000/kadim
71
93
  ## Roadmap
72
94
  - [x] Dynamic CRUD generation from application models
73
95
  - [x] Tasks to copy files form kadim to the hosted application
74
- - [ ] Add support to ActiveStorage attachments
96
+ - [x] Add support to ActiveStorage attachments
75
97
  - [ ] Add support to belongs_to relationships
76
98
  - [ ] Add a beautiful look and feel
77
99
 
@@ -1 +1,4 @@
1
1
  //= require rails-ujs
2
+ //= require activestorage
3
+ //= require activestorage-resumable
4
+ //= require_tree .
@@ -0,0 +1,36 @@
1
+ addEventListener('direct-upload:initialize', event => {
2
+ const { target, detail } = event
3
+ const { id, file } = detail
4
+ target.insertAdjacentHTML('beforebegin', `
5
+ <div id="direct-upload-${id}" class="direct-upload direct-upload--pending">
6
+ <div id="direct-upload-progress-${id}" class="direct-upload__progress" style="width: 0%"></div>
7
+ <span class="direct-upload__filename">${file.name}</span>
8
+ </div>
9
+ `)
10
+ })
11
+
12
+ addEventListener('direct-upload:start', event => {
13
+ const { id } = event.detail
14
+ const element = document.getElementById(`direct-upload-${id}`)
15
+ element.classList.remove('direct-upload--pending')
16
+ })
17
+
18
+ addEventListener('direct-upload:progress', event => {
19
+ const { id, progress } = event.detail
20
+ const progressElement = document.getElementById(`direct-upload-progress-${id}`)
21
+ progressElement.style.width = `${progress}%`
22
+ })
23
+
24
+ addEventListener('direct-upload:error', event => {
25
+ event.preventDefault()
26
+ const { id, error } = event.detail
27
+ const element = document.getElementById(`direct-upload-${id}`)
28
+ element.classList.add('direct-upload--error')
29
+ element.setAttribute('title', error)
30
+ })
31
+
32
+ addEventListener('direct-upload:end', event => {
33
+ const { id } = event.detail
34
+ const element = document.getElementById(`direct-upload-${id}`)
35
+ element.classList.add('direct-upload--complete')
36
+ })
@@ -0,0 +1,36 @@
1
+ addEventListener('resumable-upload:initialize', event => {
2
+ const { target, detail } = event
3
+ const { id, file } = detail
4
+ target.insertAdjacentHTML('beforebegin', `
5
+ <div id="resumable-upload-${id}" class="resumable-upload resumable-upload--pending">
6
+ <div id="resumable-upload-progress-${id}" class="resumable-upload__progress" style="width: 0%"></div>
7
+ <span class="resumable-upload__filename">${file.name}</span>
8
+ </div>
9
+ `)
10
+ })
11
+
12
+ addEventListener('resumable-upload:start', event => {
13
+ const { id } = event.detail
14
+ const element = document.getElementById(`resumable-upload-${id}`)
15
+ element.classList.remove('resumable-upload--pending')
16
+ })
17
+
18
+ addEventListener('resumable-upload:progress', event => {
19
+ const { id, progress } = event.detail
20
+ const progressElement = document.getElementById(`resumable-upload-progress-${id}`)
21
+ progressElement.style.width = `${progress}%`
22
+ })
23
+
24
+ addEventListener('resumable-upload:error', event => {
25
+ event.preventDefault()
26
+ const { id, error } = event.detail
27
+ const element = document.getElementById(`resumable-upload-${id}`)
28
+ element.classList.add('resumable-upload--error')
29
+ element.setAttribute('title', error)
30
+ })
31
+
32
+ addEventListener('resumable-upload:end', event => {
33
+ const { id } = event.detail
34
+ const element = document.getElementById(`resumable-upload-${id}`)
35
+ element.classList.add('resumable-upload--complete')
36
+ })
@@ -0,0 +1,37 @@
1
+ .direct-upload {
2
+ display: inline-block;
3
+ position: relative;
4
+ padding: 2px 4px;
5
+ margin: 0 3px 3px 0;
6
+ border: 1px solid rgba(0, 0, 0, 0.3);
7
+ border-radius: 3px;
8
+ font-size: 11px;
9
+ line-height: 13px;
10
+ }
11
+
12
+ .direct-upload--pending {
13
+ opacity: 0.6;
14
+ }
15
+
16
+ .direct-upload__progress {
17
+ position: absolute;
18
+ top: 0;
19
+ left: 0;
20
+ bottom: 0;
21
+ opacity: 0.2;
22
+ background: #0076ff;
23
+ transition: width 120ms ease-out, opacity 60ms 60ms ease-in;
24
+ transform: translate3d(0, 0, 0);
25
+ }
26
+
27
+ .direct-upload--complete .direct-upload__progress {
28
+ opacity: 0.4;
29
+ }
30
+
31
+ .direct-upload--error {
32
+ border-color: red;
33
+ }
34
+
35
+ input[type=file][data-direct-upload-url][disabled] {
36
+ display: none;
37
+ }
@@ -0,0 +1,37 @@
1
+ .resumable-upload {
2
+ display: inline-block;
3
+ position: relative;
4
+ padding: 2px 4px;
5
+ margin: 0 3px 3px 0;
6
+ border: 1px solid rgba(0, 0, 0, 0.3);
7
+ border-radius: 3px;
8
+ font-size: 11px;
9
+ line-height: 13px;
10
+ }
11
+
12
+ .resumable-upload--pending {
13
+ opacity: 0.6;
14
+ }
15
+
16
+ .resumable-upload__progress {
17
+ position: absolute;
18
+ top: 0;
19
+ left: 0;
20
+ bottom: 0;
21
+ opacity: 0.2;
22
+ background: #0076ff;
23
+ transition: width 120ms ease-out, opacity 60ms 60ms ease-in;
24
+ transform: translate3d(0, 0, 0);
25
+ }
26
+
27
+ .resumable-upload--complete .resumable-upload__progress {
28
+ opacity: 0.4;
29
+ }
30
+
31
+ .resumable-upload--error {
32
+ border-color: red;
33
+ }
34
+
35
+ input[type=file][data-resumable-upload-url][disabled] {
36
+ display: none;
37
+ }
@@ -3,6 +3,12 @@
3
3
  module Kadim
4
4
  class ApplicationController < ActionController::Base
5
5
  protect_from_forgery with: :exception
6
+ before_action :import_main_app_polymorphic_mappings
6
7
  append_view_path Kadim::MemoryResolver.instance
8
+
9
+ private
10
+ def import_main_app_polymorphic_mappings
11
+ Kadim::Engine.routes.polymorphic_mappings.merge! Rails.application.routes.polymorphic_mappings
12
+ end
7
13
  end
8
14
  end
@@ -3,10 +3,43 @@
3
3
  module Kadim
4
4
  module ApplicationHelper
5
5
  def menu_links
6
+ kadim_link = link_to("Kadim", kadim.root_path)
6
7
  links = Kadim.app_model_paths.map(&:camelize).map(&:constantize).map do |model_klass|
7
8
  link_to model_klass.model_name.human(count: :many), model_klass
8
9
  end
9
- safe_join(links, " | ")
10
+ safe_join([kadim_link] + links, " | ")
11
+ end
12
+
13
+ def upload_type
14
+ case Kadim.upload_type
15
+ when :direct then { direct_upload: true }
16
+ when :resumable then { resumable_upload: true }
17
+ else {}
18
+ end
19
+ end
20
+
21
+ def method_missing(method, *args, &block)
22
+ if method.to_s.end_with?("_path", "_url")
23
+ if main_app.respond_to?(method)
24
+ main_app.send(method, *args)
25
+ else
26
+ super
27
+ end
28
+ else
29
+ super
30
+ end
31
+ end
32
+
33
+ def respond_to?(method)
34
+ if method.to_s.end_with?("_path", "_url")
35
+ if main_app.respond_to?(method)
36
+ true
37
+ else
38
+ super
39
+ end
40
+ else
41
+ super
42
+ end
10
43
  end
11
44
  end
12
45
  end
@@ -0,0 +1,18 @@
1
+ Usage:
2
+ rails generate kadim:host:scaffold_controller NAME [field:type field:type] [options]
3
+
4
+ Description:
5
+ This is a thin wrapper on scaffold_controller from Rails, if you don't specify any field the generated scaffold will
6
+ contain all model fields, except id and timestamps.
7
+
8
+ Please, use rails generate scaffold_controller --help to see all options.
9
+
10
+ Example:
11
+ `rails generate kadim:host:scaffold_controller CreditCard`
12
+
13
+ This will create:
14
+ Credit card controller with URLs like /credit_cards.
15
+ Controller: app/controllers/credit_cards_controller.rb
16
+ Test: test/controllers/credit_cards_controller_test.rb
17
+ Views: app/views/credit_cards/index.html.erb [...]
18
+ Helper: app/helpers/credit_cards_helper.rb
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kadim
4
+ module Generators
5
+ class ScaffoldControllerGenerator < Rails::Generators::NamedBase
6
+ def initialize(args = [], local_options = {}, config = {})
7
+ @initial_args = args
8
+ @initial_options = local_options
9
+ @initial_config = config
10
+ super
11
+ end
12
+
13
+ def scaffold_controller
14
+ model_path = name.underscore
15
+ unless Kadim.app_model_paths.include?(model_path)
16
+ puts "Are you sure \"#{name}\" is a model?"
17
+ return
18
+ end
19
+
20
+ @initial_args += Kadim.scaffold_attributes(model_path.camelize.constantize) if @initial_args.one?
21
+
22
+ Kadim.scaffold_controller(@initial_args, @initial_options, @initial_config)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ <%%= form_with(model: <%= model_resource_name %>, local: true) 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.full_messages.each do |message| %>
8
+ <li><%%= message %></li>
9
+ <%% end %>
10
+ </ul>
11
+ </div>
12
+ <%% end %>
13
+
14
+ <% attributes.each do |attribute| -%>
15
+ <div class="field">
16
+ <% if attribute.password_digest? -%>
17
+ <%%= form.label :password %>
18
+ <%%= form.password_field :password %>
19
+ </div>
20
+
21
+ <div class="field">
22
+ <%%= form.label :password_confirmation %>
23
+ <%%= form.password_field :password_confirmation %>
24
+ <% elsif attribute.attachment? -%>
25
+ <%%= form.label :<%= attribute.column_name %> %>
26
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, **upload_type %>
27
+ <% elsif attribute.attachments? -%>
28
+ <%%= form.label :<%= attribute.column_name %> %>
29
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, **upload_type, multiple: true %>
30
+ <% else -%>
31
+ <%%= form.label :<%= attribute.column_name %> %>
32
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %> %>
33
+ <% end -%>
34
+ </div>
35
+
36
+ <% end -%>
37
+ <div class="actions">
38
+ <%%= form.submit %>
39
+ </div>
40
+ <%% end %>
data/lib/kadim.rb CHANGED
@@ -4,6 +4,29 @@ require "kadim/engine"
4
4
  require "kadim/template/memory_resolver"
5
5
 
6
6
  module Kadim
7
+ # @overload upload_type
8
+ # @return [Symbol] current upload type used to scaffold file input fields
9
+ # @overload upload_type=(value)
10
+ # You can use the following symbols to set the upload type:
11
+ # * +:local+ - Uses ActiveStorage {https://guides.rubyonrails.org/active_storage_overview.html#disk-service Disk Service}
12
+ # * +:direct+ - Uses ActiveStorage {https://guides.rubyonrails.org/active_storage_overview.html#direct-uploads Direct Upload}
13
+ # * +:resumable+ - Uses {https://rubygems.org/gems/activestorage-resumable activestorage-resumable gem} to implement {https://cloud.google.com/storage/docs/performing-resumable-uploads Resumable Uploads} (supports only GCS)
14
+ # @param value [Symbol]
15
+ # @return [Symbol]
16
+ mattr_accessor :upload_type
17
+
18
+ def self.init
19
+ @@upload_type ||= if [:amazon, :google, :microsoft].include?(Rails.configuration.active_storage.service)
20
+ :direct
21
+ else
22
+ :local
23
+ end
24
+ end
25
+
26
+ def self.configure
27
+ yield self
28
+ end
29
+
7
30
  def self.app_model_paths
8
31
  return [] unless db_connection?
9
32
 
@@ -22,13 +45,25 @@ module Kadim
22
45
  scaffold_controllers
23
46
  end
24
47
 
48
+ def self.scaffold_controller(args, options, config)
49
+ current_namespace = Rails::Generators.namespace
50
+ Rails::Generators.namespace = Kadim
51
+
52
+ require "rails/generators/erb/scaffold/scaffold_generator"
53
+ Erb::Generators::ScaffoldGenerator.source_paths.prepend(
54
+ File.expand_path("generators/kadim/scaffold_controller/templates", __dir__)
55
+ )
56
+
57
+ generator = Rails::Generators::ScaffoldControllerGenerator.new(args, options, config)
58
+ source_path_idx = generator.class.source_paths.index { |source_path| source_path.include?("jbuilder") }
59
+ generator.class.source_paths[source_path_idx] = generator.class.source_root if source_path_idx
60
+ generator.invoke_all
61
+ ensure
62
+ Rails::Generators.namespace = current_namespace
63
+ end
64
+
25
65
  def self.scaffold_attributes(model_klass)
26
- model_klass.columns
27
- .reject { |column| %w[id created_at updated_at].include?(column.name) }
28
- .sort_by(&:name)
29
- .map { |column| [column.name, column.type] }
30
- .to_h
31
- .map { |k, v| "#{k}:#{v}" }
66
+ database_attributes(model_klass) + attachment_attributes(model_klass)
32
67
  end
33
68
 
34
69
  class << self
@@ -58,31 +93,41 @@ module Kadim
58
93
  Rails.application.load_generators
59
94
  require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
60
95
 
61
- current_namespace = Rails::Generators.namespace
62
- Rails::Generators.namespace = Kadim
63
96
  app_model_paths.each do |model_name|
64
97
  next if Kadim.const_defined?("#{model_name.pluralize}_controller".camelize, false)
98
+ model_klass = model_name.camelize.constantize
99
+ return unless model_klass.table_exists?
100
+
101
+ args = [model_name, *scaffold_attributes(model_klass)]
102
+ options = ["--force", "--quiet", "--no-test-framework", "--no-helper", "--template-engine=erb"]
103
+ config = { destination_root: Rails.root.join("tmp", "kadim") }
65
104
 
66
- scaffold_controller(model_name)
105
+ scaffold_controller(args, options, config)
67
106
  end
68
107
  load_kadim_controllers
69
108
  load_kadim_views
70
- ensure
71
- Rails::Generators.namespace = current_namespace
72
109
  end
73
110
 
74
- def scaffold_controller(model_name)
75
- model_klass = model_name.camelize.constantize
76
- return unless model_klass.table_exists?
77
-
78
- generator = Rails::Generators::ScaffoldControllerGenerator.new(
79
- [model_name, *scaffold_attributes(model_klass)],
80
- ["--force", "--quiet", "--no-test-framework", "--no-helper", "--template-engine=erb"],
81
- destination_root: Rails.root.join("tmp", "kadim")
82
- )
83
- source_path_idx = generator.class.source_paths.index { |source_path| source_path.include?("jbuilder") }
84
- generator.class.source_paths[source_path_idx] = generator.class.source_root if source_path_idx
85
- generator.invoke_all
111
+ def database_attributes(model_klass)
112
+ model_klass.columns
113
+ .reject { |column| %w[id created_at updated_at].include?(column.name) }
114
+ .sort_by(&:name)
115
+ .map { |column| [column.name, column.type] }
116
+ .to_h
117
+ .map { |k, v| "#{k}:#{v}" }
118
+ end
119
+
120
+ def attachment_attributes(model_klass)
121
+ model_klass.attachment_reflections
122
+ .values
123
+ .map do |reflection|
124
+ attribute_type = if reflection.is_a?(ActiveStorage::Reflection::HasOneAttachedReflection)
125
+ "attachment"
126
+ else
127
+ "attachments"
128
+ end
129
+ "#{reflection.name}:#{attribute_type}"
130
+ end
86
131
  end
87
132
 
88
133
  def load_kadim_controllers
@@ -105,8 +150,7 @@ module Kadim
105
150
  end
106
151
 
107
152
  def db_connection?
108
- ActiveRecord::Base.establish_connection # Establishes connection
109
- ActiveRecord::Base.connection # Calls connection object
153
+ ActiveRecord::Base.connection
110
154
  ActiveRecord::Base.connected?
111
155
  rescue ActiveRecord::AdapterNotFound, ActiveRecord::AdapterNotSpecified, ActiveRecord::NoDatabaseError
112
156
  false
data/lib/kadim/engine.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "activestorage/resumable"
4
+
3
5
  module Kadim
4
6
  class Engine < ::Rails::Engine
5
7
  isolate_namespace Kadim
@@ -12,6 +14,7 @@ module Kadim
12
14
  end
13
15
 
14
16
  config.to_prepare do
17
+ Kadim.init
15
18
  Kadim.bootstrap_controllers
16
19
  end
17
20
 
@@ -53,6 +53,7 @@ module Kadim
53
53
 
54
54
  private
55
55
  def find_templates(name, prefix, partial, details, locals = [])
56
+ details[:handlers].map! { |handler| handler.to_sym }
56
57
  return unless details[:formats].include?(:html) && details[:handlers].include?(:erb)
57
58
 
58
59
  body = @store.find(name, prefix, partial)
data/lib/kadim/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kadim
4
- VERSION = "0.2.3"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kadim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kadu Diógenes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-11 00:00:00.000000000 Z
11
+ date: 2019-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activestorage-resumable
@@ -24,6 +24,26 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: google-cloud-storage
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.21.0
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '2.0'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.21.0
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: rails
29
49
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +86,20 @@ dependencies:
66
86
  - - "~>"
67
87
  - !ruby/object:Gem::Version
68
88
  version: 0.9.4
89
+ - !ruby/object:Gem::Dependency
90
+ name: guard-rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 4.7.3
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 4.7.3
69
103
  - !ruby/object:Gem::Dependency
70
104
  name: guard
71
105
  requirement: !ruby/object:Gem::Requirement
@@ -81,19 +115,19 @@ dependencies:
81
115
  - !ruby/object:Gem::Version
82
116
  version: 2.16.1
83
117
  - !ruby/object:Gem::Dependency
84
- name: guard-rspec
118
+ name: launchy
85
119
  requirement: !ruby/object:Gem::Requirement
86
120
  requirements:
87
121
  - - "~>"
88
122
  - !ruby/object:Gem::Version
89
- version: 4.7.3
123
+ version: 2.4.3
90
124
  type: :development
91
125
  prerelease: false
92
126
  version_requirements: !ruby/object:Gem::Requirement
93
127
  requirements:
94
128
  - - "~>"
95
129
  - !ruby/object:Gem::Version
96
- version: 4.7.3
130
+ version: 2.4.3
97
131
  - !ruby/object:Gem::Dependency
98
132
  name: nokogiri
99
133
  requirement: !ruby/object:Gem::Requirement
@@ -151,33 +185,33 @@ dependencies:
151
185
  - !ruby/object:Gem::Version
152
186
  version: 2.0.3
153
187
  - !ruby/object:Gem::Dependency
154
- name: rspec-rails
188
+ name: redcarpet
155
189
  requirement: !ruby/object:Gem::Requirement
156
190
  requirements:
157
191
  - - "~>"
158
192
  - !ruby/object:Gem::Version
159
- version: 3.8.0
193
+ version: 3.5.0
160
194
  type: :development
161
195
  prerelease: false
162
196
  version_requirements: !ruby/object:Gem::Requirement
163
197
  requirements:
164
198
  - - "~>"
165
199
  - !ruby/object:Gem::Version
166
- version: 3.8.0
200
+ version: 3.5.0
167
201
  - !ruby/object:Gem::Dependency
168
- name: rubocop
202
+ name: rspec-rails
169
203
  requirement: !ruby/object:Gem::Requirement
170
204
  requirements:
171
205
  - - "~>"
172
206
  - !ruby/object:Gem::Version
173
- version: 0.72.0
207
+ version: 3.8.0
174
208
  type: :development
175
209
  prerelease: false
176
210
  version_requirements: !ruby/object:Gem::Requirement
177
211
  requirements:
178
212
  - - "~>"
179
213
  - !ruby/object:Gem::Version
180
- version: 0.72.0
214
+ version: 3.8.0
181
215
  - !ruby/object:Gem::Dependency
182
216
  name: rubocop-performance
183
217
  requirement: !ruby/object:Gem::Requirement
@@ -220,6 +254,20 @@ dependencies:
220
254
  - - "~>"
221
255
  - !ruby/object:Gem::Version
222
256
  version: 1.36.0
257
+ - !ruby/object:Gem::Dependency
258
+ name: rubocop
259
+ requirement: !ruby/object:Gem::Requirement
260
+ requirements:
261
+ - - "~>"
262
+ - !ruby/object:Gem::Version
263
+ version: 0.72.0
264
+ type: :development
265
+ prerelease: false
266
+ version_requirements: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - "~>"
269
+ - !ruby/object:Gem::Version
270
+ version: 0.72.0
223
271
  - !ruby/object:Gem::Dependency
224
272
  name: selenium-webdriver
225
273
  requirement: !ruby/object:Gem::Requirement
@@ -274,7 +322,11 @@ files:
274
322
  - Rakefile
275
323
  - app/assets/config/kadim_manifest.js
276
324
  - app/assets/javascripts/kadim/application.js
325
+ - app/assets/javascripts/kadim/direct_upload.js
326
+ - app/assets/javascripts/kadim/resumable_upload.js
277
327
  - app/assets/stylesheets/kadim/application.css
328
+ - app/assets/stylesheets/kadim/direct_upload.css
329
+ - app/assets/stylesheets/kadim/resumable_upload.css
278
330
  - app/controllers/kadim/application_controller.rb
279
331
  - app/helpers/kadim/application_helper.rb
280
332
  - app/jobs/kadim/application_job.rb
@@ -284,8 +336,9 @@ files:
284
336
  - config/routes.rb
285
337
  - lib/generators/kadim/host/USAGE
286
338
  - lib/generators/kadim/host/host_generator.rb
287
- - lib/generators/kadim/host/scaffold_controller/USAGE
288
- - lib/generators/kadim/host/scaffold_controller/scaffold_controller_generator.rb
339
+ - lib/generators/kadim/scaffold_controller/USAGE
340
+ - lib/generators/kadim/scaffold_controller/scaffold_controller_generator.rb
341
+ - lib/generators/kadim/scaffold_controller/templates/_form.html.erb.tt
289
342
  - lib/kadim.rb
290
343
  - lib/kadim/engine.rb
291
344
  - lib/kadim/template/memory_resolver.rb
@@ -1,16 +0,0 @@
1
- Description:
2
- Hosts on your application the files generated in runtime by `kadim` for the giving resource. This turns the
3
- responsability for the resource to your application.
4
-
5
- The model attributes are automatically detected by `kadim`.
6
- resource.
7
-
8
- Example:
9
- `rails generate kadim:host:scaffold_controller CreditCard`
10
-
11
- This will create:
12
- Credit card controller with URLs like /credit_cards.
13
- Controller: app/controllers/credit_cards_controller.rb
14
- Test: test/controllers/credit_cards_controller_test.rb
15
- Views: app/views/credit_cards/index.html.erb [...]
16
- Helper: app/helpers/credit_cards_helper.rb
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kadim
4
- module Host
5
- class ScaffoldControllerGenerator < Rails::Generators::NamedBase
6
- source_root File.expand_path("templates", __dir__)
7
-
8
- def scaffold_controller
9
- model_path = name.underscore
10
- unless Kadim.app_model_paths.include?(model_path)
11
- puts "Are you sure \"#{name}\" is a model?"
12
- return
13
- end
14
-
15
-
16
- Rails::Generators.namespace = Kadim
17
- generator = Rails::Generators::ScaffoldControllerGenerator.new(
18
- [model_path, *Kadim.scaffold_attributes(model_path.camelize.constantize)],
19
- ["--no-jbuilder", "--template-engine=erb"],
20
- behavior: behavior,
21
- destination_root: destination_root
22
- )
23
-
24
- # jbuilder 2.9.1 controller template uses a method removed from Rails6
25
- # https://github.com/rails/jbuilder/issues/470
26
- source_path_idx = generator.class.source_paths.index { |source_path| source_path.include?("jbuilder") }
27
- generator.class.source_paths[source_path_idx] = generator.class.source_root if source_path_idx
28
-
29
- generator.invoke_all
30
- end
31
- end
32
- end
33
- end