plutonium 0.15.4 → 0.15.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/plutonium.css +1 -1
  3. data/app/assets/plutonium.ico +0 -0
  4. data/app/assets/plutonium.png +0 -0
  5. data/app/views/components/table_search_input/table_search_input_component.html.erb +3 -3
  6. data/app/views/resource/_resource_table.html.erb +0 -321
  7. data/docs/.vitepress/config.ts +61 -0
  8. data/docs/.vitepress/theme/custom.css +61 -0
  9. data/docs/.vitepress/theme/index.ts +4 -0
  10. data/docs/api-examples.md +49 -0
  11. data/docs/guide/getting-started/authorization.md +296 -0
  12. data/docs/guide/getting-started/core-concepts.md +432 -0
  13. data/docs/guide/getting-started/index.md +18 -0
  14. data/docs/guide/getting-started/installation.md +269 -0
  15. data/docs/guide/getting-started/resources.md +254 -0
  16. data/docs/guide/what-is-plutonium.md +211 -0
  17. data/docs/index.md +43 -0
  18. data/docs/markdown-examples.md +85 -0
  19. data/docs/public/android-chrome-192x192.png +0 -0
  20. data/docs/public/android-chrome-512x512.png +0 -0
  21. data/docs/public/apple-touch-icon.png +0 -0
  22. data/docs/public/favicon-16x16.png +0 -0
  23. data/docs/public/favicon-32x32.png +0 -0
  24. data/docs/public/favicon.ico +0 -0
  25. data/docs/public/plutonium.png +0 -0
  26. data/docs/public/site.webmanifest +1 -0
  27. data/docs/public/templates/plutonium.rb +21 -0
  28. data/lib/generators/pu/core/assets/assets_generator.rb +2 -3
  29. data/lib/generators/pu/core/assets/templates/tailwind.config.js +2 -2
  30. data/lib/generators/pu/core/install/install_generator.rb +9 -1
  31. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +0 -1
  32. data/lib/plutonium/core/controllers/authorizable.rb +1 -1
  33. data/lib/plutonium/definition/base.rb +8 -0
  34. data/lib/plutonium/definition/defineable_props.rb +1 -1
  35. data/lib/plutonium/definition/presentable.rb +71 -0
  36. data/lib/plutonium/interaction/README.md +1 -1
  37. data/lib/plutonium/interaction/base.rb +6 -6
  38. data/lib/plutonium/lib/deep_freezer.rb +31 -0
  39. data/lib/plutonium/query/adhoc_block.rb +19 -0
  40. data/lib/plutonium/query/base.rb +29 -0
  41. data/lib/plutonium/query/filter.rb +12 -0
  42. data/lib/plutonium/query/filters/text.rb +77 -0
  43. data/lib/plutonium/query/model_scope.rb +19 -0
  44. data/lib/plutonium/railtie.rb +0 -10
  45. data/lib/plutonium/resource/controller.rb +0 -3
  46. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +26 -0
  47. data/lib/plutonium/resource/controllers/crud_actions.rb +3 -6
  48. data/lib/plutonium/resource/controllers/defineable.rb +0 -2
  49. data/lib/plutonium/resource/controllers/queryable.rb +36 -20
  50. data/lib/plutonium/resource/policy.rb +5 -6
  51. data/lib/plutonium/resource/query_object.rb +61 -147
  52. data/lib/plutonium/resource/register.rb +3 -0
  53. data/lib/plutonium/{refinements/parameter_refinements.rb → support/parameters.rb} +5 -7
  54. data/lib/plutonium/ui/action_button.rb +34 -19
  55. data/lib/plutonium/ui/component/methods.rb +1 -1
  56. data/lib/plutonium/ui/display/resource.rb +19 -15
  57. data/lib/plutonium/ui/form/query.rb +171 -0
  58. data/lib/plutonium/ui/form/resource.rb +22 -17
  59. data/lib/plutonium/ui/table/components/scopes_bar.rb +1 -1
  60. data/lib/plutonium/ui/table/components/search_bar.rb +6 -139
  61. data/lib/plutonium/ui/table/resource.rb +10 -9
  62. data/lib/plutonium/version.rb +1 -1
  63. data/package-lock.json +5769 -1853
  64. data/package.json +11 -5
  65. data/src/js/core.js +0 -1
  66. data/tailwind.options.js +89 -11
  67. metadata +37 -13
  68. data/app/assets/plutonium-original.png +0 -0
  69. data/app/assets/plutonium-white.png +0 -0
  70. data/lib/plutonium/interaction/concerns/presentable.rb +0 -73
  71. data/public/plutonium-assets/fonts/bootstrap-icons.woff +0 -0
  72. data/public/plutonium-assets/fonts/bootstrap-icons.woff2 +0 -0
  73. /data/{templates → docs/public/templates}/base.rb +0 -0
