plutonium 0.8.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -0
  3. data/Rakefile +10 -0
  4. data/app/assets/build/plutonium.js +5122 -0
  5. data/app/assets/javascripts/controllers/index.js +34 -0
  6. data/app/assets/javascripts/controllers/resource_dismiss_controller.js +37 -0
  7. data/app/assets/javascripts/controllers/resource_drop_down_controller.js +29 -0
  8. data/app/assets/javascripts/plutonium-app.js +7 -0
  9. data/app/assets/javascripts/plutonium.js +1 -0
  10. data/app/assets/{js → javascripts}/turbo/index.js +1 -1
  11. data/app/views/application/_flash.html.erb +1 -1
  12. data/app/views/application/_flash_alerts.html.erb +51 -7
  13. data/app/views/application/_flash_toasts.html.erb +53 -23
  14. data/app/views/application/_resource_header.html.erb +563 -561
  15. data/app/views/components/form/form_builder.rb +2 -2
  16. data/app/views/components/form/form_component.html.erb +5 -6
  17. data/app/views/components/interactive_action_form/interactive_action_form_component.html.erb +1 -1
  18. data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.html.erb +66 -0
  19. data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.rb +23 -0
  20. data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_controller.js +64 -0
  21. data/app/views/components/sidebar/sidebar_component.html.erb +61 -63
  22. data/app/views/components/table_search_input/table_search_input_component.html.erb +1 -1
  23. data/app/views/layouts/resource.html copy.erb +0 -2
  24. data/app/views/layouts/resource.html.erb +1 -3
  25. data/app/views/layouts/rodauth.html.erb +0 -1
  26. data/app/views/resource/_interactive_resource_action_form.html.erb +1 -1
  27. data/css.manifest +3 -0
  28. data/esbuild.config.js +44 -0
  29. data/exe/pug +6 -0
  30. data/lib/generators/pu/gen/component/component_generator.rb +14 -5
  31. data/lib/generators/pu/gen/pug/pug_generator.rb +1 -1
  32. data/lib/generators/pu/lib/plutonium_generators/cli.rb +42 -0
  33. data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +86 -72
  34. data/lib/generators/pu/lib/plutonium_generators/generator.rb +1 -5
  35. data/lib/generators/pu/lib/plutonium_generators.rb +8 -0
  36. data/lib/generators/pu/rodauth/install_generator.rb +1 -2
  37. data/lib/plutonium/core/actions/collection.rb +1 -1
  38. data/lib/plutonium/core/controllers/authorizable.rb +4 -4
  39. data/lib/plutonium/core/fields/inputs/base.rb +1 -1
  40. data/lib/plutonium/core/fields/inputs/nested_input.rb +57 -0
  41. data/lib/plutonium/core/fields/inputs/noop_input.rb +1 -1
  42. data/lib/plutonium/core/fields/inputs/phone_input.rb +1 -1
  43. data/lib/plutonium/core/fields/inputs/polymorphic_belongs_to_association_input.rb +1 -1
  44. data/lib/plutonium/core/fields/inputs/simple_form_association_input.rb +1 -1
  45. data/lib/plutonium/core/fields/inputs/simple_form_input.rb +1 -1
  46. data/lib/plutonium/pkg/base.rb +0 -4
  47. data/lib/plutonium/railtie.rb +10 -2
  48. data/lib/plutonium/resource/policy.rb +6 -0
  49. data/lib/plutonium/resource/presenter.rb +35 -0
  50. data/lib/plutonium/resource/record.rb +40 -7
  51. data/lib/plutonium/version.rb +1 -1
  52. data/lib/plutonium.rb +17 -14
  53. data/package.json +4 -3
  54. data/postcss.config.js +1 -1
  55. data/public/plutonium-assets/plutonium-app-36KN5FVJ.js +6 -0
  56. data/public/plutonium-assets/plutonium-app-36KN5FVJ.js.map +7 -0
  57. data/public/plutonium-assets/plutonium.50232e35b5495f5ad90d.css +3415 -0
  58. data/tailwind.config.js +11 -12
  59. data/templates/base.rb +8 -0
  60. metadata +28 -21
  61. data/app/assets/js/controllers/application.js +0 -6
  62. data/app/assets/js/controllers/dropdown_controller.js +0 -12
  63. data/app/assets/js/controllers/index.js +0 -21
  64. data/app/assets/js/plutonium.js +0 -2
  65. data/build.js +0 -12
  66. data/lib/generators/pu/gem/pagy/pagy_generator.rb +0 -25
  67. data/lib/generators/pu/gem/pagy/templates/config/initializers/pagy.rb +0 -4
  68. data/lib/generators/pu/gem/rabl/rabl_generator.rb +0 -25
  69. data/lib/generators/pu/gem/rabl/templates/.keep +0 -0
  70. data/lib/generators/pu/gem/rabl/templates/config/initializers/rabl.rb +0 -60
  71. data/lib/generators/pu/gem/simple_form/simple_form_generator.rb +0 -25
  72. data/lib/generators/pu/gem/simple_form/templates/.keep +0 -0
  73. /data/{lib/generators/pu/gem/pagy/templates → app/assets/build}/.keep +0 -0
  74. /data/app/assets/{js → javascripts}/turbo/turbo_actions.js +0 -0
  75. /data/app/assets/{js → javascripts}/turbo/turbo_debug.js +0 -0
  76. /data/app/assets/{js → javascripts}/turbo/turbo_frame_monkey_patch.js +0 -0
  77. /data/app/assets/{css → stylesheets}/plutonium.css +0 -0
