I'm working on a preservation project where I have models for Institutions, Objects, and Files and I'm using resources in my routes file to help manage all of that. The problem I'm having is that resources uses the :id generated by Ruby on Rails for all of its routes and I would like to use a different attribute. This is particularly important for academic preservation and URL consistency. For example, I would like my show URL for an institution to read institutions/:identifier as opposed to institutions/:id, where :identifier is the attribute I have created. The problem is, I haven't been able to find any information on how to do this aside from just matching individual routes to the new ones I want which seems like a cheap hack at best and breaks a lot of my code.
This is my current routes file:
Fluctus::Application.routes.draw do
#match "institutions/", to: 'institutions#index', via: [:get]
#match "institutions/", to: 'institutions#create', via: [:post]
#match "institutions/:identifier", to: 'institutions#show', via: [:get]
#match "institutions/:identifier", to: 'institutions#update', via: [:patch]
#match "institutions/:identifier", to: 'institutions#update', via: [:put]
#match "institutions/:identifier", to: 'institutions#destroy', via: [:delete]
#match "institutions/:identifier/edit", to: 'institutions#edit', via: [:get]
#match "institutions/:identifier/events", to: 'events#index', via: [:get]
#match "institutions/new", to: 'institutions#new', via: [:get]
#
#match "objects/institution_identifier", to: 'intellectual_objects#index', via: [:get], as: "intellectual_objects_path"
#match "objects/institution_identifier", to: 'intellectual_objects#create', via: [:post]
resources :institutions do
resources :intellectual_objects, only: [:index, :create], path: 'objects'
resources :events, only: [:index]
end
resources :intellectual_objects, only: [:show, :edit, :update, :destroy], path: 'objects' do
resources :generic_files, only: :create, path: 'files'
patch "files/:id", to: 'generic_files#update', constraints: {id: /.*/}, trailing_slash: true, format: 'json'
resources :events, only: [:create, :index]
end
devise_for :users
resources :users do
patch 'update_password', on: :collection
get 'edit_password', on: :member
patch 'generate_api_key', on: :member
end
resources :generic_files, only: [:show, :destroy], path: 'files' do
resources :events, only: [:create]
end
Blacklight.add_routes(self)
mount Hydra::RoleManagement::Engine => '/'
authenticated :user do
root to: "institutions#show", as: 'authenticated_root'
# Rails 4 users must specify the 'as' option to give it a unique name
# root :to => "main#dashboard", :as => "authenticated_root"
end
root :to => "catalog#index"
end
You can see where I have attempted to match individual routes without much luck. I've also looked into FriendlyID without any luck so far. If anyone has any ideas it would be greatly appreciated. Thank you!
Unless I'm missing something here, you should just be able to stick the string you want to use into the URL where the id whould be. For example, /objects/show/1 would become /objects/show/some_string. Then in your controller you can find the object using the id parameter:
def show
#object = Object.where(:some_attribute => params[:id]).first
end
Related
I'm using the friendly_id gem in a Rails application, to be able to view organisations at site.com/organisation-name
The problem is that I have a few static pages like "About" and "Contact" at site.com/about and friendly_id assumes these pages should point to a record, hence I get this error.
ActiveRecord::RecordNotFound in OrganisationsController#show
can't find record with friendly id: "about"
routes.rb
resources :organisations, path: "", except: [:index, :new, :create] do
resources :posts
end
get '/organise', to: 'home#organise'
get '/privacy', to: 'home#privacy'
get '/about', to: 'home#about'
get '/terms', to: 'home#terms'
Is there a way to ignore these routes at all, or do I need to prefix them with something else?
The solution was to simply reorder my routes to put the static page routes above my organisations route definition:-
get '/organise', to: 'home#organise'
get '/privacy', to: 'home#privacy'
get '/about', to: 'home#about'
get '/terms', to: 'home#terms'
resources :organisations, path: "", except: [:index, :new, :create] do
resources :posts
end
I'm deploying my Rails app that uses the clearance gem to Heroku. Everything works fine in development but I'm running into trouble with the gem generated routes I get.
When attempting to deploy to Heroku, I get the error...
ArgumentError: Invalid route name, already in use: 'sign_in'
You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here:
remote: http://guides.rubyonrails.org/routing.html#restricting-the-routes-created
I'm not seeing where to restrict the duplicates or where they would be generated with any of my resources:
Please see routes.rb file below
Routes.rb
Rails.application.routes.draw do
resources :passwords, controller: "clearance/passwords", only: [:create, :new]
resource :session, controller: "clearance/sessions", only: [:create]
resources :users, controller: "clearance/users", only: [:create] do
resource :password,
controller: "clearance/passwords",
only: [:create, :edit, :update]
end
get "/sign_in" => "clearance/sessions#new", as: "sign_in"
delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out"
get "/sign_up" => "clearance/users#new", as: "sign_up"
get 'newSignUp', to: 'signups#new'
post 'newSignUp', to: 'signups#create'
get 'newTrip', to: 'trips#new'
post 'newTrip', to: 'trips#create'
get 'trips/:id/send_itinerary' => 'trips#send_itinerary', as: :trips_send_itinerary
root 'static_pages#home'
get 'static_pages/home'
get 'static_pages/help'
get 'static_pages/about'
get 'static_pages/contact'
resources :signups
resources :tripitems
resources :trips
end
This issue has to do with the clearance gem.
I am not totally familiar with the gem, so as per usual, I checked out the github and found the following:
# config/routes.rb
if Clearance.configuration.routes_enabled?
Rails.application.routes.draw do
resources :passwords,
controller: 'clearance/passwords',
only: [:create, :new]
resource :session,
controller: 'clearance/sessions',
only: [:create]
resources :users,
controller: 'clearance/users',
only: Clearance.configuration.user_actions do
resource :password,
controller: 'clearance/passwords',
only: [:create, :edit, :update]
end
get '/sign_in' => 'clearance/sessions#new', as: 'sign_in'
delete '/sign_out' => 'clearance/sessions#destroy', as: 'sign_out'
if Clearance.configuration.allow_sign_up?
get '/sign_up' => 'clearance/users#new', as: 'sign_up'
end
end
end
This is basically creating the same routes for you, only if the config routes_enabled? is true.
You need to configure clearance as follows to handle the routes yourself:
config.routes = false
After looking at the gems GitHub, it looks like I raked the routes earlier and even though config.routes was set to false in the initializer, there was a conflict generate in the generated resources in production.
I wound up deleting the raked routes and making config.routes=true.
Right now I have the route as below;
resources :invoices do
collection do
match 'search' => 'invoices#search', via: [:get, :post], as: :search
end
end
But I would like to get 'deliveries#search' instead of 'invoices#search'.
I successfully customized for the below routes;
get 'deliveries', to: 'invoices#index', as: :deliveries
get 'deliveries/new', to: 'invoices#new', as: :delivery
get 'deliveries/:id/edit', to: 'invoices#edit', :as => :del
I have tried but unable to customized for the 'deliveries#search'.
Any suggestions are most welcome.
Thank you in advance.
resources :invoices, path: 'deliveries' do
collection do
match 'search' => 'invoices#search', via: [:get, :post], as: :search
end
end
it will generate route with prefix deliveries like /deliveries/your_action
Change your routes as follows
resources :deliveries, controller: 'invoices', only: [:index, :new, :edit]
resources :deliveries, only: [] do
collection do
get :search
post :search
end
end
This will generate following routes for you:
deliveries GET /deliveries(.:format) invoices#index
new_delivery GET /deliveries/new(.:format) invoices#new
edit_delivery GET /deliveries/:id/edit(.:format) invoices#edit
search_deliveries GET /deliveries/search(.:format) deliveries#search
POST /deliveries/search(.:format) deliveries#search
EDIT
According to your comment I think you just need to use different controller
Try this
resources :deliveries, controller: 'invoices', only: [:index, :new, :edit] do
collection do
get :search
post :search
end
end
This will generate following routes:
search_deliveries GET /deliveries/search(.:format) invoices#search
POST /deliveries/search(.:format) invoices#search
deliveries GET /deliveries(.:format) invoices#index
new_delivery GET /deliveries/new(.:format) invoices#new
edit_delivery GET /deliveries/:id/edit(.:format) invoices#edit
I'm trying to define custom routes to my controller and I need to use some of the default routes too. Is there any simple solution?
So far I've something like this
resources :users do
member do
get 'users/:id', to: 'users#show'
delete 'users/:id', to: 'users#destroy'
end
collection do
post 'users', to: 'users#create'
post 'users/login', to: 'users#login'
end
end
resources :users, :only => [:show, :destroy, :create, :login]
I don't need nor want the index route but with this settings it's still trying to route GET users/ to user_controller index method.
I know that there is probably some simple and obvious answer but I'm not able to find it.
Thank's in advance.
You got your routes wrong. The resources :users generates seven default routes which include the index route as well. You need to tweak the code to below
resources :users, :only => [:show, :destroy, :create] do
collection do
post 'login', to: 'users#login'
end
end
Note:
If you noticed, I've removed the custom routes for show,create and delete as they are generated by default.
Your first line defines the route to the index action. Define a resource once only. Read the routing guide.
resources :users, :except => [:index] do
collection do
post 'users/login', to: 'users#login'
end
end
Run rake routes from the command line in your project root folder to see all your route definitions.
I'm following Michael Hartl's Rails Tutorial and deploying to Heroku.
I have static pages that are public to every web visitor and dynamic and "protected" pages that require the user to sign in in order to view them. Currently all pages are deployed to the website's root: example.com/static-page and example.com/users/1/
My objective:
deploy static pages to the root, like example.com/static-page
deploy rails' pages to a subdomain, like app.example.com/users/1
I assume the solution involves changing the routes file. Is there any tutorial or video explaining how to do so? I'm a newbie on Rails.
My routes file:
Dcid::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
root 'static_pages#home'
match '/home', to: 'static_pages#home', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
You could either have a controller serving your pages or simply put your HTML files in public an treat them as assets.
In either case if they are really static, you might want to cache heavily or put a CDN in front of everything.
You'll want something like this:
#config/routes.rb
root 'static_pages#home'
#Subdomain
constraints subdomain: 'app' do
resources :users
end
#Pages
pages = %w(home about)
for page in pages do
get "/#{page}", to: "static_pages##{page}"
end
#Resources
resources :users do
get :new, as: :collection
end
resources :sessions, only: [:new, :create, :destroy] do
get :signin, action: :new, as: :collection
delete :signout, to: :destroy, as: :collection
end
This will create the routes you need. However, you won't be able to use a subdomain on Heroku, unless you use a custom domain