stimulus_grid_rails 0.1.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.
@@ -0,0 +1,3 @@
1
+ module StimulusGridRails
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,79 @@
1
+ require "stimulus_grid_rails/version"
2
+ require "stimulus_grid_rails/engine"
3
+ require "stimulus_grid_rails/column"
4
+ require "stimulus_grid_rails/grid"
5
+ require "stimulus_grid_rails/turbo_streams_helper"
6
+ require "stimulus_grid_rails/concerns/broadcastable"
7
+
8
+ module StimulusGridRails
9
+ class << self
10
+ # Base class for the gem's controllers. Set to your authenticated base
11
+ # controller so Devise (authenticate_user!) and ActsAsTenant
12
+ # (set_current_tenant_through_filter) before_actions apply to the grid's
13
+ # cell/row endpoints too — otherwise they'd run unauthenticated and
14
+ # unscoped, leaking across tenants.
15
+ #
16
+ # StimulusGridRails.parent_controller = "ApplicationController" # default
17
+ attr_writer :parent_controller
18
+
19
+ def parent_controller
20
+ @parent_controller ||= "ApplicationController"
21
+ end
22
+
23
+ # Where the engine is mounted. The grid's client-side endpoints are built
24
+ # from this, so it must match how you mount the engine:
25
+ #
26
+ # # config/initializers/stimulus_grid_rails.rb
27
+ # StimulusGridRails.mount_path = "/admin/grids"
28
+ #
29
+ # # config/routes.rb
30
+ # mount StimulusGridRails::Engine => StimulusGridRails.mount_path
31
+ #
32
+ # Using the same value in both places keeps the browser requests and the
33
+ # routes in sync regardless of namespace/scope. Default "/grids".
34
+ def mount_path
35
+ @mount_path || "/grids"
36
+ end
37
+
38
+ def mount_path=(path)
39
+ @mount_path = path.to_s.sub(%r{/+\z}, "") # strip trailing slash(es)
40
+ end
41
+ end
42
+
43
+ # Per-process registry of ApplicationGrid subclasses, keyed by `resource`.
44
+ # Populated lazily when a Grid subclass is instantiated, so the cells
45
+ # controller can resolve `/grids/:resource/...` back to the right Grid class.
46
+ def self.registry
47
+ @registry ||= {}
48
+ end
49
+
50
+ def self.register_grid(resource, klass)
51
+ registry[resource.to_s] = klass
52
+ end
53
+
54
+ def self.lookup_grid(resource)
55
+ registry[resource.to_s] or
56
+ raise ArgumentError, "No grid registered for resource #{resource.inspect}. " \
57
+ "Did you define a Grid subclass and reference it from a view?"
58
+ end
59
+
60
+ # Tenant-isolation token for stream names (RAILS.md §2). When the app uses
61
+ # ActsAsTenant and a tenant is set, this returns a per-tenant token so a
62
+ # broadcast for one tenant can never reach another tenant's subscribers,
63
+ # even when grids share a logical stream name. Returns nil when not
64
+ # multi-tenant. Both the broadcaster (model callback) and the subscriber
65
+ # (turbo_stream_from in the view) run in the same request/tenant context, so
66
+ # they derive the same token and match.
67
+ def self.tenant_stream_token
68
+ return nil unless defined?(ActsAsTenant) && ActsAsTenant.respond_to?(:current_tenant)
69
+ tenant = ActsAsTenant.current_tenant
70
+ tenant ? "sgr-tenant:#{tenant.class.name}:#{tenant.id}" : nil
71
+ end
72
+
73
+ # The streamables a grid's broadcasts + subscription share. Tenant-scoped
74
+ # automatically. Pass extra view-scoping tokens (e.g. a signed view name)
75
+ # as needed.
76
+ def self.streamables_for(resource, *extra)
77
+ [tenant_stream_token, "sgr-grid:#{resource}", *extra].compact
78
+ end
79
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stimulus_grid_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marcus Schappi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '7.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '7.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: turbo-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: stimulus-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: importmap-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
69
+ description: Brings the stimulus_grid data-grid into Rails as a first-class engine.
70
+ Provides ApplicationGrid for declaring columns server-side; cell-grained Turbo Stream
71
+ actions (cell, cell-confirm, cell-revert, row-insert-sorted, row-remove, bulk);
72
+ a single PATCH endpoint for cell mutations with optimistic-id reconciliation; and
73
+ importmap-pinnable JS for both the grid and the live-sync layer.
74
+ email:
75
+ - marcus@schappi.com
76
+ executables: []
77
+ extensions: []
78
+ extra_rdoc_files: []
79
+ files:
80
+ - CHANGELOG.md
81
+ - MIT-LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - app/assets/javascripts/stimulus_grid.js
85
+ - app/assets/javascripts/stimulus_grid_rails.js
86
+ - app/assets/stylesheets/stimulus_grid.css
87
+ - app/assets/stylesheets/stimulus_grid_rails.css
88
+ - app/controllers/stimulus_grid_rails/base_controller.rb
89
+ - app/controllers/stimulus_grid_rails/cells_controller.rb
90
+ - app/controllers/stimulus_grid_rails/history_controller.rb
91
+ - app/controllers/stimulus_grid_rails/rows_controller.rb
92
+ - app/models/stimulus_grid_rails/audit.rb
93
+ - app/views/stimulus_grid_rails/grids/_grid.html.erb
94
+ - app/views/stimulus_grid_rails/grids/_row.html.erb
95
+ - config/importmap.rb
96
+ - config/routes.rb
97
+ - db/migrate/20260520000001_create_stimulus_grid_audits.rb
98
+ - lib/stimulus_grid_rails.rb
99
+ - lib/stimulus_grid_rails/column.rb
100
+ - lib/stimulus_grid_rails/concerns/broadcastable.rb
101
+ - lib/stimulus_grid_rails/engine.rb
102
+ - lib/stimulus_grid_rails/grid.rb
103
+ - lib/stimulus_grid_rails/turbo_streams_helper.rb
104
+ - lib/stimulus_grid_rails/version.rb
105
+ homepage: https://github.com/schappim/stimulus_grid
106
+ licenses:
107
+ - MIT
108
+ metadata:
109
+ homepage_uri: https://github.com/schappim/stimulus_grid
110
+ source_code_uri: https://github.com/schappim/stimulus_grid
111
+ changelog_uri: https://github.com/schappim/stimulus_grid/blob/main/gem/stimulus_grid_rails/CHANGELOG.md
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: 3.0.0
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.5.22
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Rails + Hotwire bindings for stimulus_grid — server-side column registry,
131
+ custom Turbo Stream actions, optimistic cell updates.
132
+ test_files: []