@@ -11,87 +11,89 @@ module PlutoniumGenerators
11
11
  protected
12
12
 
13
13
  #
14
- # Sets the ruby version for the project in .ruby-version and Gemfile to `PlutoniumGenerators::RUBY_VERSION`
14
+ # Sets the ruby version for the project in .ruby-version and Gemfile to `version`
15
15
  #
16
- # @return [void]
17
- #
18
- def set_ruby_version!
19
- log :set_ruby_version!, PlutoniumGenerators::RUBY_VERSION
20
-
21
- in_root do
22
- create_file ".ruby-version", PlutoniumGenerators::RUBY_VERSION, force: true, verbose: false
23
- gsub_file "Gemfile", /^ruby ["'].*["']/, "ruby '~> #{PlutoniumGenerators::RUBY_VERSION}'", verbose: false
24
- end
25
- end
26
-
27
- #
28
- # Adds a new gem into the Gemfile
29
- # Existing directives are updated if they do not match
30
- # When `:group` is specified, the gem is inserted into the approriate gem group.
31
- #
32
- # @param [String] name the name of the gem
33
- # @param [Hash] **kwargs set of options to append see #super
16
+ # @param [string] version semantic ruby version you want to use e.g. 3.3.0
34
17
  #
35
18
  # @return [void]
36
19
  #
37
- def gem(name, **kwargs)
38
- groups = Array(kwargs.delete(:group))
20
+ def set_ruby_version!(version)
21
+ log :set_ruby_version!, version
39
22
 
40
23
  in_root do
41
- begin
42
- # Create a temp gemfile
43
- File.rename("Gemfile", "Gemfile.bak")
44
- File.write("Gemfile", "")
45
- # Generate the directive
46
- super
47
- # Get the generated directive
48
- directive = gemfile.strip
49
- ensure
50
- # Restore our gemfile
51
- File.delete "Gemfile"
52
- File.rename "Gemfile.bak", "Gemfile"
53
- end
54
-
55
- pattern = /^# gem ['"]#{name}['"].*/
56
- if gemfile.match(pattern)
57
- # Replace commented out directive
58
- gsub_file("Gemfile", pattern, directive)
59
- break
60
- end
61
-
62
- # Remove existing directive
63
- remove_gem name
64
-
65
- # Insert the new directive
66
- if groups != []
67
- str = groups.sort.map(&:inspect).join(", ")
68
- after_sentinel = "group #{str} do\n"
69
-
70
- unless File.read("Gemfile").match?(/^#{after_sentinel}/)
71
- inject_into_file "Gemfile", "\n#{after_sentinel}end\n"
72
- end
73
- else
74
- after_sentinel = "# Project gems\n\n"
75
- unless File.read("Gemfile").match?(/^#{after_sentinel}/)
76
- inject_into_file "Gemfile", "\n#{after_sentinel}", after: /^ruby .*\n/
77
- end
78
- end
79
-
80
- inject_into_file "Gemfile", "#{directive}\n", after: /^#{after_sentinel}/
24
+ create_file ".ruby-version", version, force: true, verbose: false
25
+ gsub_file "Gemfile", /^ruby ["'].*["']/, "ruby '~> #{version}'", verbose: false
81
26
  end
82
27
  end
83
28
 
84
- #
85
- # Removes a gem and any preceeding comments from the Gemfile
86
- #
87
- # @param gem [String] the name of the gem to remove
88
- #
89
- # @return [void]
90
- #
91
- def remove_gem(gem)
92
- log :remove_gem, gem
93
- gsub_file "Gemfile", /(:?^.*#.*\n)*.*gem ['"]#{gem}['"].*\n/, "", verbose: false
94
- end
29
+ # #
30
+ # # Adds a new gem into the Gemfile
31
+ # # Existing directives are updated if they do not match
32
+ # # When `:group` is specified, the gem is inserted into the approriate gem group.
33
+ # #
34
+ # # @param [String] name the name of the gem
35
+ # # @param [Hash] **kwargs set of options to append see #super
36
+ # #
37
+ # # @return [void]
38
+ # #
39
+ # def gem(name, **kwargs)
40
+ # groups = Array(kwargs.delete(:group))
41
+
42
+ # in_root do
43
+ # begin
44
+ # # Create a temp gemfile
45
+ # File.rename("Gemfile", "Gemfile.bak")
46
+ # File.write("Gemfile", "")
47
+ # # Generate the directive
48
+ # super
49
+ # # Get the generated directive
50
+ # directive = gemfile.strip
51
+ # ensure
52
+ # # Restore our gemfile
53
+ # File.delete "Gemfile"
54
+ # File.rename "Gemfile.bak", "Gemfile"
55
+ # end
56
+
57
+ # pattern = /^# gem ['"]#{name}['"].*/
58
+ # if gemfile.match(pattern)
59
+ # # Replace commented out directive
60
+ # gsub_file("Gemfile", pattern, directive)
61
+ # break
62
+ # end
63
+
64
+ # # Remove existing directive
65
+ # remove_gem name
66
+
67
+ # # Insert the new directive
68
+ # if groups != []
69
+ # str = groups.sort.map(&:inspect).join(", ")
70
+ # after_sentinel = "group #{str} do\n"
71
+
72
+ # unless File.read("Gemfile").match?(/^#{after_sentinel}/)
73
+ # inject_into_file "Gemfile", "\n#{after_sentinel}end\n"
74
+ # end
75
+ # else
76
+ # after_sentinel = "# Project gems\n\n"
77
+ # unless File.read("Gemfile").match?(/^#{after_sentinel}/)
78
+ # inject_into_file "Gemfile", "\n#{after_sentinel}", after: /^ruby .*\n/
79
+ # end
80
+ # end
81
+
82
+ # inject_into_file "Gemfile", "#{directive}\n", after: /^#{after_sentinel}/
83
+ # end
84
+ # end
85
+
86
+ # #
87
+ # # Removes a gem and any preceeding comments from the Gemfile
88
+ # #
89
+ # # @param gem [String] the name of the gem to remove
90
+ # #
91
+ # # @return [void]
92
+ # #
93
+ # def remove_gem(gem)
94
+ # log :remove_gem, gem
95
+ # gsub_file "Gemfile", /(:?^.*#.*\n)*.*gem ['"]#{gem}['"].*\n/, "", verbose: false
96
+ # end
95
97
 
96
98
  #
97
99
  # Evaluates the given template and merges it with the project's docker-compose.yml
@@ -348,6 +350,18 @@ module PlutoniumGenerators
348
350
  File.read("Gemfile")
349
351
  end
350
352
  end
353
+
354
+ def bundle(*gems)
355
+ Bundler.with_unbundled_env do
356
+ run "bundle add #{Array(gems).join " "}"
357
+ end
358
+ end
359
+
360
+ def unbundle(*gems)
361
+ Bundler.with_unbundled_env do
362
+ run "bundle remove #{Array(gems).join " "}"
363
+ end
364
+ end
351
365
  end
352
366
  end
353
367
  end
@@ -64,12 +64,8 @@ module PlutoniumGenerators
64
64
  @prompt ||= TTY::Prompt.new
65
65
  end
66
66
 
67
- def rails?
68
- PlutoniumGenerators.rails?
69
- end
70
-
71
67
  def appname
72
- rails? ? Rails.application.class.module_parent.name : "PlutoniumGenerators"
68
+ defined?(Rails.application) ? Rails.application.class.module_parent.name : "PlutoniumGenerators"
73
69
  end
74
70
 
75
71
  def app_name
@@ -1,7 +1,15 @@
1
1
  require "zeitwerk"
2
2
 
3
3
  loader = Zeitwerk::Loader.for_gem # (warn_on_extra_files: false)
4
+ loader.inflector.inflect(
5
+ "cli" => "CLI"
6
+ )
4
7
  loader.setup
5
8
 
6
9
  module PlutoniumGenerators
10
+ class << self
11
+ def cli?
12
+ ENV["PU_CLI"] == "1"
13
+ end
14
+ end
7
15
  end
@@ -18,8 +18,7 @@ module Pu
18
18
 
19
19
  def add_rodauth
20
20
  Bundler.with_unbundled_env do
21
- run "bundle add bcrypt"
22
- run "bundle add rodauth-rails"
21
+ run "bundle add bcrypt rodauth-rails"
23
22
  end
24
23
  end
25
24
 
@@ -9,7 +9,7 @@ module Plutonium
9
9
  end
10
10
 
11
11
  def permitted_for(policy)
12
- Collection.new(@collection.select { |name, action| policy.send :"#{action.name}?" })
12
+ Collection.new(@collection.select { |name, action| policy.send_with_report :"#{action.name}?" })
13
13
  end
14
14
 
15
15
  def collection_actions
@@ -42,7 +42,7 @@ module Plutonium
42
42
  end
43
43
 
44
44
  def permitted_attributes
45
- @permitted_attributes ||= current_policy.send :"permitted_attributes_for_#{action_name}"
45
+ @permitted_attributes ||= current_policy.send_with_report :"permitted_attributes_for_#{action_name}"
46
46
  end
47
47
 
48
48
  def current_policy
@@ -52,9 +52,9 @@ module Plutonium
52
52
  end
53
53
  end
54
54
 
55
- def parent_policy
56
- @parent_policy ||= policy(current_parent) if current_parent.present?
57
- end
55
+ # def parent_policy
56
+ # @parent_policy ||= policy(current_parent) if current_parent.present?
57
+ # end
58
58
  end
59
59
  end
60
60
  end
@@ -10,7 +10,7 @@ module Plutonium
10
10
  @user_options = user_options
11
11
  end
12
12
 
13
- def render(f, record, **)
13
+ def render(view_context, f, record, **)
14
14
  raise NotImplementedError, "#{self.class}#render"
15
15
  end
16
16
 
@@ -0,0 +1,57 @@
1
+ module Plutonium
2
+ module Core
3
+ module Fields
4
+ module Inputs
5
+ class NestedInput < Base
6
+ include Plutonium::Core::Definers::InputDefiner
7
+
8
+ attr_reader :inputs, :resource_class
9
+
10
+ def initialize(name, inputs:, resource_class:, allow_destroy:, update_only:, limit:, **user_options)
11
+ @inputs = inputs
12
+ @resource_class = resource_class
13
+ @allow_destroy = allow_destroy
14
+ @update_only = update_only
15
+ @limit = limit
16
+
17
+ super(name, **user_options)
18
+ end
19
+
20
+ def render(view_context, f, record, **opts)
21
+ opts = options.deep_merge opts
22
+ view_context.render_component :nested_resource_form_fields, form: f, **opts
23
+ end
24
+
25
+ def collect(params)
26
+ attributes = {}
27
+ params[param].each do |index, nested_params|
28
+ collected = defined_inputs.collect_all(nested_params)
29
+ collected[:id] = nested_params[:id] if nested_params.key?(:id) && !@update_only
30
+ collected[:_destroy] = nested_params[:_destroy] if @allow_destroy
31
+ attributes[index] = collected
32
+ end
33
+
34
+ {param => attributes}
35
+ end
36
+
37
+ private
38
+
39
+ def param = :"#{name}_attributes"
40
+
41
+ def input_options = {
42
+ name:,
43
+ resource_class:,
44
+ allow_destroy: @allow_destroy,
45
+ update_only: @update_only,
46
+ limit: @limit,
47
+ inputs: defined_inputs
48
+ }
49
+
50
+ def defined_inputs
51
+ @defined_inputs ||= defined_inputs_for(*inputs)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -6,7 +6,7 @@ module Plutonium
6
6
  def initialize(*)
7
7
  end
8
8
 
9
- def render(f, record, **)
9
+ def render(view_context, f, record, **)
10
10
  end
11
11
 
12
12
  def collect(params)
@@ -3,7 +3,7 @@ module Plutonium
3
3
  module Fields
4
4
  module Inputs
5
5
  class PhoneInput < SimpleFormInput
6
- # def render(f, record, **opts)
6
+ # def render(view_context, f, record, **opts)
7
7
  # opts = options.deep_merge opts
8
8
  # opts.delete(:as)
9
9
  # f.input name, **opts
@@ -3,7 +3,7 @@ module Plutonium
3
3
  module Fields
4
4
  module Inputs
5
5
  class PolymorphicBelongsToAssociationInput < SimpleFormAssociationInput
6
- def render(f, record, **opts)
6
+ def render(view_context, f, record, **opts)
7
7
  opts = options.deep_merge opts
8
8
  f.input param, **opts
9
9
  end
@@ -10,7 +10,7 @@ module Plutonium
10
10
  super(name, **user_options)
11
11
  end
12
12
 
13
- def render(f, record, **opts)
13
+ def render(view_context, f, record, **opts)
14
14
  opts = options.deep_merge opts
15
15
  f.association name, **opts
16
16
  end
@@ -3,7 +3,7 @@ module Plutonium
3
3
  module Fields
4
4
  module Inputs
5
5
  class SimpleFormInput < Base
6
- def render(f, record, **opts)
6
+ def render(view_context, f, record, **opts)
7
7
  opts = options.deep_merge opts
8
8
  f.input name, **opts
9
9
  end
@@ -17,10 +17,6 @@ module Plutonium
17
17
  add_view_paths_initializer.instance_variable_set(:@block, ->(app) {})
18
18
  end
19
19
  end
20
-
21
- def scoped_to_entity?
22
- raise NotImplementedError, "scoped_to_entity?"
23
- end
24
20
  end
25
21
  end
26
22
  end
@@ -2,7 +2,15 @@ require "view_component"
2
2
 
3
3
  module Plutonium
4
4
  class Railtie < Rails::Railtie
5
- initializer "plutonium.assets_server" do
5
+ config.plutonium = ActiveSupport::OrderedOptions.new
6
+
7
+ initializer "plutonium.append_assets_path" do |app|
8
+ config.to_prepare do
9
+ Rails.application.config.assets.paths << Plutonium.root.join("app/assets/build").to_s
10
+ end
11
+ end
12
+
13
+ initializer "plutonium.asset_server" do
6
14
  # setup a middleware to serve our assets
7
15
  config.app_middleware.insert_before(
8
16
  ActionDispatch::Static,
@@ -17,7 +25,7 @@ module Plutonium
17
25
  )
18
26
  end
19
27
 
20
- initializer "plutonium.view_components" do
28
+ initializer "plutonium.view_components_capture_compat" do
21
29
  config.view_component.capture_compatibility_patch_enabled = true
22
30
  end
23
31
  end
@@ -6,6 +6,12 @@ module Plutonium
6
6
  class Scope < Plutonium::Policy::Scope
7
7
  end
8
8
 
9
+ def send_with_report(method)
10
+ raise NotImplementedError, "#{self.class.name} does not implement the required #{method}" unless respond_to? method
11
+
12
+ send method
13
+ end
14
+
9
15
  # Core actions
10
16
 
11
17
  def create?
@@ -37,6 +37,41 @@ module Plutonium
37
37
  define_action Plutonium::Core::Actions::InteractiveAction.new(name, interaction:, **)
38
38
  end
39
39
 
40
+ # TODO: move this to its own definer
41
+ def define_nested_input(name, inputs:, model_class: nil, **options)
42
+ nested_attribute_options = resource_class.all_nested_attributes_options[name]
43
+
44
+ nested_attribute_options_class = nested_attribute_options&.[](:class)
45
+ if nested_attribute_options_class.nil? && model_class.nil?
46
+ raise ArgumentError, "model_class is required if your field is not an association or is polymorphic"
47
+ end
48
+ model_class ||= nested_attribute_options_class
49
+
50
+ macro = nested_attribute_options&.[](:macro)
51
+ allow_destroy = nested_attribute_options&.[](:allow_destroy).presence
52
+ update_only = nested_attribute_options&.[](:update_only).presence
53
+ limit = if macro == :has_one
54
+ 1
55
+ elsif options.key?(:limit)
56
+ options[:limit]
57
+ else
58
+ nested_attribute_options&.[](:limit)
59
+ end
60
+
61
+ input = Plutonium::Core::Fields::Inputs::NestedInput.new(
62
+ name,
63
+ inputs:,
64
+ allow_destroy: options.key?(:allow_destroy) ? options[:allow_destroy] : allow_destroy,
65
+ update_only: options.key?(:update_only) ? options[:update_only] : update_only,
66
+ limit: limit,
67
+ resource_class: model_class,
68
+ **options
69
+ )
70
+ yield input if block_given?
71
+
72
+ define_input name, input:
73
+ end
74
+
40
75
  def resource_class = context.resource_class
41
76
  end
42
77
  end
@@ -117,6 +117,23 @@ module Plutonium
117
117
  @has_many_association_routes ||= reflect_on_all_associations(:has_many).map { |assoc| assoc.klass.model_name.plural }
118
118
  end
119
119
 
120
+ def all_nested_attributes_options
121
+ unless Rails.env.local?
122
+ return @all_nested_attributes_options if defined?(@all_nested_attributes_options)
123
+ end
124
+
125
+ @all_nested_attributes_options = reflect_on_all_associations.map do |association|
126
+ setter_method = "#{association.name}_attributes="
127
+ if method_defined?(setter_method)
128
+ [association.name, {
129
+ **nested_attributes_options[association.name],
130
+ macro: association.macro,
131
+ class: association.polymorphic? ? nil : association.klass
132
+ }]
133
+ end
134
+ end.compact.to_h
135
+ end
136
+
120
137
  #
121
138
  # Returns the strong parameters definition for the given attribute names
122
139
  #
@@ -127,6 +144,8 @@ module Plutonium
127
144
  #
128
145
  def strong_parameters_for(*attributes)
129
146
  # attributes that are passed but we do not have a model/database backed definition for e.g. virtual attributes.
147
+ # if they are passed and we are not expecting them, our inputs will filter them out as they apply an additional level
148
+ # of filtering
130
149
  unbacked = attributes - strong_parameters_definition.keys
131
150
 
132
151
  # attributes backed by some model/database definition
@@ -147,8 +166,13 @@ module Plutonium
147
166
  private
148
167
 
149
168
  def strong_parameters_definition
150
- # @strong_parameters ||= begin
169
+ unless Rails.env.local?
170
+ return @strong_parameters if defined?(@strong_parameters)
171
+ end
172
+
151
173
  @strong_parameters = begin
174
+ # Columns
175
+
152
176
  content_column_parameters = content_column_field_names.map do |name|
153
177
  column = columns_hash[name.to_s]
154
178
 
@@ -160,21 +184,30 @@ module Plutonium
160
184
  end
161
185
  parameters = content_column_parameters.to_h
162
186
 
163
- # TODO: add nested support
187
+ # Associations
164
188
 
165
- # TODO:
166
189
  parameters.merge! reflect_on_all_associations(:belongs_to)
167
190
  .map { |reflection|
168
- input_param = (reflection.respond_to?(:options) && reflection.options[:foreign_key]) || :"#{reflection.name}_id"
191
+ input_param = reflection.respond_to?(:options) ? reflection.options[:foreign_key] : :"#{reflection.name}_id"
169
192
  [reflection.name, {input_param => nil}]
170
193
  }
171
194
  .to_h
172
195
 
173
- parameters.merge! has_one_association_field_names.map { |name| [name, {name => nil}] }.to_h
196
+ parameters.merge! has_many_association_field_names
197
+ .map { |name| [name, {"#{name.to_s.singularize}_ids": []}] }
198
+ .to_h
199
+
200
+ # Attachments
201
+
202
+ parameters.merge! has_many_attached_field_names.map { |name| [name, {name => []}] }.to_h
203
+
174
204
  parameters.merge! has_one_attached_field_names.map { |name| [name, {name => nil}] }.to_h
175
205
 
176
- parameters.merge! has_many_association_field_names.map { |name| [name, {"#{name.to_s.singularize}_ids": []}] }.to_h
177
- parameters.merge! has_many_attached_field_names.map { |name| [name, {name: []}] }.to_h
206
+ # Nested Attributes
207
+
208
+ parameters.merge! all_nested_attributes_options.keys
209
+ .map { |name| [name, {"#{name}_attributes" => {}}] }
210
+ .to_h
178
211
 
179
212
  # e.g.
180
213
  # {:name=>{:name=>nil}, :cover_image=>{:cover_image=>nil}, :user=>{:user_id=>nil} :comments=>{:comment_ids=>[]}}
@@ -1,3 +1,3 @@
1
1
  module Plutonium
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.1"
3
3
  end
data/lib/plutonium.rb CHANGED
@@ -21,28 +21,31 @@ module Plutonium
21
21
 
22
22
  def self.stylesheet_link
23
23
  if Plutonium::Config.development
24
- file = JSON.parse(File.read(root.join("css.manifest")))["plutonium-dev.css"]
25
- "/plutonium-assets/build/#{file}"
24
+ base_dir = "/plutonium-assets/build"
25
+ manifest = "css.dev.manifest"
26
+ filename = "plutonium-dev.css"
26
27
  else
27
- raise NotImplementedError, "TODO: implement asset resolution for prod"
28
- # @stylesheet ||= begin
29
- # file = JSON.parse(File.read(root.join("css.manifest")))["plutonium.css"]
30
- # "/plutonium-assets/#{file}"
31
- # end
28
+ base_dir = "/plutonium-assets"
29
+ manifest = "css.manifest"
30
+ filename = "plutonium.css"
32
31
  end
32
+
33
+ file = JSON.parse(File.read(root.join(manifest)))[filename]
34
+ "#{base_dir}/#{file}"
33
35
  end
34
36
 
35
37
  def self.script_link
38
+ filename = "plutonium-app.js"
36
39
  if Plutonium::Config.development
37
- file = JSON.parse(File.read(root.join("js.manifest")))["plutonium.js"]
38
- "/plutonium-assets/build/#{file}"
40
+ base_dir = "/plutonium-assets/build"
41
+ manifest = "js.dev.manifest"
39
42
  else
40
- raise NotImplementedError, "TODO: implement asset resolution for prod"
41
- # @stylesheet ||= begin
42
- # file = JSON.parse(File.read(root.join("css.manifest")))["plutonium.css"]
43
- # "/plutonium-assets/#{file}"
44
- # end
43
+ base_dir = "/plutonium-assets"
44
+ manifest = "js.manifest"
45
45
  end
46
+
47
+ file = JSON.parse(File.read(root.join(manifest)))[filename]
48
+ "#{base_dir}/#{file}"
46
49
  end
47
50
  end
48
51
 
data/package.json CHANGED
@@ -14,8 +14,9 @@
14
14
  "tailwindcss": "^3.4.1"
15
15
  },
16
16
  "scripts": {
17
- "watch": "postcss app/assets/css/plutonium.css -o public/plutonium-assets/build/plutonium-dev.css --watch",
18
- "scripts": "node build.js",
19
- "build": "postcss app/assets/css/plutonium.css -o public/plutonium-assets/build/plutonium.css --watch"
17
+ "css:dev": "postcss app/assets/stylesheets/plutonium.css -o public/plutonium-assets/build/plutonium-dev.css --watch",
18
+ "js:dev": "node esbuild.config.js",
19
+ "css:prod": "postcss app/assets/stylesheets/plutonium.css -o public/plutonium-assets/plutonium.css --prod",
20
+ "js:prod": "node esbuild.config.js --prod"
20
21
  }
21
22
  }
data/postcss.config.js CHANGED
@@ -5,7 +5,7 @@ module.exports = {
5
5
  'postcss-hash': {
6
6
  algorithm: 'sha256',
7
7
  trim: 20,
8
- manifest: './css.manifest'
8
+ manifest: process.argv.includes("--prod") ? './css.manifest' : './css.dev.manifest'
9
9
  },
10
10
  }
11
11
  }