organizations 0.3.1 → 0.4.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: 93641d7c8f80e347c31ffb9ad1c1f0f489078218f65c8204a4f3f48ad1d3c070
4
- data.tar.gz: 79f97cdfe624459b128075e7800d1452b35be970109cb7b1e2c040fcc69694b0
3
+ metadata.gz: 3489dee0ace79d490d899aa756462b26d367d2f609ca58b2ff96b41326a58ab1
4
+ data.tar.gz: 6764004c3e0fc2524eee6b457f8384de50ce9d4117b414eca9ba4519316e202b
5
5
  SHA512:
6
- metadata.gz: b60315a1184fe81064acb974a95dd80a82c99abf9fbedb117a231e43a44ec11b99218b25f38efeae6ad88015b7445e66354a2351c28ad3572f75dd7323e60601
7
- data.tar.gz: 5d0618750b4a4e59757538a99e1ca3e8ae6817f7cf6a395e194e7754eabc1f43dd747ea37e3aacf6979b0b5c945336b226c6e18e915a3dae58b14bbe13c3c1a5
6
+ metadata.gz: 88518342c7bcc6cc8c75eb83a036ac08348fc83962ba5f78e536deb22eedf1a1bfcc44c72255afe4e9b3080d6e8657133125ece9c87da21db583e1888eae09f5
7
+ data.tar.gz: d1f4aafce6fd17500d9f287b7907b165b4faee6a9fc219472f22a68fc06cabfb9cb82907184f6bf8530660fb89f3df7c449651cbc32217a168e0ddb7eb0c6d67
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [0.4.0] - 2026-03-17
2
+
3
+ **Breaking:** `memberships_count` column is now required on the organizations table.
4
+
5
+ - Added `memberships_count` to the install migration template (fresh installs get it automatically)
6
+ - Switched to Rails' native `counter_cache` so in-memory organization instances stay accurate after member changes
7
+ - `member_count` now reads directly from the counter cache (no fallback to COUNT query)
8
+ - Marked `memberships_count` as readonly on organizations
9
+
1
10
  ## [0.3.1] - 2026-02-28
2
11
 
3
12
  - Fixed `organization_switcher_data[:switch_path]` generating broken URLs when engine mounted with custom name (e.g., `as: 'organizations_engine'`)
data/README.md CHANGED
@@ -1387,24 +1387,11 @@ organization_switcher_data
1387
1387
 
1388
1388
  ### Counter caches for member counts
1389
1389
 
1390
- If you display member counts frequently (pricing pages, org listings), consider adding a counter cache:
1391
-
1392
- ```ruby
1393
- # In a migration
1394
- add_column :organizations_organizations, :memberships_count, :integer, default: 0, null: false
1395
-
1396
- # Reset existing counts
1397
- Organization.find_each do |org|
1398
- Organization.reset_counters(org.id, :memberships)
1399
- end
1400
- ```
1401
-
1402
- The gem automatically uses the counter cache if present:
1390
+ The install migration includes a `memberships_count` counter cache on organizations, and `member_count` reads from it directly:
1403
1391
 
1404
1392
  ```ruby
1405
1393
  org.member_count
1406
- # Uses memberships_count column if it exists
1407
- # Falls back to COUNT(*) query otherwise
1394
+ # Uses the memberships_count counter cache
1408
1395
  ```
1409
1396
 
1410
1397
  ### Existence checks use SQL
@@ -8,6 +8,7 @@ class CreateOrganizationsTables < ActiveRecord::Migration<%= migration_version %
8
8
  # Organizations table
9
9
  create_table :organizations_organizations, id: primary_key_type do |t|
10
10
  t.string :name, null: false
11
+ t.integer :memberships_count, default: 0, null: false
11
12
  t.send(json_column_type, :metadata, null: json_column_null, default: json_column_default)
12
13
 
13
14
  t.timestamps
@@ -28,7 +28,8 @@ module Organizations
28
28
  belongs_to :user
29
29
  belongs_to :organization,
30
30
  class_name: "Organizations::Organization",
31
- inverse_of: :memberships
31
+ inverse_of: :memberships,
32
+ counter_cache: :memberships_count
32
33
 
33
34
  belongs_to :invited_by,
34
35
  class_name: "User",
@@ -40,11 +41,6 @@ module Organizations
40
41
  validates :user_id, uniqueness: { scope: :organization_id, message: "is already a member of this organization" }
41
42
  validate :single_owner_per_organization, if: :owner?
42
43
 
43
- # Keep memberships_count accurate when the optional counter cache column exists.
44
- after_create_commit :increment_memberships_counter_cache
45
- after_destroy_commit :decrement_memberships_counter_cache
46
- after_update_commit :sync_memberships_counter_cache_for_org_change, if: :saved_change_to_organization_id?
47
-
48
44
  # === Scopes ===
49
45
 
50
46
  # Memberships with owner role
@@ -200,34 +196,6 @@ module Organizations
200
196
  errors.add(:role, "owner already exists for this organization")
201
197
  end
202
198
 
203
- def increment_memberships_counter_cache
204
- return unless memberships_counter_cache_enabled?
205
- return unless organization_id
206
-
207
- Organizations::Organization.increment_counter(:memberships_count, organization_id)
208
- end
209
-
210
- def decrement_memberships_counter_cache
211
- return unless memberships_counter_cache_enabled?
212
- return unless organization_id
213
-
214
- Organizations::Organization.decrement_counter(:memberships_count, organization_id)
215
- end
216
-
217
- def sync_memberships_counter_cache_for_org_change
218
- return unless memberships_counter_cache_enabled?
219
-
220
- old_org_id, new_org_id = saved_change_to_organization_id
221
- Organizations::Organization.decrement_counter(:memberships_count, old_org_id) if old_org_id
222
- Organizations::Organization.increment_counter(:memberships_count, new_org_id) if new_org_id
223
- end
224
-
225
- def memberships_counter_cache_enabled?
226
- Organizations::Organization.column_names.include?("memberships_count")
227
- rescue StandardError
228
- false
229
- end
230
-
231
199
  def validate_role!(role)
232
200
  unless Roles.valid_role?(role)
233
201
  raise ArgumentError, "Invalid role: #{role}. Must be one of: #{Roles.valid_roles.join(', ')}"
@@ -46,6 +46,7 @@ module Organizations
46
46
  # === Validations ===
47
47
 
48
48
  validates :name, presence: true
49
+ attr_readonly :memberships_count
49
50
 
50
51
  # === Scopes ===
51
52
 
@@ -101,14 +102,10 @@ module Organizations
101
102
  memberships.exists?
102
103
  end
103
104
 
104
- # Get member count (uses counter cache if available, otherwise COUNT)
105
+ # Get member count from the organizations counter cache.
105
106
  # @return [Integer]
106
107
  def member_count
107
- if has_attribute?(:memberships_count)
108
- self[:memberships_count] || memberships.count
109
- else
110
- memberships.count
111
- end
108
+ memberships_count || 0
112
109
  end
113
110
 
114
111
  # Get pending invitations
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Organizations
4
- VERSION = "0.3.1"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: organizations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - rameerez
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-02-28 00:00:00.000000000 Z
10
+ date: 2026-03-17 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: railties