@@ -0,0 +1,211 @@
1
+ # What is Plutonium?
2
+
3
+ Plutonium is a Rapid Application Development (RAD) toolkit that extends Rails with powerful conventions, patterns, and tools to accelerate application development while maintaining flexibility and maintainability.
4
+
5
+ It acts as a higher-level abstraction on top of Rails, providing ready-to-use solutions for common application needs while preserving Rails' elegance.
6
+
7
+ ## Core Architecture
8
+
9
+ ### Rails-Native Design
10
+
11
+ Plutonium integrates seamlessly with Rails, extending its conventions rather than replacing them:
12
+
13
+ ```ruby
14
+ # Plutonium controllers inherit from your ApplicationController
15
+ class ResourceController < ApplicationController
16
+ include Plutonium::Resource::Controller
17
+ end
18
+
19
+ # Plutonium controllers are Rails controllers
20
+ class ProductsController < ResourceController
21
+ # Enhanced with resource capabilities
22
+ def custom_action
23
+ # Regular Rails code works just fine
24
+ respond_to do |format|
25
+ format.html
26
+ format.json
27
+ end
28
+ end
29
+ end
30
+ ```
31
+
32
+ ### Resource-Oriented Architecture
33
+
34
+ Resources are the building blocks of Plutonium applications:
35
+
36
+ ```ruby
37
+ class ProductDefinition < ResourceDefinition
38
+ # Declarative field definitions
39
+ field :name, as: :string
40
+ field :description, as: :markdown
41
+ field :price_cents, as: :money
42
+
43
+ # Resource-level search
44
+ search do |scope, query|
45
+ scope.where("name LIKE ?", "%#{query}%")
46
+ end
47
+
48
+ # Business actions
49
+ action :publish, interaction: PublishProduct
50
+ action :archive, interaction: ArchiveProduct
51
+ end
52
+ ```
53
+
54
+ ### Modular by Design
55
+
56
+ Plutonium's packaging system helps organize code into focused, reusable modules:
57
+
58
+ ```ruby
59
+ # Generate different types of packages
60
+ rails generate pu:pkg:portal admin
61
+ rails generate pu:pkg:package inventory
62
+
63
+ # Packages are isolated and focused
64
+ module AdminPortal
65
+ class Engine < Rails::Engine
66
+ include Plutonium::Portal::Engine
67
+ end
68
+ end
69
+
70
+ AdminPortal::Engine.routes.draw do
71
+ register_resource ::Product
72
+ end
73
+ ```
74
+
75
+ ### Progressive Enhancement
76
+
77
+ Built on modern web technologies like Hotwire, delivering rich interactivity without sacrificing simplicity:
78
+
79
+ ```ruby
80
+ class PublishProduct < ResourceInteraction
81
+ attribute :schedule_for, :datetime
82
+ attribute :notify_users, :boolean
83
+
84
+ def execute
85
+ resource.publish!(schedule_for:)
86
+ notify_users! if notify_users
87
+
88
+ success(resource)
89
+ .with_message("Product scheduled for publishing")
90
+ .with_render_response(NotificationComponent.new)
91
+ end
92
+ end
93
+ ```
94
+
95
+ ## Use Cases
96
+
97
+ ### Business Applications
98
+
99
+ ::: details Enterprise Resource Planning (ERP)
100
+ ```ruby
101
+ class InvoiceDefinition < ResourceDefinition
102
+ # Rich field handling
103
+ field :line_items, as: :nested, limit: 20
104
+ field :attachments, as: :document, multiple: true
105
+
106
+ # Business actions
107
+ action :submit_for_approval, interaction: SubmitForApproval
108
+ action :approve, interaction: ApproveInvoice
109
+ action :reject, interaction: RejectInvoice
110
+
111
+ # Workflow states
112
+ scope :draft
113
+ scope :pending_approval
114
+ scope :approved
115
+ end
116
+ ```
117
+ :::
118
+
119
+ ::: details Multi-tenant SaaS
120
+ ```ruby
121
+ module CustomerPortal
122
+ class Engine < Rails::Engine
123
+ include Plutonium::Package::Engine
124
+ # Automatic tenant isolation
125
+ scope_to_entity Organization
126
+ end
127
+ end
128
+ ```
129
+ :::
130
+
131
+ ### Administrative Systems
132
+
133
+ ::: details Back-office Applications
134
+ ```ruby
135
+ class OrderDefinition < ResourceDefinition
136
+ # Advanced filtering
137
+ filter :status, with: SelectFilter, choices: Order.statuses
138
+ filter :created_at, with: DateRangeFilter
139
+
140
+ # Bulk actions
141
+ action :process_batch, interaction: ProcessPendingOrders
142
+ action :export_to_csv, interaction: ExportOrders
143
+
144
+ # Complex displays
145
+ display :summary do |field|
146
+ OrderSummaryComponent.new(field)
147
+ end
148
+ end
149
+ ```
150
+ :::
151
+
152
+ ::: details Content Management
153
+ ```ruby
154
+ class ArticleDefinition < ResourceDefinition
155
+ field :content, as: :markdown
156
+ field :featured_image, as: :image
157
+
158
+ # Publishing workflow
159
+ action :publish, interaction: PublishArticle
160
+ action :schedule, interaction: ScheduleArticle
161
+
162
+ # Content organization
163
+ scope :draft
164
+ scope :published
165
+ scope :scheduled
166
+ end
167
+ ```
168
+ :::
169
+
170
+ ## Key Benefits
171
+
172
+ ### Accelerated Development
173
+ - Pre-built components for common functionality
174
+ - Smart generators for boilerplate code
175
+ - Convention-based resource handling
176
+ - Integrated authentication and authorization
177
+
178
+ ### Maintainable Architecture
179
+ - Clear separation of concerns through packages
180
+ - Consistent patterns across the application
181
+ - Deep Rails integration
182
+ - Progressive enhancement
183
+
184
+ ### Enterprise Ready
185
+ - Flexible and robust access control
186
+ - Multi-tenancy support
187
+ - Extensible component system
188
+ - Mobile-friendly by default
189
+
190
+ ## Best For
191
+
192
+ ::: tip IDEAL USE CASES
193
+ - Complex business applications
194
+ - Multi-tenant SaaS platforms
195
+ - Administrative systems
196
+ - Content management systems
197
+ - Resource management systems
198
+ :::
199
+
200
+ ::: warning MIGHT NOT BE THE BEST FIT
201
+ - Simple blogs or brochure sites
202
+ - Basic CRUD applications
203
+ - Pure API-only services
204
+ :::
205
+
206
+ ## Prerequisites
207
+
208
+ - Ruby 3.2.2 or higher
209
+ - Rails 7.1 or higher
210
+ - Node.js and Yarn
211
+ - Basic understanding of Ruby on Rails
data/docs/index.md ADDED
@@ -0,0 +1,43 @@
1
+ ---
2
+ # https://vitepress.dev/reference/default-theme-home-page
3
+ layout: home
4
+
5
+ hero:
6
+ name: Plutonium RADKit
7
+ tagline: The Ultimate Rapid Application Development Toolkit (RADKit) for Rails
8
+ image:
9
+ src: /plutonium.png
10
+ alt: Plutonium
11
+ actions:
12
+ - theme: brand
13
+ text: Get started
14
+ link: /guide/getting-started/
15
+ - theme: alt
16
+ text: Learn more
17
+ link: /guide/what-is-plutonium
18
+
19
+ features:
20
+ - title: Pro-Grade CRUD UI
21
+ details: Stunning, modern interface with rich field types to build powerful admin panels in minutes
22
+
23
+ - title: Intelligent Fields
24
+ details: Zero-config field detection that matches your Rails models out of the box
25
+
26
+ - title: Seamless Authentication
27
+ details: Use your existing auth or our Rodauth integration - get setup in seconds
28
+
29
+ - title: Enterprise Authorization
30
+ details: Industrial-strength access control powered by Action Policy's proven framework
31
+
32
+ - title: Built-in Multitenancy
33
+ details: Row-level multitenancy that just works - perfect for SaaS and enterprise apps
34
+
35
+ - title: Advanced Nested Resources
36
+ details: Complex resource relationships made simple with zero extra configuration
37
+
38
+ - title: Custom Actions
39
+ details: Extend your admin panel with incredibly simple custom actions and workflows
40
+
41
+ - title: Complete Builder Control
42
+ details: Total flexibility to customize every aspect of your admin UI with elegant builder APIs
43
+ ---
@@ -0,0 +1,85 @@
1
+ # Markdown Extension Examples
2
+
3
+ This page demonstrates some of the built-in markdown extensions provided by VitePress.
4
+
5
+ ## Syntax Highlighting
6
+
7
+ VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
8
+
9
+ **Input**
10
+
11
+ ````md
12
+ ```js{4}
13
+ export default {
14
+ data () {
15
+ return {
16
+ msg: 'Highlighted!'
17
+ }
18
+ }
19
+ }
20
+ ```
21
+ ````
22
+
23
+ **Output**
24
+
25
+ ```js{4}
26
+ export default {
27
+ data () {
28
+ return {
29
+ msg: 'Highlighted!'
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ ## Custom Containers
36
+
37
+ **Input**
38
+
39
+ ```md
40
+ ::: info
41
+ This is an info box.
42
+ :::
43
+
44
+ ::: tip
45
+ This is a tip.
46
+ :::
47
+
48
+ ::: warning
49
+ This is a warning.
50
+ :::
51
+
52
+ ::: danger
53
+ This is a dangerous warning.
54
+ :::
55
+
56
+ ::: details
57
+ This is a details block.
58
+ :::
59
+ ```
60
+
61
+ **Output**
62
+
63
+ ::: info
64
+ This is an info box.
65
+ :::
66
+
67
+ ::: tip
68
+ This is a tip.
69
+ :::
70
+
71
+ ::: warning
72
+ This is a warning.
73
+ :::
74
+
75
+ ::: danger
76
+ This is a dangerous warning.
77
+ :::
78
+
79
+ ::: details
80
+ This is a details block.
81
+ :::
82
+
83
+ ## More
84
+
85
+ Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
@@ -0,0 +1,21 @@
1
+ after_bundle do
2
+ # We just installed Rails, let's create a commit
3
+ git add: "."
4
+ git commit: %( -m 'initial commit' )
5
+
6
+ # Run the base install
7
+ rails_command "app:template LOCATION=https://radioactive-labs.github.io/plutonium-core/templates/base.rb"
8
+
9
+ # Add development tools
10
+ generate "pu:gem:dotenv"
11
+ git add: "."
12
+ git commit: %( -m 'add dotenv' )
13
+
14
+ generate "pu:gem:annotate"
15
+ git add: "."
16
+ git commit: %( -m 'add annotate' )
17
+
18
+ generate "pu:core:assets"
19
+ git add: "."
20
+ git commit: %( -m 'integrate assets' )
21
+ end
@@ -22,12 +22,11 @@ module Pu
22
22
  private
23
23
 
24
24
  def copy_tailwind_config
25
- copy_file "tailwind.config.js"
25
+ copy_file "tailwind.config.js", force: true
26
26
  end
27
27
 
28
28
  def install_dependencies
29
- `yarn add @radioactive-labs/plutonium`
30
- `yarn add flowbite @tailwindcss/forms`
29
+ run "npm install @radioactive-labs/plutonium flowbite @tailwindcss/forms"
31
30
  end
32
31
 
33
32
  def configure_application
@@ -9,12 +9,12 @@ module.exports = {
9
9
  ].concat(plutoniumTailwindConfig.plugins.map((plugin) => require(plugin))),
10
10
  theme: plutoniumTailwindConfig.theme,
11
11
  content: [
12
+ `${__dirname}/app/**/*.rb`,
12
13
  `${__dirname}/app/views/**/*.html.erb`,
13
14
  `${__dirname}/app/helpers/**/*.rb`,
14
15
  `${__dirname}/app/assets/stylesheets/**/*.css`,
15
16
  `${__dirname}/app/javascript/**/*.js`,
16
- `${__dirname}/app/plutonium/**/*.rb`,
17
- `${__dirname}/packages/**/app/plutonium/**/*.rb`,
17
+ `${__dirname}/packages/**/app/**/*.rb`,
18
18
  `${__dirname}/packages/**/app/views/**/*.html.erb`,
19
19
  ].concat(plutoniumTailwindConfig.content),
20
20
  }
@@ -15,6 +15,7 @@ module Pu
15
15
  setup_packages
16
16
  setup_app
17
17
  eject_views
18
+ setup_active_record
18
19
  rescue => e
19
20
  exception "#{self.class} failed:", e
20
21
  end
@@ -25,7 +26,6 @@ module Pu
25
26
  copy_file "config/packages.rb"
26
27
  create_file "packages/.keep"
27
28
  insert_into_file "config/application.rb", "\nrequire_relative \"packages\"\n", after: /Bundler\.require.*\n/
28
- # insert_into_file "config/application.rb", indent("Plutonium.configure_rails config\n\n", 4), after: /.*< Rails::Application\n/
29
29
  end
30
30
 
31
31
  def setup_app
@@ -38,6 +38,14 @@ module Pu
38
38
  force: options[:force],
39
39
  skip: options[:skip]
40
40
  end
41
+
42
+ def setup_active_record
43
+ inject_into_class(
44
+ "app/models/application_record.rb",
45
+ "ApplicationRecord",
46
+ " include Plutonium::Resource::Record\n"
47
+ )
48
+ end
41
49
  end
42
50
  end
43
51
  end
@@ -3,6 +3,5 @@
3
3
  Plutonium.configure do |config|
4
4
  config.load_defaults 1.0
5
5
 
6
- # config.assets.logo = "logo.png"
7
6
  # Configure plutonium above.
8
7
  end
@@ -9,7 +9,7 @@ module Plutonium
9
9
 
10
10
  included do
11
11
  authorize :user, through: :current_user
12
- authorize :scope, through: :entity_scope_for_authorize
12
+ authorize :entity_scope, through: :entity_scope_for_authorize
13
13
 
14
14
  helper_method :policy_for, :authorized_resource_scope
15
15
  end
@@ -46,6 +46,10 @@ module Plutonium
46
46
 
47
47
  class Display < Plutonium::UI::Display::Resource; end
48
48
 
49
+ class QueryForm < Plutonium::UI::Form::Query; end
50
+
51
+ class TextFilter < Plutonium::Query::Filters::Text; end
52
+
49
53
  # fields
50
54
  defineable_props :field, :input, :display, :column
51
55
 
@@ -94,6 +98,10 @@ module Plutonium
94
98
  def detail_class
95
99
  self.class::Display
96
100
  end
101
+
102
+ def query_form
103
+ self.class::QueryForm
104
+ end
97
105
  end
98
106
  end
99
107
  end
@@ -67,7 +67,7 @@ module Plutonium
67
67
  end
68
68
  # merged[name].compact!
69
69
  end
70
- merged
70
+ Plutonium::Lib::DeepFreezer.freeze(merged)
71
71
  end
72
72
  end
73
73
 
@@ -0,0 +1,71 @@
1
+ module Plutonium
2
+ module Definition
3
+ # Provides presentation-related functionality for interactions.
4
+ #
5
+ # This module allows interactions to define metadata such as labels, icons,
6
+ # and descriptions, which can be used for UI generation or documentation.
7
+ #
8
+ # @example
9
+ # class MyInteraction < Plutonium::Interaction::Base
10
+ # include Plutonium::Definition::Presentable
11
+ #
12
+ # presents label: "My Interaction",
13
+ # icon: "star",
14
+ # description: "Does something awesome"
15
+ #
16
+ # # ... rest of the interaction
17
+ # end
18
+ module Presentable
19
+ extend ActiveSupport::Concern
20
+
21
+ included do
22
+ class_attribute :presentation_metadata, default: {}
23
+ end
24
+
25
+ class_methods do
26
+ # Defines presentation metadata for the interaction.
27
+ #
28
+ # @param options [Hash] The presentation options.
29
+ # @option options [String] :label The label for the interaction.
30
+ # @option options [String] :icon The icon for the interaction.
31
+ # @option options [String] :description The description of the interaction.
32
+ def presents(**options)
33
+ self.presentation_metadata = options
34
+ end
35
+
36
+ # Returns the label for the interaction.
37
+ #
38
+ # @return [String] The label defined in the presentation metadata or a default generated from the class name.
39
+ def label
40
+ presentation_metadata[:label] || name.demodulize.titleize
41
+ end
42
+
43
+ # Returns the icon for the interaction.
44
+ #
45
+ # @return [String, nil] The icon defined in the presentation metadata.
46
+ def icon
47
+ presentation_metadata[:icon]
48
+ end
49
+
50
+ # Returns the description for the interaction.
51
+ #
52
+ # @return [String, nil] The description defined in the presentation metadata.
53
+ def description
54
+ presentation_metadata[:description]
55
+ end
56
+ end
57
+
58
+ def label
59
+ self.class.label
60
+ end
61
+
62
+ def icon
63
+ self.class.icon
64
+ end
65
+
66
+ def description
67
+ self.class.description
68
+ end
69
+ end
70
+ end
71
+ end
@@ -252,7 +252,7 @@ The `Presentable` concern allows you to add metadata to your interactions, which
252
252
 
253
253
  ```ruby
