Adding Custom Route to Rails app - ruby-on-rails

I have read up on the Rails Guides.
What I want to set up are the following routes that are routed to the 'profiles' controller:
GET profiles/charities - Should display all the charities
GET profiles/charties/:id should display a specfic charity
GET profiles/donors - Should display all the donors
GET profiles/donors/:id - Should display a specfic donor
I have created the profile controller and two methods: charities and donors.
Is this all I need?

The following will set up routes for what you want, but will map them to :index and :show of CharitiesController and DonorsController:
namespace :profiles do
# Actions: charities#index and charities#show
resources :charities, :only => [:index, :show]
# Actions: donors#index and donors#show
resources :donors, :only => [:index, :show]
end
When it's more appropriate to set up custom routes, something like this would do:
get 'profiles/charities', :to => 'profiles#charities_index'
get 'profiles/charities/:id', :to => 'profiles#charities_show'
get 'profiles/donors', :to => 'profiles#donor_index'
get 'profiles/donors/:id', :to => 'profiles#donor_show'
Here are relevant sections in the guide that you were going through:
Resource Routing: the Rails Default - Controller Namespaces and Routing
Non-Resourceful Routes - Naming Routes

The charities and donors seem to be nested resources. If so, in your config/routes.rb file you should have something like,
resources :profiles do
resources :charities
resources :donors
end
Because these are nested resources, you do not need the two methods named charities and donors in your profiles controller. In fact, depending on your app, you may need separate controllers and/or models for your charities and donors.

Related

configuring routes for collections in rails

I have a rails application that needs to search two different collections independently, but both are indexed in a single solr instance. However, when i try to search in one collection, when i get to the item i want displayed, it reroutes to the same id within the other collection. How should i adjust my routes.rb to remedy this?
Here is the code:
Rails.application.routes.draw do
get 'biofile/search'
get 'masterfile/search'
mount Blacklight::Engine => '/'
Blacklight::Marc.add_routes(self)
root to: "catalog#index"
concern :searchable, Blacklight::Routes::Searchable.new
resource :catalog, only: [:index], as: 'catalog', path: '/', controller: 'catalog' do
concerns :searchable
end
resource :masterfile, only: [:search], as: 'masterfile', path: '/masterfile', controller: 'masterfile' do
concerns :searchable
end
resource :biofile, only: [:search], as: 'biofile', path: '/biofile', controller: 'biofile' do
concerns :searchable
end
devise_for :users
concern :exportable, Blacklight::Routes::Exportable.new
resources :solr_documents, only: [:show], path: '/catalog', controller: 'catalog' do
concerns :exportable
end
resources :solr_documents, only: [:show], path: 'masterfile', controller: 'masterfile' do
concerns :exportable
end
resources :solr_documents, only: [:show], path: 'biofile', controller: 'biofile' do
concerns :exportable
end
resources :bookmarks do
concerns :exportable
collection do
delete 'clear'
end
end
get '/catalog/masterfile/', to: 'masterfile#search', as: 'masterfile'
get '/catalog/biofile/', to: 'biofile#search', as: 'biofile'
get '*path' => redirect('/')
end
are you asking about nested routes? you want the path to look like model1_model2_path? the below example will give you group_memberships_path to use in your view and the url would have the id of the group and the id of the membership like .../groups/22/membership/13/edit
use rails routes in rails 5.x or rake routes in rails 4 to see the list of your new routes and you can see the urls will take 2 id's that can be passed to your application.
# nested routes for groups
resources :groups do
resources :memberships
end
I think you'll need to override this method https://github.com/projectblacklight/blacklight/blob/9f676994f437f7664cfc2b5c4dffe4382a6d14d3/lib/blacklight/search_state.rb#L48 either by configuration or monkeypatch to behave differently based on some info in solr document

How to name nested controllers and routes?

I'm working on creating a wiki app from scratch with the following organization:
Main Controller: Wiki
Nested Controller: WikiCategories
Nested Controller: WikiArticles
In my config/routes.rb I have:
resource :wiki do
resources :wiki_categories, :as => :categories
resources :wiki_articles, :as => :articles
end
I've chosen to name the categories and articles controllers as WikiCategories and WikiArticles to differentiate from other category and article controllers that I want to make in the future under a blog nesting.
This gives me the following routes:
/wiki/wiki_categories/new
/wiki/wiki_articles/new
Is there any way to rewrite the routes to be:
/wiki/categories/new
/wiki/articles/new
... while still using the WikiCategories and WikiArticles controller names?
I've chosen to name the categories and articles controllers as WikiCategories and WikiArticles to differentiate from other category and article controllers that I want to make in the future under a blog nesting.
IMO, it seems like you're bucking convention a bit. As discussed in Controller Namespaces and Routing, why not do:
namespace :wiki do
resources :categories, :articles
end
Which will give you:
wiki_categories GET /wiki/categories(.:format) wiki/categories#index
POST /wiki/categories(.:format) wiki/categories#create
new_wiki_category GET /wiki/categories/new(.:format) wiki/categories#new
edit_wiki_category GET /wiki/categories/:id/edit(.:format) wiki/categories#edit
wiki_category GET /wiki/categories/:id(.:format) wiki/categories#show
PATCH /wiki/categories/:id(.:format) wiki/categories#update
PUT /wiki/categories/:id(.:format) wiki/categories#update
DELETE /wiki/categories/:id(.:format) wiki/categories#destroy
wiki_articles GET /wiki/articles(.:format) wiki/articles#index
POST /wiki/articles(.:format) wiki/articles#create
new_wiki_article GET /wiki/articles/new(.:format) wiki/articles#new
edit_wiki_article GET /wiki/articles/:id/edit(.:format) wiki/articles#edit
wiki_article GET /wiki/articles/:id(.:format) wiki/articles#show
PATCH /wiki/articles/:id(.:format) wiki/articles#update
PUT /wiki/articles/:id(.:format) wiki/articles#update
DELETE /wiki/articles/:id(.:format) wiki/articles#destroy
Then, create namespaced controllers, something like:
app/controllers/wiki/categories.rb
class Wiki::CategoriesController < ApplicationController
...
end
and
app/controllers/wiki/articles.rb
class Wiki::ArticlesController < ApplicationController
...
end
Yes it is by specifying the controller, the resource can then be named whichever way you like.
resource :wiki do
resources :categories, controller: 'wiki_categories'
resources :articles, controller: 'wiki_articles'
end
Please see the guide for further information.
You can use the path: option as follows:
resource :wiki do
resources :wiki_categories, path: 'categories', :as => :categories
resources :wiki_articles, path: 'articles', :as => :articles
end
Which will give you:
/wiki/categories/...
/wiki/articles/...
See Translated Paths section of the guides for further details.

