encoded url as parameter in rails routes - ruby-on-rails

I want to set a url as encoded url to REST API. The url I want to my route to look like this
Required: https://localhost:3000/api/v1/articles?url=https%3A%2F%2Frepository.dri.ie%2Fcatalog%2F5999pn33w&format=json
In the routes.rb I tried to set the route like this:
namespace 'api' do
namespace 'v1' do
resources :articles
get 'articles/*url' => 'articles#show'
end
end
so my route look like this
http://localhost:3000/api/v1/articles/https://repository.dri.ie/catalog/5999pn33w
how can I make the url passed as encoded url?

You have missidentified the issue here as it has nothing to do with URL encoding. Rails doesn't care about the contents of the query string when matching routes. It just matches the request by path and method.
Thus a request for https://localhost:3000/api/v1/articles?url=https%3A%2F%2Frepository.dri.ie%2Fcatalog%2F5999pn33w&format=json will alway match the index route defined by resources :articles. Remember also that routes have priority in the order they are defined.
What you need to do instead is create a route that matches /articles with a constraint:
Rails.application.routes.draw do
# Custom route to match /articles?url=xxx
get 'articles',
to: 'articles#show',
constraints: ->(request){ request.query_parameters["url"].present? }
# this must come after the custom route
resources :articles
end

Related

Rails 5: How to overwrite route parameters for extra member route

In Rails 5 I've figured out how to
Overwrite the route parameter from id to something like name
Add another route for a resource
So that my routes.rb looks something like this
Rails.application.routes.draw do
resources :cats, param: :name
resources :cats do
get :preview, on: :member
end
end
I've noticed however that my additional preview route does not keep the overwritten named route parameter. Instead, when looking at the output from rake routes, I have something that looks like this.
GET /cats/:id/preview(.:format)
when what I was expecting, and trying to achieve, was a route that looks like
GET /cats/:name/preview(.:format)
How do I both add an additional route to a resource while overwriting the parameter?
You're duplicating your routes entries for cats, and you've provided the block for declaring the preview route on the entry missing the param name override. You need to provide the override and the block in the same route declaration.
Rails.application.routes.draw do
resources :cats, param: :name do
get :preview, on: :member
end
end
This gives you the route you want:
$ rake routes
Prefix Verb URI Pattern Controller#Action
preview_cat GET /cats/:name/preview(.:format) cats#preview

Understanding rails routing that include (=>) and (:as)

While reading about rails routing I found routing that include =>. But I don't understnad what it means. Also I found some routing example with :as. It would be nice if someone explained a little bit about it. I have read rails guide but still I am not quite clear about them.
Please explain what this means
get 'customer_details' => "customers#details"
and
get 'customer_details' => "customers#details", :as => :customerdetails
Each time you define a route, you have to define a controller#action for that route:
#config/routes.rb
get :customer_details => "customers#details"
get :customer_details, to: "customers#details"
get :customer_details, controller: :customers, action: :details
The routing module provides URL rewriting in native Ruby. It's a way to redirect incoming requests to controllers and actions.
The following symbols are special:
:controller maps to your controller name
:action maps to an action with your controllers
Other names simply map to a parameter as in the case of :id.
Using => is simply a shortcut for the to: option...
When a pattern points to an internal route, the route's :action and :controller should be set in options or hash shorthand. Examples:
match 'photos/:id' => 'photos#show', via: :get
match 'photos/:id', to: 'photos#show', via: :get
match 'photos/:id', controller: 'photos', action: 'show', via: :get
In short, it's another way to pass the required "controller#action" arguments to the Rails router.
--
Of course, this is negated by using the resources directive, which sets the controller & actions implicitly:
#config/routes.rb
resources :customers, only: [], path: "" do
get :customer_details, on: :collection #-> url.com/customer_details
end
The routing middleware (ActionDispatch::Routing) takes inbound URL paths, and matches them against your defined routes -- sending the user to the appropriate controller / action.
The entire routing structure (even when you use link_to) depends on having the controller & action set for a route; especially true with a path helper.
Setting as: gives you the ability to explicitly define the name of the path, for example:
#config/routes.rb
get "search/:query", to: "application#search", as: :app_search
... the above will create the helper <%= app_search %>
Update
In response to your comment, you'll want to use either of the following:
#config/routes.rb
get "customers/details", to: "customers#details" #-> url.com/customers/details
- or -
resources :customers do
get :details, on: :collection #-> url.com/customers/details
end
If you're defining a single route, only use symbols if Ruby can interpret that data without any interpolation. For example get :details can be treated as get "details", however get "customers/details" cannot be treated as a symbol.

Ruby on Rails Routing for Wildcard URL

I was trying to pull a segment from the URL and since I'm a rookie, kind of confused by the routing.
My code to get the last segment works fine, it's my routing that is messed up.
Ideally the URL would like this:
http://localhost.com/track/item/1234
I'm using Rails v4.0.8 & Ruby v2.0.0p451
The error is No route matches [GET] "/track/item/1234"
Here's the whole routes.rb file:
SepContact::Application.routes.draw do
get "track/item"
get "track/item/:id"
get "contacts/contact"
resources "contacts", only: [:new, :create]
end
I think CWitty's should work as well but here is a more explicit format.
match "track/items", to: 'controller#index', via: :get, as: "items"
match "track/items/:id", to: 'controller#show', via: :get, as: "item"
Note I updated your url to be more rails like items rather than item
I think most of your problem is with the track segment of the url.
I don't see how get 'track/items' would map the the items#index controller / method
I think the match method would be needed here to explicitly map the url to the correct controller and method.
Is there a good reason you are naming you url like that?
You can read all about routing here:
http://guides.rubyonrails.org/routing.html
Here is the section of the above document that discusses using the match method:
3.7 HTTP Verb Constraints
In general, you should use the get, post, put, patch and delete methods to constrain a route to a particular verb. You can use the match method with the :via option to match multiple verbs at once:
match 'photos', to: 'photos#show', via: [:get, :post]
You can match all verbs to a particular route using via: :all:
match 'photos', to: 'photos#show', via: :all
Routing both GET and POST requests to a single action has security implications. In general, you should avoid routing all verbs to an action unless you have a good reason to.
Your routes should be like:
SepContact::Application.routes.draw do
get "track/item/:id", to: 'controller#action'
get "track/item", to: 'controller#action'
get "contacts/contact" to: 'controller#action'
resources :contacts, only: [:new, :create]
end
You need to specify a to: pointing to a controller and action unless you use the resource or resources helper.

rails passing in id parameter ambiguous

If I have a route:
/users/9/follow
"9" comes in like this:
Parameters: {"id"=>"9"}
But if I have a route:
/images/6936/like
then parameter has image appended to it:
Parameters: {"image_id"=>"6936"}
Just wondering how I should know if it's id or resourcename_id.
Extract from Rails Routing from the Outside In
2.10.1 Adding Member Routes
To add a member route, just add a member block into the resource
block:
resources :photos do
member do
get 'preview'
end
end
This will recognize /photos/1/preview with GET, and route to
the preview action of PhotosController, with the resource id value
passed in params[:id]. It will also create the preview_photo_url
and preview_photo_path helpers.
Within the block of member routes, each route name specifies the HTTP
verb that it will recognize. You can use get, patch, put, post, or
delete here. If you don't have multiple member routes, you can also
pass :on to a route, eliminating the block:
resources :photos do
get 'preview', on: :member
end
And the actual answer to your question is in the last paragraph:
You can leave out the :on option, this will create the same member
route except that the resource id value will be available in
params[:photo_id] instead of params[:id].

How can I guess the route helpers that are created with match in Rails?

I have created a route in the routes.rb file like this:
match ':controller/:action/:id'
I tried invoking add_posts_path() and add_post_path() from my view and in both cases I got similar error messages like this one:
undefined method `add_post_path' for ...
I have tried declaring my match route both before and after the resources :posts declaration.
Are any route helpers created for such a route? I am unsure what helper methods can be used with such a match rule.
You can name routes with :as parameter
match '/foo/bar', to: 'foo#bar', as: 'foo_bar'
and then use foo_bar_path in your view
http://guides.rubyonrails.org/routing.html#naming-routes
If you have resources :posts, you have a helper new_post_path to add new posts. Run rake routes to see your apps routes.
add_post_path does't follow Rails routes convention for resources and if you need it, must add a custom method:
resources :posts do
get :add, :on => :collection
end
You can read more about this in this Rails guide.
When you define match ':controller/:action/:id', you set the format of your app's urls and their params, but this do not magically will define routes helpers.

Resources