254
254
  class MyInteraction < Plutonium::Interaction::Base
255
- include Plutonium::Interaction::Concerns::Presentable
255
+ include Plutonium::Definition::Presentable
256
256
 
257
257
  presents label: "My Interaction",
258
258
  icon: Phlex::TablerIcons::Activate,
@@ -22,10 +22,10 @@ module Plutonium
22
22
  class Base
23
23
  include ActiveModel::Model
24
24
  include ActiveModel::Attributes
25
- include Concerns::Presentable
26
25
  include Plutonium::Definition::DefineableProps
27
26
  include Plutonium::Definition::ConfigAttr
28
- # include Concerns::WorkflowDSL
27
+ include Plutonium::Definition::Presentable
28
+ # include Plutonium::Interaction::Concerns::WorkflowDSL
29
29
 
30
30
  class Form < Plutonium::UI::Form::Interaction; end
31
31
 
@@ -44,6 +44,10 @@ module Plutonium
44
44
  self::Form.new(instance || new)
45
45
  end
46
46
 
47
+ def build_form
48
+ self.class.build_form(self)
49
+ end
50
+
47
51
  # Executes the interaction.
48
52
  #
49
53
  # @return [Plutonium::Interaction::Outcome] The result of the interaction.
@@ -60,10 +64,6 @@ module Plutonium
60
64
  end
