kadim 0.2.3 → 0.3.0

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