Skip to content

Commit

Permalink
Add fallback: true option
Browse files Browse the repository at this point in the history
  • Loading branch information
excid3 committed Mar 22, 2023
1 parent 511cea6 commit 680eb01
Show file tree
Hide file tree
Showing 16 changed files with 87 additions and 26 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
### Unreleased

### 1.5.0

* Add `has_prefix_id fallback: false` option to disable lookup by regular ID - @excid3

### 1.4.0

* Add `decode_prefix_id` and `decode_prefix_ids` class methods - @TastyPi
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
prefixed_ids (1.4.0)
prefixed_ids (1.5.0)
hashids (>= 1.0.0, < 2.0.0)
rails (>= 6.0.0)

Expand Down Expand Up @@ -203,4 +203,4 @@ DEPENDENCIES
standard

BUNDLED WITH
2.4.7
2.4.9
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ User.find("user_5vJjbzXq9KrLEMm32iAnOP0xGDYk6dpe")
User.find_by_prefix_id("user_5vJjbzXq9KrLEMm32iAnOP0xGDYk6dpe")
```

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

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

```ruby
class Account < ApplicationRecord
has_prefix_id :acct, minimum_length: 32, override_find: false, override_param: false, salt: ""
has_prefix_id :acct, minimum_length: 32, override_find: false, override_param: false, salt: "", fallback: false
end
```

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.

## Development

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.
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/rails_6.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
prefixed_ids (1.4.0)
prefixed_ids (1.5.0)
hashids (>= 1.0.0, < 2.0.0)
rails (>= 6.0.0)

Expand Down Expand Up @@ -202,4 +202,4 @@ DEPENDENCIES
standard

BUNDLED WITH
2.4.7
2.4.9
4 changes: 2 additions & 2 deletions gemfiles/rails_6_1.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
prefixed_ids (1.4.0)
prefixed_ids (1.5.0)
hashids (>= 1.0.0, < 2.0.0)
rails (>= 6.0.0)

Expand Down Expand Up @@ -205,4 +205,4 @@ DEPENDENCIES
standard

BUNDLED WITH
2.4.7
2.4.9
4 changes: 2 additions & 2 deletions gemfiles/rails_7_0.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
prefixed_ids (1.4.0)
prefixed_ids (1.5.0)
hashids (>= 1.0.0, < 2.0.0)
rails (>= 6.0.0)

Expand Down Expand Up @@ -202,4 +202,4 @@ DEPENDENCIES
standard

BUNDLED WITH
2.4.7
2.4.9
4 changes: 2 additions & 2 deletions gemfiles/rails_master.gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ GIT
PATH
remote: ..
specs:
prefixed_ids (1.4.0)
prefixed_ids (1.5.0)
hashids (>= 1.0.0, < 2.0.0)
rails (>= 6.0.0)

Expand Down Expand Up @@ -211,4 +211,4 @@ DEPENDENCIES
standard

BUNDLED WITH
2.4.7
2.4.9
13 changes: 10 additions & 3 deletions lib/prefixed_ids.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ module Rails

included do
class_attribute :_prefix_id
class_attribute :_prefix_id_fallback
end

class_methods do
def has_prefix_id(prefix, override_find: true, override_param: true, **options)
def has_prefix_id(prefix, override_find: true, override_param: true, fallback: true, **options)
include Attribute
include Finder if override_find
include ToParam if override_param
self._prefix_id = PrefixId.new(self, prefix, **options)
self._prefix_id_fallback = fallback

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

def prefix_id
self.class._prefix_id.encode(id)
_prefix_id.encode(id)
end
end

Expand All @@ -81,7 +83,12 @@ module Finder

class_methods do
def find(*ids)
super(*ids.map { |id| _prefix_id.decode(id, fallback: true) })
prefix_ids = *ids.map do |id|
prefix_id = _prefix_id.decode(id, fallback: _prefix_id_fallback)
raise Error, "#{id} is not a valid prefix_id" if !_prefix_id_fallback && prefix_id.nil?
prefix_id
end
super(*prefix_ids)
end

def relation
Expand Down
8 changes: 5 additions & 3 deletions lib/prefixed_ids/prefix_id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ def decode(id, fallback: false)
fallback_value = fallback ? id : nil
_, id_without_prefix = PrefixedIds.split_id(id, @delimiter)
decoded_hashid = @hashids.decode(id_without_prefix)
return fallback_value unless valid?(decoded_hashid)

decoded_hashid.last || fallback_value
if fallback && !valid?(decoded_hashid)
fallback_value
else
decoded_hashid.last
end
end

private
Expand Down
2 changes: 1 addition & 1 deletion lib/prefixed_ids/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module PrefixedIds
VERSION = "1.4.0"
VERSION = "1.5.0"
end
3 changes: 3 additions & 0 deletions test/dummy/app/models/team.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Team < ApplicationRecord
has_prefix_id :team, fallback: false
end
8 changes: 8 additions & 0 deletions test/dummy/db/migrate/20230322131821_create_teams.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CreateTeams < ActiveRecord::Migration[7.0]
def change
create_table :teams do |t|

t.timestamps
end
end
end
19 changes: 12 additions & 7 deletions test/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,28 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2021_05_03_145247) do
ActiveRecord::Schema[7.0].define(version: 2023_03_22_131821) do
create_table "accounts", force: :cascade do |t|
t.integer "user_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "posts", force: :cascade do |t|
t.integer "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end

create_table "teams", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "users", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

add_foreign_key "posts", "users"
Expand Down
7 changes: 7 additions & 0 deletions test/dummy/test/models/team_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require "test_helper"

class TeamTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
8 changes: 8 additions & 0 deletions test/fixtures/teams.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the "{}" from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
two: {}
15 changes: 15 additions & 0 deletions test/prefixed_ids_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,19 @@ class PrefixedIdsTest < ActiveSupport::TestCase
test "can override salt on model" do
assert_equal "accountsabcd", Account._prefix_id.hashids.salt
end

test "decode with fallback false returns nil for regular ID" do
assert_nil Team._prefix_id.decode(1)
end

test "disabled fallback allows find by prefix id" do
team = Team.find_by(id: ActiveRecord::FixtureSet.identify(:one))
assert_equal team, Team.find(team.prefix_id)
end

test "disabled fallback raises an error if not prefix_id" do
assert_raises PrefixedIds::Error do
Team.find(ActiveRecord::FixtureSet.identify(:one))
end
end
end

0 comments on commit 680eb01

Please sign in to comment.