61
65
  end
62
66
 
63
- def build_form
64
- self.class.build_form(self)
65
- end
66
-
67
67
  private
68
68
 
69
69
  # Implement the main logic of the interaction.
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plutonium
4
+ module Lib
5
+ class DeepFreezer
6
+ def self.freeze(object)
7
+ # Recursive calling #deep_freeze for enumerable objects.
8
+ if object.respond_to? :each
9
+ if object.instance_of?(Hash)
10
+ object.each { |key, val| freeze(val) }
11
+ else
12
+ object.each { |val| freeze(val) }
13
+ end
14
+ end
15
+
16
+ # # Freezing of all instance variable values.
17
+ # object.instance_variables.each do |var|
18
+ # frozen_val = instance_variable_get(var)
19
+ # frozen_val.deep_freeze
20
+ # instance_variable_set(var, frozen_val)
21
+ # end
22
+
23
+ if object.frozen?
24
+ object
25
+ else
26
+ object.freeze
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Plutonium
2
+ module Query
3
+ class AdhocBlock < Base
4
+ attr_reader :body
5
+
6
+ # Initializes a AdhocBlock with a given block of code.
7
+ #
8
+ # @param body [Proc] The block of code for the query.
9
+ def initialize(body)
10
+ super()
11
+ @body = body
12
+ end
13
+
14
+ def apply(scope, **)
15
+ body.call(scope, **)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ module Plutonium
2
+ module Query
3
+ class Base
4
+ include Plutonium::Definition::DefineableProps
5
+ include Plutonium::Definition::ConfigAttr
6
+ include Plutonium::Definition::Presentable
7
+
8
+ defineable_props :field, :input
9
+
10
+ # Applies a parameterized query to modify the given scope.
11
+ #
12
+ # @param scope [Object] The initial scope that will be filtered, sorted, or otherwise modified
13
+ # by applying this query. This is typically an ActiveRecord::Relation or similar query object.
14
+ #
15
+ # @param params [Hash] Optional parameters that configure how the query is applied.
16
+ # The specific parameters accepted depend on the implementing class.
17
+ #
18
+ # @return [Object] The modified scope with this query's conditions applied. Returns the same
19
+ # type as the input scope parameter.
20
+ #
21
+ # @example Basic usage
22
+ # query.apply(User.all, status: 'active')
23
+ #
24
+ def apply(scope, **params)
25
+ raise NotImplementedError, "#{self.class}#apply(scope, **params)"
26
+ end
27
+ end
28
+ end
29
+ end