How to get raw route of named helper? - ruby-on-rails

I have
# routes.rb
Rails.application.routes.draw do
get 'order/:order_id/add_item/:item_id' => 'order#item_add', as: :order_add_item
end
I can call order_add_item_url(order_id: something, item_id: some_other) and it will return order/something/add_item/some_other.
My question is, can i get the "raw" URL? So i want to get something like order_add_item_url returns order/:order_id/add_item/:item_id
I have digged into Rails' Journey internals, and get field something like this:
Rails.application.routes.named_routes.routes[:order_add_item].path.source
=> "\\A/pos/order/([^/.?]+)/add_item/([^/.?]+)(?:\\.([^/.?]+))?\\Z"
But it strips down the "original" version of the path i wrote in the routes. There is no :item_id and :order_id
I am using Rails 4.2.

I believe this is what you want or at least somewhere for you to start working on:
Rails.application.routes.named_routes.routes[:order_add_item].path.spec.to_s

Related

Adding a record's attribute to the URL before the ID

I'm trying to add a specific attribute of a record in Rails to the URL from something like:
domain.com/share/5
(where 5 is the record ID) to something like:
domain.com/share/johnsmith/5
where johnsmith is stored in record 5. I'm alternating between these two routes to no success:
get "/share/:name/:id" => "share#show"
resources :share, :only => [:show]
And between these two methods:
share_path(doc.user.name, doc)
share_path(doc)
The show method in the ShareController is pretty standard.
The problem:
Using share_path(doc.user.name, doc) in the view generates a link to /share/johnsmith.5, instead of /share/johnsmith/5.
get "/share/:name/:id" => "share#show" should do the job. But you may have to look at the order of routes in routes.rb, maybe Rails took the wrong route?
Best tip to look at what's happening:
Call the URL in your browser (or using curl or whatever) and then look into your console where your started rails s (or rails server).
There you should see something like this:
Processing by ShareController#show
Parameters: {"id"=>"5", "name"=>"johnsmith"}
Concerning the path methods:
Simply use rake routes, it will tell you which path methods are available.
No idea what happened but it resolved itself with this:
get "/share/:name/:id" => "share#show", :as => :share
share_path(doc.user.name, doc)
I do not get the . and / issue at all. I restarted everything and it was gone.

Changing the params in URL on rails

I want to change the :id param on the URL. I added to my routes.rb file something like:
match "articles/:name/edit", :to => 'articles#edit', :as => 'edit_article'
Thinking that :name would be readed by the server as params[:name] later for me in rails. I edited my article controller definition for edit so:
def edit
#article = Article.find(params[:name])
end
I get always the error couldn't find article with id=test and I was wondering why "id" instead of :name? I tried also changing match to get but I got the same.
I have also the default resources :articles still in my routes.rb file, don't know if there's something like a double rule working there.
The whole thing is that instead of ID numbers I would use names in my URL —not just the edit one, with the show method I could handle it, but not with edit/update/delete.
I was reading about routing but I can't figure out what I am doing wrong.
By default, find search by id.
You should replace it with find_by_name.
Advice: use friendly_id

autogenerate paths in rails 3?

From the looks of some railscasts (this one in particular), it seems like there is some autogeneration of "*_path" variables that not happening for me. in this rails cast, the edit_mutliple_products_path seems to be generated automagically (i don't normally like using that word). When I follow through the same steps and try to access a similar path, i get this:
undefined local variable or method `edit_multiple_distributions_workflows_path' for #<#<Class:0x132b18a68>:0x132af3290>
This is rails 2.X. Rails routes changed in Rails 3. in order to get this route add below to routes.rb:
resources :products do
collection do
post 'edit_multiple'
put 'update_multiple'
end
end
You will be able to access this paths with
edit_multiple_products_url
edit_multiple_products_path
update_multiple_products_url
update_multiple_products_path
instead of edit_multiple_distributions_workflow_path. Btw where did you get this path from? I did not see it in the railscast.
In the given tutorial, which looks like it's from an older Rails, this is the line which would generate the path methods:
map.resources :products, :collection => { :edit_multiple => :post, :update_multiple => :put }
In rails 3, you can see its usage in the docs here: http://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default

make pretty url with routes.rb

I would like to do something to this effect, I believe:
map.connect 'show/:company_name/:id',
:controller => 'companies',
:action => 'show'
Basically, each time the show action is called, I would like it to take the company_name param and place it into the url as such (show/:company_name/:id)
However, it seems I am using old (rails 2.x routing api) and cannot use map.connect without getting an error. How can I upgrade this?
Is there some way to do this with "match"?
Thanks!
===================
This is the error I see when I try to use map.connect:
undefined local variable or method `map' for #<ActionDispatch::Routing::Mapper:0x103757458>
I think your routes lack a "/" symbol in the first line.
Try this:
match '/show/:company_name/:id' => 'companies#show'
You can check your routes path with command rake routes.
--
Besides, the show action is the default RESTful method in Rails. I'll suggest you change a equivalent word, and reserve "show" action for future or other situation.
In Rails convention, you can write resources :companies, and the path will be /companies/:id using show action.
Some adjustment, in app/models/company.rb
def to_param
self.name
end
So your url will look like http://yourdoamin.com/companies/37signals.
In app/controllers/companies_controller.rb
#company = Company.find_by_name(params[:id])
If I'm understanding your goal, try
match 'companies/show/:company_name/:id' => 'companies#show'

rails3 routes issue

I have following routes.
pota.resources :on_k,
:as => ':klass',
:path_prefix => 'pota/klass',
:controller => 'main'
When I do rake routes this is what I get for show method:
pota_on_k GET /pota/klass/:klass/:id(.:format)
{:action=>"show", :controller=>"pota/main"}
Above code works fine in rails 2.x . However if I am using rails3 then I get following error
ActionController::RoutingError: No route matches
{:action=>"show", :controller=>"pota/main", :klass=>"vehicle/door", :id=>1}
Notice that I am passing 'vehicle/door' as :klass. If I pass a standard model like :klass => 'pet' then it works fine. However if I pass a nested model name like :klass => 'vehicle/door' then I get route error in rails3.
I guess that is because I have '/' in the value . I can solve that by having a regex but I might also pass :klass which is not nested.
On a class like Vehicle::Car I do
Vehicle::Car.underscore #=> vehicle/car
"vehicle/car".camelize.constantize #=> Vehicle::Car
This underscore and camelize/constantize on the other side makes it easier to pass nested class name.
Any idea on how to go about fixing it for rails3?
STOP!
Think about what you're doing here - you should not be calling constantize on url parameters. Assuming that you're likely to be calling find on the result you're basically giving a hacker a way to query every ActiveRecord model in your application.
A better way is to use meta programming to dynamically build static routes that can't be hacked, e.g:
%w[pet vehicle/car vehicle/bike].each do |klass|
resources :pota,
:path => "pota/#{klass.pluralize}",
:as => "pota_#{klass.tr('/','_').pluralize}",
:defaults => { :klass => klass }
end
Then you can add a helper method that calls the appropriate named route helper to generate urls based upon a passed model instance.

Resources