Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I handle this scoped slug use case without a new option from Friendly ID to disable UUID generation? #996

Open
nickjj opened this issue Jul 10, 2022 · 2 comments
Labels

Comments

@nickjj
Copy link

nickjj commented Jul 10, 2022

Here's a stripped down example of what I have set up:

class Course < ActiveRecord::Base
  extend FriendlyId

  validates :title, presence: true, length: { maximum: 70 }
  validates :slug, presence: true, length: { maximum: 70 }, uniqueness: { scope: :version }
  validates :version, presence: true, length: { maximum: 10 }

  friendly_id :slug_candidates, use: [:slugged]

  def slug_candidates
    [
      :title,
      [:title, :version]
    ]
  end
end

My database migration has:

t.text :title, null: false, default: ""
t.text :slug, null: false
t.text :version, null: false

add_index :courses, %i[slug version], unique: true

The issue

I want to explicitly require that a version is always provided when creating a course such as:

Course.create!(title: "Yay for learning", version: "v1")

This works fine and you end up with a slug of yay-for-learning because the version didn't have to be taken into account to be unique.

But if you run this a second time you'll end up with a slug of yay-for-learning-v1 which technically allows you to have version: v1 twice which isn't what I'm trying to do.

If you run it a third time you get yay-for-learning-0fa8243c-78a9-4fe3-b89b-080117d98b57 as a slug since the slug+version alone isn't unique.

What I tried

I can't add uniqueness: true to the version on its own at the Rails validation level because that would prevent (2) completely different course titles from ever having v1 set for their versions when each course on its own should be able to do that.

This also doesn't work:

  validates :slug, presence: true, length: { maximum: 70 }, uniqueness: { scope: :version }
  validates :version, presence: true, length: { maximum: 10 }, uniqueness: { scope: :slug }

Because technically the slug gets generated with a UUID so the slug is always different. This is where I think the only way this can be solved is if Friendly ID provides a mechanism to disable UUIDs from being generated and instead bubble up an ActiveRecord validation error (or DB error if no validation exists at the Rails level).

Is there something I'm missing here?

What I'm trying to do

In case it's not clear my intent is:

  • A course with a title of "hello" can have a version of "v1", "v2", "v3" as 3 different course records
    • Expected slugs for all 3 courses: hello, hello-v2, hello-v3
  • A course with a title of "world" can have a version of "v1", "v2", "v3" as 3 different course records
    • Expected slugs for all 3 courses: world, world-v2, world-v3
  • When adding a new course with a title of "hello" and a version of "v2" when this combo already exists would throw a uniqueness validation error if you had the 2 validation rules in the "This also doesn't work" section of this issue and if that validation didn't exist you'd get a PG index error because you have a unique index on the slug and version together

That last bullet is what I'm having trouble getting to work with Friendly ID because instead of letting this validation error happen it behind the scenes generates a UUID to "fix" the uniqueness issue.

@stale
Copy link

stale bot commented Nov 13, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 13, 2022
@nickjj
Copy link
Author

nickjj commented Nov 13, 2022

Just replying so it doesn't get auto-closed by a bot.

@parndt parndt added the pinned label Nov 15, 2022
@stale stale bot removed the stale label Nov 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants