Using rails 4.2.1
I want to store my rails declared routes from config/routes.rb into a ruby hash that I can access or render somewhere.
The hash should be of the format
{
name: 'path',
# e.g.
login: '/login',
home: '/'
}
How do I do this in rails?
Note: I think you get the routes through Rails.application.routes and maybe the names from Rails.application.routes.routes.named_routes.keys, but what's next?
This will give you a Hash where the keys are the route names and the values are the paths:
routes = Hash[Rails.application.routes.routes.map { |r| [r.name, r.path.spec.to_s] }]
routes will now look like:
{
"entities" => "/entities(.:format)",
"new_entity" => "/entities/new(.:format)",
"edit_entity" => "/entities/:id/edit(.:format)",
"entity" => "/entities/:id(.:format)"
}
If you really have to do this, you can:
ri = ActionDispatch::Routing::RoutesInspector.new([])
result = ri.send :collect_routes, Rails.application.routes.routes
The result will be an array of hashes which look like:
{:name=>"product", :verb=>"GET", :path=>"/products/:id(.:format)", :reqs=>"products#show", :regexp=>"^\\/products\\/([^\\/.?]+)(?:\\.([^\\/.?]+))?$"}
You may want to use the JS-Routes gem that generates a javascript file that defines all Rails named routes as javascript helpers.
Setup (just add it to the asset pipeline):
# add to your application.js
/*
= require js-routes
*/
Usage your javascript code like this:
Routes.users_path() // => "/users"
Routes.user_path(1) // => "/users/1"
Routes.user_path(1, {format: 'json'}) // => "/users/1.json"
Find the documentation here: https://github.com/railsware/js-routes#usage
Related
I'm working on a vanilla Rails 4.2 app for a demo of building a JSON API with Rails.
bundle exec rails g scaffold widget name
Out of the box, Rails provides an easy way to fetch a resource as JSON by simply adding .json to the end of the URL.
/widgets.json
# or...
/widgets/123.json
However, I was wondering what is the most simple way to allow Rails to respond as JSON by using other means than simply appending .json. Do I need to send an Accept header in the request? Or do I have to explicitly respond_to :json in order to add this support? I also need to continue to support HTML, but wanted a clean URL. What do I need to do?
For defining all the routes to json use the following code.
resources :you_resouce, :defaults => { :format => 'json' }
For specific route use the following code.
scope :format => true, :constraints => { :format => 'json' } do
get '/endpoint' => "controller#action_method"
end
I'm switching from using a laravel php framework to a rails framework and cannot figure out how to get nested routes working in rails like it did in laravel. In laravel it would work like this:
Route::group(['prefix' => 'healthandwelness'], function() {
Route::get('', [
'uses' => 'healthandwelness#index'
]);
Route::group(['prefix' => 'healthcare'], function() {
Route::get('', [
'uses' => 'healthcare#index'
]);
Route::get('{article_id}', [
'uses' => 'article#index'
]);
]);
});
Which would give me the routes:
/healthandwellness
/healthandwellness/healthcare
/healthandwellness/healthcare/{article_id}
The only way I've seen to nest routes in rails is with resources which I've used to tried and recreate my routes in rails like this:
resources :healthandwellness do
resources :healthcare
end
But the nature of resources makes this route into the following gets:
/healthandwellness
/healthandwellness/:health_and_wellness_id/healthcare
/healthandwellness/:health_and_wellness_id/healthcare/:id
Is there anyway to do what I am looking for in rails and recreate what I was able to do laravel?
You can use namespace:
namespace :healthandwellness do
resources :healthcare
end
Note that this assumes that your controller is located in app/controllers/healthsandwellness/healthcare_controller.rb and should be defined as follows:
class Healthandwellness::HealthcareController < ApplicationController
...
end
If you want to keep your controller under apps/controller and not scoped under app/controllers/healthandwellness, you can use scope:
scope '/healthandwellness' do
resources :healthcare
end
The documentation here provides good examples of namespace and scope
I already see some similar quetions:
How to set the default format for a route in Rails?
Rails 3 respond_to: default format?
Rails 3.1 force .html instead of no extension
But any solution didn't work in rails 4 for me:
in routers.rb
:defaults => { :format => 'html' }
in app/controllers/some_controller.rb
before_filter :set_format
def set_format
request.format = 'html'
end
in config/application.rb
config.default_url_options = { :format => "html" }
Any of there. I tried all it together and each separate.
Here my code:
link_to("Read more", article_path(article, :format => "html"))
# => Read more
What will be if I remove :format => "html":
link_to("Read more", article_path(article))
# => Read more
What I am want:
link_to("Read more", article_path(article))
# => Read more
Share your suggestion for it, please.
If you use add these options to your route, I think you'll end up with the .html in the path like you want. You shouldn't even need to modify your call to article_path.
format: true, defaults: { format: 'html' }
I ran into something similar. Looking through the Rails routing docs helped me find an answer.
I have an action which I want to default to the CSV format, but I also want to generate the URL with the .csv in it. This way the client can tell, just by looking at the URL, that it's a CSV. Without the .csv, it's not very clear what the link will be.
My route was something like this:
get 'customers/with_favorite_color/:color' => 'customers#with_favorite_color', as: :customers_with_favorite_color, format: 'csv'
And I was generating the link like this:
customers_with_favorite_color_url(color: 'blue', format: :csv)
# => `http://localhost:3000/customers/with_favorite_color/blue
Except, I want http://localhost:3000/customers/with_favorite_color/blue.csv.
It seemed that the format would not be added to the URL if that format was also specified in the route.
To get this to work, I changed my route to
get 'customers/with_favorite_color/:color' => 'customers#with_favorite_color', as: :customers_with_favorite_color, format: true, defaults: { format: 'csv' }
Notice the options added/changed are: format: true, defaults: { format: 'csv' }
And now, when I generate the URL, I get the .csv appended like I wanted.
customers_with_favorite_color_url(color: 'blue')
# => `http://localhost:3000/customers/with_favorite_color/blue.csv
Update
To apply this to many routes, you can follow the advice of How to set default format for routing in Rails? and use a scope with these defaults.
scope format: true, defaults: { format: 'html' } do
# Define your resources here like normal
end
I want my urls to use dash - instead of underscore _ as word separators. For example controller/my-action instead of controller/my_action.
I'm surprised about two things:
Google et al. continue to distinguish them.
That Ruby on Rails doesn't have a simple, global configuration parameter to map - to _ in the routing. Or does it?
The best solution I've is to use :as or a named route.
My idea is to modify the Rails routing to check for that global config and change - to _ before dispatching to a controller action.
Is there a better way?
With Rails 3 and later you can do like this:
resources :user_bundles, :path => '/user-bundles'
Another option is to modify Rails, via an initializer.
I don't recommend this though, since it may break in future versions (edit: doesn't work in Rails 5).
Using :path as shown above is better.
# Using private APIs is not recommended and may break in future Rails versions.
# https://github.com/rails/rails/blob/4-1-stable/actionpack/lib/action_dispatch/routing/mapper.rb#L1012
#
# config/initializers/adjust-route-paths.rb
module ActionDispatch
module Routing
class Mapper
module Resources
class Resource
def path
#path.dasherize
end
end
end
end
end
end
You can overload controller and action names to use dashes:
# config/routes.rb
resources :my_resources, path: 'my-resources' do
collection do
get 'my-method', to: :my_method
end
end
You can test in console:
rails routes -g my_resources
my_method_my_resources GET /my-resources/my-method(.:format) my_resources#my_method
You can use named routes. It will allow using '-' as word seperators. In routes.rb,
map.name_of_route 'a-b-c', :controller => 'my_controller', :action => "my_action"
Now urls like http://my_application/a-b-c would go to specified controller and action.
Also, for creating dynamic urls
map.name_of_route 'id1-:id2-:id3', :controller => 'my_controller', :action => "my_action"
in this case 'id1, id2 & id2 would be passed as http params to the action
In you actions and views,
name_of_route_url(:id1=>val1, :id2=>val2, :id3=>val3)
would evaluate to url 'http://my_application/val1-val2-val3'.
if you use underscores in a controller and view file then just use dashes in your routes file, and it will work..
get 'blog/example-text' this is my route for this controller
def example_text
end <-- this is my controller
and example_text.html.erb is the file
and this is the actual link site.com/blog/example-text
i figured this is works for me, and it's more effective than underscores SEO wise
Say I have a router helper that I want more info on, like blogs_path, how do I find out the map statements behind that in console.
I tried generate and recognize and I got unrecognized method error, even after I did require 'config/routes.rb'
There is a good summary with examples at Zobie's Blog showing how to manually check URL-to-controller/action mapping and the converse. For example, start with
r = Rails.application.routes
to access the routes object (Zobie's page, a couple years old, says to use ActionController::Routing::Routes, but that's now deprecated in favor of Rails.application.routes). You can then check the routing based on a URL:
>> r.recognize_path "/station/index/42.html"
=> {:controller=>"station", :action=>"index", :format=>"html", :id=>"42"}
and see what URL is generated for a given controller/action/parameters combination:
>> r.generate :controller => :station, :action=> :index, :id=>42
=> /station/index/42
Thanks, Zobie!
In the console of a Rails 3.2 app:
# include routing and URL helpers
include ActionDispatch::Routing
include Rails.application.routes.url_helpers
# use routes normally
users_path #=> "/users"
Basically(if I understood your question right) it boils down to including the UrlWriter Module:
include ActionController::UrlWriter
root_path
=> "/"
Or you can prepend app to the calls in the console e.g.:
ruby-1.9.2-p136 :002 > app.root_path
=> "/"
(This is all Rails v. 3.0.3)
running the routes command from your project directory will display your routing:
rake routes
is this what you had in mind?
If you are seeing errors like
ActionController::RoutingError: No route matches
Where it should be working, you may be using a rails gem or engine that does something like Spree does where it prepends routes, you may need to do something else to view routes in console.
In spree's case, this is in the routes file
Spree::Core::Engine.routes.prepend do
...
end
And to work like #mike-blythe suggests, you would then do this before generate or recognize_path.
r = Spree::Core::Engine.routes