-1

I have these nested routes, and I want to hide the id param from the url.

resources :shares, only: [:index, :create, :update] do 
  resource :wizard, path: "trade" do
    get :first_object
    get :second_object
    get :confirmation
    post :validate_step
  end
end

Each page has a form_for that looks like this up top:

<%= form_for [@object, @trade_wizard], as: :trade_wizard, url: validate_step_share_wizard_path(@object) do |f| %>

So the user adds the first_object to the wizard, and gets redirected to the following url: /shares/113/trade/second_object. After adding second_object (which is obviously different from the first), the user is redirected to to /shares/106/trade/confirmation. I'm not sure if this represents a potential security violation, and my tests seem to work just fine, so I'm thinking it should be ok if I find some way to hide that id part of the url?

Or is my use case for nested routes incorrect?

Ilya Konyukhov
  • 2,506
  • 1
  • 9
  • 20
calyxofheld
  • 361
  • 1
  • 15
  • 35

2 Answers2

2

gem 'friendly_id' lets you create pretty URLs and work with human-friendly strings as if they were numeric ids.

https://github.com/norman/friendly_id

Saqib Shahzad
  • 909
  • 9
  • 25
2

You have a set of possible solutions:

  1. As mentioned, you can convert the IDs into something like a slug, or something else, which is what the other answer has mentioned: https://github.com/norman/friendly_id

  2. You can store the IDs of the selected objects in session cookies. That way, the client is still sending the relevant data, but it doesn't really appear in the URL.

  3. You can have an ephemeral Transaction table, where you can store the first object and the second object. That way, the routes will deal with the transaction_id, while the first_object_id and second_object_id are abstracted away within the table. This will also allow you to store other metadata related to the transaction or the trade process.

  4. You can create a separate endpoint not linked with the shares controller, where you can accept two (optional) query params: /sharetransaction/trade?first_object_id=113&second_object_id=106. That way, the URL reflects what is actually happening, rather than changing IDs in the middle for no discernible reason.

The approach you go for depends on your use-case.

shashwat
  • 896
  • 1
  • 12
  • 26
  • Thank you! I actually left this part out of the question (since it felt extraneous), but I actually am storing the relevant IDs in a session variable. The whole thing is built up in a multistep form wizard and then gets propagated to db only after everything has been successfully added. I am still confused about how to hide the ID from the url. Don't I need to pass the ID in the form? – calyxofheld Oct 24 '18 at 16:18
  • i'm still sort of confused. both `first_object` and `second_object` are picked by the user from a list of similar objects, and i cannot pass either to session without passing them as an argument to `form_for`. how can i assign them in the controller? – calyxofheld Oct 25 '18 at 02:27