change routes URL from a random :id to :username in rails

I want to change my routes.rb file in a way so that it changes my current urls
localhost:3000/amitian/1
to localhost:3000/username
I will provide my routes.rb file for reference
Rails.application.routes.draw do
devise_for :amitians
root 'home#index'
resources :amitians do
member do
get :following, :followers
end
end
resources :confessions do
member do
get 'like' , to: 'confessions#upvote'
get 'dislike' , to: 'confessions#downvote'
end
resources :confessioncomments
end
resources :relationships, only: [:create, :destroy]
end
As Gregg mentioned, you can change the name of the parameter using:
resources :amitians, param: :username
But you're essentially just renaming a variable. Whether you expect an id or a username is determined in the controller action amitians#show:
#amitian = Amitian.find(param[:id]) # Treat :id as id
#amitian = Amitian.find_by_username(param[:id]) # Treat :id as username
Now, if you want to specifically route to /:username rather than /amitians/:username, you'll have to override that resource route:
resources :amitians, except: [:show] do
member do
get :following, :followers
end
end
get '/:username', to: 'amitians#show'
However, I would recommend against that. Having a parameter directly off root will cause lots of confusion for you when users type in the incorrect url and get a user page instead of a 404 error. Or even worse, what if a user chooses the username 'login' or 'register'? Either your register page would be unreachable or else that user's page would be.
I should also point out that rails convenience methods such as resources, Amitian.find, url_for #amitian, link_to #amitian etc. all use the REST standard which uses numerical IDs.
If you want to use a username instead of IDs, you'll have to stop relying on these methods and change your controllers and views, in addition to your routes file.
In rails 4 you can do the following in the route
resources :amitians, param: :username

Custom Route to Custom Page in Rails 4

I have an app with a parent resource (has_many) of patterns and a child resource (belongs_to) of snippets. My desire is to build a couple custom routes to specific pages and I am wondering the best way to do that. For now, here is what I have that is working, but I am wondering if there is a better way since the article I read on custom routing tells me this is not good practice.
I have purposefully not nested the resources because the snippets need to stand alone as well as be viewed within the context of their parent pattern.
The goal is to be able to create a few custom views like the following:
http://patterns.dev/patterns/:id/snippets //Got this one working, but incorrectly I believe
http://patterns.dev/patterns/:id/snippets/sort // Show all snippets for pattern to sort
http://patterns.dev/patterns/:id/images // Show all the images for patterns to moderate
routes.rb
Rails.application.routes.draw do
devise_for :users, :path => '', :path_names => {:sign_in => 'login', :sign_out => 'logout'}
resources :patterns
get 'patterns/:id/snippets' => 'patterns#snippets', as: 'pattern_snippets'
resources :snippets
root 'welcome#index'
end
I guess nested resources is what you need. You can specify just index action for nesting and keep all the snippets resources separately. Also you are to add some logic to snippets#index action to check params[:pattern_id]'s existance:
resources :patterns do
# this line will generate the `patterns/:id/snippets` route
# referencing to snippents#index action but within specific pattern.
# Also you have to add pattern_id column to snippets table to define the relation
resources :snippets, only: :index
end
resources :snippets
Use Collection Routes to make Rails to recognize paths like /patterns/:id/snippets/sort
resources :patterns do
resources :snippets, only: :index do
# this line will generate the `patterns/:id/snippets/sort` route
# referencing to snippets#sort action but again within specific pattern.
get :sort, on: :collection
end
end
resources :snippets
If you have Image model you can nest resources the same way like with snippets:
resources :patterns do
resources :images, only: :index
end
If it's just an action in patterns controller you can do:
resources :patterns do
get :images, on: :member
end

Aliasing routes in rails 4

If I have the following routes
resources :pages do
resources :sections
end
I get routes that look like this:
/pages = #index
/pages/:id = #show
/pages/:id/edit = #edit
...etc
How can I go about making it so that the url for the #show action of the pages controller looks like '/:id', without the '/pages/' prefix? should I exclude #show from resources :page & create a get route + alias for it separately? or is there a way to do it from inside the resources :page block? Thanks in advanced.
EDIT:
Changed it to:
resources :pages, except: [:show] do
resources :sections
end
get '/:id', to: 'pages#show'
& rerouting non-existing :ids' to 404 for now, let me know if there's a better solution. Thanks.
get '/:id', to: 'pages#show', as: 'page'
Make sure this is at the bottom of your routes.rb file, otherwise it is going to hijack requests to other routes.
This also gives you page_url and page_path helper methods. But to use them you must exclude show action from previous routes.
resources :pages, except: [:show]

Resources