Route cannot be found Rails 5.2.3 [duplicate] - ruby-on-rails

How to force Rails to consider a param with a dot in the value like google.com (e.g. /some_action/google.com) a single param and not "id" => "google", "format"=> "com"?
The parameter value should be "id" => "google.com"

By default, dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. However, you can add some regex requirements to the route parameters. Here, you want to allow the dots in the parameters.
match 'some_action/:id' => 'controller#action', :constraints => { :id => /[0-z\.]+/ }
And in rails 2.3:
map.connect 'some_action/:id', :controller => 'controller', :action => 'action', :requirements => { :id => /[0-z\.]+/ }
Relevent rails guides section

In Rails 4 I used:
get 'operation/:p1/:p2', to: 'operation#get', constraints: { p1: /[^\/]+/, p2: /[^\/]+/ }
it allows any character in both params (other than '/')

And when used with the resources notation, it can be done like this:
resources :post,
only: [ :create, :index, :destroy ],
constraints: { id: /[0-z\.]+/ }
Tested in Rails 4.1

We had similar case when we removed some part of an api path. Basically we went from /api/app/v1/* to /api/v1/*
We put this in our routes
match '/api/app/v1/*path', to: redirect(path: '/api/v1/%{path}'), via: :all
This was all fine except for some routes that ended with path params including dots. E.g. /api/v1/foo/00.00.100 where .100 got parsed into format and the remaining param only had the value 00.00
We guarded this with some constraint on the params.
put '/api/app/v1/foo/:version',
constraints: { version: /([0-9]+)\.([0-9]+)\.([0-9]+)/ },
to: redirect('/api/v1/foo/%{version}')
Edit: we use rails 5

Related

How to add alias in routes.rb

How to add alias to route file?
Something like this:
/rules => 'posts/1', param: id => 1
Is it possible define it in routes.rb
I want
/rules => posts/1
not
/rules/1 => posts/1
Well, let's look at the official Rails routing guide:
You can also define other defaults in a route by supplying a hash for the :defaults option. This even applies to parameters that you do not specify as dynamic segments.
So then:
get "/rules" => "posts#show", :defaults => { :id => "1" }
try this
get '/rules', to: redirect('/posts/1')
http://guides.rubyonrails.org/routing.html#redirection

params.merge instead of :overwrite_params gives different URLs

In my old Rails 2.3 application I had something like:
link_to 'Portuguese', url_for(:overwrite_params => { :lang => 'pt' })
which was returning me URLs formatted as:
.../pt
Now that I've upgraded to Rails 3.0 :overwrite_params doesn't work any more, they say params.merge can be used instead to have the same result.
This is true, the page I land to is the same, yet
link_to 'Portuguese', params.merge(:lang => 'pt')
gives me URLs the kind of:
.../?lang=pt
How could I maintain the same URLs as before?
you can use a match statement. In routes.rb file you need to mention something like
get "sign_up/:lang" => "users#new"
I tried this in console
1.9.3-p429 :001 > include Rails.application.routes.url_helpers
1.9.3-p429 :011 > url_for(:only_path => true, :controller => 'users', :action = 'new' , :lang=>'pt')
=> "/sign_up/pt"
In this manner you will pass the parameter lang as '/pt' and not '/?lang=pt'
I had this horrible-looking workaround working:
after defining a matching route
match '(/:lang)', to: 'home#index', as: :home
I create the link to it as:
link_to "Portuguese", URI(request.referer).path + "pt"

Rails 3 Routing based on regex

I want to redirect all routes that start with the string xyz to some other path.
match /\/xyz\/(.)*/ => redirect{ "whateverurl" }
The match method doesn't seem to work when given a regex, I have googled alot seems like there are options to do with regex but they are for params for example
match 'photos/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ }
How can I achieve it ?
How about:
match '/xyz/*foo' => redirect('url')
It's not a regexp, it's called route globbing. More about it here.

Rails REST routing: dots in the resource item ID

I have following in my routes.rb:
resources :users, :except => [:new, :create] do
get 'friends', :as => :friends, :on => :member, :to => "users#friends"
end
and following in my user.rb:
def to_param
self.login
end
And when, for example, user with dots in login (for example 'any.thing') comes from facebook, rails gives routing error (no route found, I suppose that's because it recognises anything after dot as a format or because of route constraints). How can I come over this error?
The following constrain definition permit the dot in id as well as any character except slash.
Supported formats must be explicitly defined (here .html and .json) to not to be taken by id.
resources :foobars,
:constraints => { :id => /[^\/]+(?=\.html\z|\.json\z)|[^\/]+/ }
That constrain definition is worked with Rails 3.1
For earlier Rails versions you may need to backport look-ahead support in regin gem (it is vendored in rack-mount gem)
You could replace periods with another character:
def to_param
login.gsub(/\./,"-") # note: 'self' is not needed here
end
user = User.find_by_login("bart.simpson")
user_path(user) # => "/users/bart-simpson"
EDIT
You're right, this fails to deal with unique logins that map to the same value. Maybe a better way is to use segment constraints in the route:
match 'users/(:id)' => 'users#show',
:constraints => { :id => /[0-9A-Za-z\-\.]+/ }
This should allow "/users/bart-simpson" and /users/bart.simpson" to generate :id => "bart-simpson" and :id => "bart.simpson" respectively. You'd have to alter the regex to add all the acceptable characters for the URL.
Note that this is mentioned in the Rails Routing Guide, section 3.2:
By default dynamic segments don’t accept dots – this is because the
dot is used as a separator for formatted routes. If you need to use a
dot within a dynamic segment add a constraint which overrides this –
for example :id => /[^\/]+/ allows anything except a slash.
To allow the :id segment to contain any character except '/':
match 'users/(:id)' => 'users#show', :constraints => {:id => /[^\/]+/}
It's written elsewhere in one of the answers, but this is IMO the simplest way.

Rails — Params with "dot" (e.g. /google.com)

How to force Rails to consider a param with a dot in the value like google.com (e.g. /some_action/google.com) a single param and not "id" => "google", "format"=> "com"?
The parameter value should be "id" => "google.com"
By default, dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. However, you can add some regex requirements to the route parameters. Here, you want to allow the dots in the parameters.
match 'some_action/:id' => 'controller#action', :constraints => { :id => /[0-z\.]+/ }
And in rails 2.3:
map.connect 'some_action/:id', :controller => 'controller', :action => 'action', :requirements => { :id => /[0-z\.]+/ }
Relevent rails guides section
In Rails 4 I used:
get 'operation/:p1/:p2', to: 'operation#get', constraints: { p1: /[^\/]+/, p2: /[^\/]+/ }
it allows any character in both params (other than '/')
And when used with the resources notation, it can be done like this:
resources :post,
only: [ :create, :index, :destroy ],
constraints: { id: /[0-z\.]+/ }
Tested in Rails 4.1
We had similar case when we removed some part of an api path. Basically we went from /api/app/v1/* to /api/v1/*
We put this in our routes
match '/api/app/v1/*path', to: redirect(path: '/api/v1/%{path}'), via: :all
This was all fine except for some routes that ended with path params including dots. E.g. /api/v1/foo/00.00.100 where .100 got parsed into format and the remaining param only had the value 00.00
We guarded this with some constraint on the params.
put '/api/app/v1/foo/:version',
constraints: { version: /([0-9]+)\.([0-9]+)\.([0-9]+)/ },
to: redirect('/api/v1/foo/%{version}')
Edit: we use rails 5

Resources