Skip to content

Commit 680eb01

Browse files
committed
Add fallback: true option
1 parent 511cea6 commit 680eb01

16 files changed

+87
-26
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
### Unreleased
22

3+
### 1.5.0
4+
5+
* Add `has_prefix_id fallback: false` option to disable lookup by regular ID - @excid3
6+
37
### 1.4.0
48

59
* Add `decode_prefix_id` and `decode_prefix_ids` class methods - @TastyPi

Gemfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
prefixed_ids (1.4.0)
4+
prefixed_ids (1.5.0)
55
hashids (>= 1.0.0, < 2.0.0)
66
rails (>= 6.0.0)
77

@@ -203,4 +203,4 @@ DEPENDENCIES
203203
standard
204204

205205
BUNDLED WITH
206-
2.4.7
206+
2.4.9

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ User.find("user_5vJjbzXq9KrLEMm32iAnOP0xGDYk6dpe")
5959
User.find_by_prefix_id("user_5vJjbzXq9KrLEMm32iAnOP0xGDYk6dpe")
6060
```
6161

62-
⚠️ Note that `find` still finds records by the primary key. Eg. `localhost/users/1` still works.
62+
⚠️ Note that `find` still finds records by the primary key. Eg. `localhost/users/1` still works.
6363
If you're targeting security issues by masking the ID, make sure to use `find_by_prefix_id` and [add a salt](#salt).
6464

6565
We also override `to_param` by default so it'll be used in URLs automatically.
@@ -108,10 +108,12 @@ You can customize the prefix, length, and attribute name for PrefixedIds.
108108

109109
```ruby
110110
class Account < ApplicationRecord
111-
has_prefix_id :acct, minimum_length: 32, override_find: false, override_param: false, salt: ""
111+
has_prefix_id :acct, minimum_length: 32, override_find: false, override_param: false, salt: "", fallback: false
112112
end
113113
```
114114

115+
By default, `find` will accept both Prefix IDs and regular IDs. Setting `fallback: false` will disable finding by regular IDs and will only allow Prefix IDs.
116+
115117
## Development
116118

117119
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.

gemfiles/rails_6.gemfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ..
33
specs:
4-
prefixed_ids (1.4.0)
4+
prefixed_ids (1.5.0)
55
hashids (>= 1.0.0, < 2.0.0)
66
rails (>= 6.0.0)
77

@@ -202,4 +202,4 @@ DEPENDENCIES
202202
standard
203203

204204
BUNDLED WITH
205-
2.4.7
205+
2.4.9

gemfiles/rails_6_1.gemfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ..
33
specs:
4-
prefixed_ids (1.4.0)
4+
prefixed_ids (1.5.0)
55
hashids (>= 1.0.0, < 2.0.0)
66
rails (>= 6.0.0)
77

@@ -205,4 +205,4 @@ DEPENDENCIES
205205
standard
206206

207207
BUNDLED WITH
208-
2.4.7
208+
2.4.9

gemfiles/rails_7_0.gemfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: ..
33
specs:
4-
prefixed_ids (1.4.0)
4+
prefixed_ids (1.5.0)
55
hashids (>= 1.0.0, < 2.0.0)
66
rails (>= 6.0.0)
77

@@ -202,4 +202,4 @@ DEPENDENCIES
202202
standard
203203

204204
BUNDLED WITH
205-
2.4.7
205+
2.4.9

gemfiles/rails_master.gemfile.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ GIT
9494
PATH
9595
remote: ..
9696
specs:
97-
prefixed_ids (1.4.0)
97+
prefixed_ids (1.5.0)
9898
hashids (>= 1.0.0, < 2.0.0)
9999
rails (>= 6.0.0)
100100

@@ -211,4 +211,4 @@ DEPENDENCIES
211211
standard
212212

213213
BUNDLED WITH
214-
2.4.7
214+
2.4.9

lib/prefixed_ids.rb

+10-3
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,16 @@ module Rails
3434

3535
included do
3636
class_attribute :_prefix_id
37+
class_attribute :_prefix_id_fallback
3738
end
3839

3940
class_methods do
40-
def has_prefix_id(prefix, override_find: true, override_param: true, **options)
41+
def has_prefix_id(prefix, override_find: true, override_param: true, fallback: true, **options)
4142
include Attribute
4243
include Finder if override_find
4344
include ToParam if override_param
4445
self._prefix_id = PrefixId.new(self, prefix, **options)
46+
self._prefix_id_fallback = fallback
4547

4648
# Register with PrefixedIds to support PrefixedIds#find
4749
PrefixedIds.models[prefix.to_s] = self
@@ -72,7 +74,7 @@ def decode_prefix_ids(ids)
7274
end
7375

7476
def prefix_id
75-
self.class._prefix_id.encode(id)
77+
_prefix_id.encode(id)
7678
end
7779
end
7880

@@ -81,7 +83,12 @@ module Finder
8183

8284
class_methods do
8385
def find(*ids)
84-
super(*ids.map { |id| _prefix_id.decode(id, fallback: true) })
86+
prefix_ids = *ids.map do |id|
87+
prefix_id = _prefix_id.decode(id, fallback: _prefix_id_fallback)
88+
raise Error, "#{id} is not a valid prefix_id" if !_prefix_id_fallback && prefix_id.nil?
89+
prefix_id
90+
end
91+
super(*prefix_ids)
8592
end
8693

8794
def relation

lib/prefixed_ids/prefix_id.rb

+5-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ def decode(id, fallback: false)
1919
fallback_value = fallback ? id : nil
2020
_, id_without_prefix = PrefixedIds.split_id(id, @delimiter)
2121
decoded_hashid = @hashids.decode(id_without_prefix)
22-
return fallback_value unless valid?(decoded_hashid)
23-
24-
decoded_hashid.last || fallback_value
22+
if fallback && !valid?(decoded_hashid)
23+
fallback_value
24+
else
25+
decoded_hashid.last
26+
end
2527
end
2628

2729
private

lib/prefixed_ids/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module PrefixedIds
2-
VERSION = "1.4.0"
2+
VERSION = "1.5.0"
33
end

test/dummy/app/models/team.rb

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Team < ApplicationRecord
2+
has_prefix_id :team, fallback: false
3+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class CreateTeams < ActiveRecord::Migration[7.0]
2+
def change
3+
create_table :teams do |t|
4+
5+
t.timestamps
6+
end
7+
end
8+
end

test/dummy/db/schema.rb

+12-7
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,28 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema.define(version: 2021_05_03_145247) do
13+
ActiveRecord::Schema[7.0].define(version: 2023_03_22_131821) do
1414
create_table "accounts", force: :cascade do |t|
1515
t.integer "user_id"
16-
t.datetime "created_at", precision: 6, null: false
17-
t.datetime "updated_at", precision: 6, null: false
16+
t.datetime "created_at", null: false
17+
t.datetime "updated_at", null: false
1818
end
1919

2020
create_table "posts", force: :cascade do |t|
2121
t.integer "user_id", null: false
22-
t.datetime "created_at", precision: 6, null: false
23-
t.datetime "updated_at", precision: 6, null: false
22+
t.datetime "created_at", null: false
23+
t.datetime "updated_at", null: false
2424
t.index ["user_id"], name: "index_posts_on_user_id"
2525
end
2626

27+
create_table "teams", force: :cascade do |t|
28+
t.datetime "created_at", null: false
29+
t.datetime "updated_at", null: false
30+
end
31+
2732
create_table "users", force: :cascade do |t|
28-
t.datetime "created_at", precision: 6, null: false
29-
t.datetime "updated_at", precision: 6, null: false
33+
t.datetime "created_at", null: false
34+
t.datetime "updated_at", null: false
3035
end
3136

3237
add_foreign_key "posts", "users"

test/dummy/test/models/team_test.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require "test_helper"
2+
3+
class TeamTest < ActiveSupport::TestCase
4+
# test "the truth" do
5+
# assert true
6+
# end
7+
end

test/fixtures/teams.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2+
3+
# This model initially had no columns defined. If you add columns to the
4+
# model remove the "{}" from the fixture names and add the columns immediately
5+
# below each fixture, per the syntax in the comments below
6+
#
7+
one: {}
8+
two: {}

test/prefixed_ids_test.rb

+15
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,19 @@ class PrefixedIdsTest < ActiveSupport::TestCase
148148
test "can override salt on model" do
149149
assert_equal "accountsabcd", Account._prefix_id.hashids.salt
150150
end
151+
152+
test "decode with fallback false returns nil for regular ID" do
153+
assert_nil Team._prefix_id.decode(1)
154+
end
155+
156+
test "disabled fallback allows find by prefix id" do
157+
team = Team.find_by(id: ActiveRecord::FixtureSet.identify(:one))
158+
assert_equal team, Team.find(team.prefix_id)
159+
end
160+
161+
test "disabled fallback raises an error if not prefix_id" do
162+
assert_raises PrefixedIds::Error do
163+
Team.find(ActiveRecord::FixtureSet.identify(:one))
164+
end
165+
end
151166
end

0 commit comments

Comments
 (0)