Trying to simplify some parts of routes - ruby-on-rails

I want to simplify this somehow:
namespace :api do
namespace :v1 do
get ":domain/test1" => "home#test1", constraints: { domain: /[0-z\.]+/ }, defaults: { format: :json }
get ":domain/test2" => "home#test2", constraints: { domain: /[0-z\.]+/ }, defaults: { format: :json }
get ":domain/test3" => "home#test3", constraints: { domain: /[0-z\.]+/ }, defaults: { format: :json }
# ........... and so on
end
end
Is there any way?

Maybe this can help you?
http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
For your problem, you have to use:
get '/stories/:name', to: redirect('/posts/%{name}')

Perhaps you'd like to use some sort of method in your routes:
#config/routes.rb
def record id
get ":domain/#{id}" => "home#test#{id}", constraints: { domain: /[0-z\.]+/ }, defaults: { format: :json }
end
namespace :api do
namespace :v1 do
x = 10
x.times do |i|
record i
end
end
end
Very bloated, memory wise, of course.
The killer is the :domain constraint. I was ready to just create a resources :home call, with some custom methodology inside - but you'll have to define the constraint manually each time you reference the route you require

Related

Rails no route matches despite rails route output results

Route fails to match despite matching route found in rails routes
No route matches {:action=>"update", :controller=>"croppable_images", :name=>"cover_photo", :record_type=>"Stager"}, possible unmatched constraints: [:name] excluded from capture: No host specified, no public_key specified, no project_id specified
ActionController::UrlGenerationError (No route matches {:action=>"update", :controller=>"croppable_images", :name=>"cover_photo", :record_type=>"Stager"}, possible unmatched constraints: [:name]):
app/controllers/croppable_images_controller.rb:19:in `edit'
127.0.0.1 - - [04/Feb/2022:16:28:44 CST] "GET /stager/profile/cover_photo HTTP/1.1" 500 143893
http://localhost:3000/stager/profile -> /stager/profile/cover_photo
The route call
#edit_image_url = stagers_stager_croppable_image_path('cover_photo')
<%=
form_for(
#croppable_image,
url: #edit_image_url,
method: :put
) do |f|
%>
routes.rb section:
namespace :stagers, path: 'stager' do
resource(
:stager,
path: 'profile',
only: %i[edit update],
path_names: {
edit: ''
}
) do
%w[
profile_photo
cover_photo
].each do |croppable_image_name|
resources(
:croppable_image,
controller: '/croppable_images',
path: '',
param: :name,
only: %i[edit update],
path_names: {
edit: ''
},
defaults: {
record_type: 'Stager'
},
constraints: {
name: croppable_image_name
}
)
end
end
end
The route:
Helper
HTTP Verb
Path
Controller#Action
edit_stagers_stager_croppable_image_path
GET
/stager/profile/:name(.:format)
croppable_images#edit {:record_type=>"Stager", :name=>"profile_photo"}
stagers_stager_croppable_image_path
PATCH
/stager/profile/:name(.:format)
croppable_images#update {:record_type=>"Stager", :name=>"profile_photo"}
PUT
/stager/profile/:name(.:format)
croppable_images#update {:record_type=>"Stager", :name=>"profile_photo"}
GET
/stager/profile/:name(.:format)
croppable_images#edit {:record_type=>"Stager", :name=>"cover_photo"}
PATCH
/stager/profile/:name(.:format)
croppable_images#update {:record_type=>"Stager", :name=>"cover_photo"}
PUT
/stager/profile/:name(.:format)
croppable_images#update {:record_type=>"Stager", :name=>"cover_photo"}
You are setting up that route with a constraint
%w[profile_photo cover_photo].each do |croppable_image_name|
resrources
...
constraints: { name: croppable_image_name }
end
end
So you need to add name: to your route, so this should work:
stagers_stager_croppable_image_path(name: 'profile_photo')
However, since you are not using a specific route name on that each loop, calling it with name set to cover_photo will not work. I think you probably want to use a regex like
constraints: { name: /(cover|profile)_photo/ }
Try declaring your routes like this (sorry I messed up your style)
Rails.application.routes.draw do
namespace :stagers, path: 'stager' do
resource(:stager, path: 'profile', only: %i[edit update], path_names: { edit: '' }) do
resources(
:croppable_image,
controller: '/croppable_images',
path: '',
param: :name,
only: %i[edit update],
path_names: {
edit: ''
},
defaults: {
record_type: 'Stager'
},
constraints: {
name: /(cover|profile)_photo/
}
)
end
end
end

RubySpec to test a redirect in Ruby controller

I'm trying to code a spec for a method who redirect to a specific path when the user access to provider/plans and provider/prospects
I was trying with many path combinations in the before group, i was trying with this.
before { get :provider_plans_index_path }
before { get :provider_index_plans_path}
before { get :provider_plans_path}
before { get :provider_index_path}
before { get :provider_plans_path}
before { get :provider_planes_path}
base_controller.rb
class Provider::BaseController < ActionController::Base
layout 'provider'
before_action :allowed_pages
def allowed_pages
redirect_to financial_dashboard_path if !requested_action?(params[:controller])
end
def requested_action?(data)
regexp = %r{
^(provider/plans)|
(provider/prospects)$
}x
data.match?(regexp)
end
end
base_controller_spec.rb
require 'rails_helper'
describe Provider::BaseController, type: :controller do
let(:provider) { create(:provider) }
let(:financial) { create(:financial, provider: provider) }
let(:user) { provider.user }
before { login_user user }
describe 'GET plans' do
context 'with not allowed url' do
before { get :provider_planes_path}
it { should redirect_to financial_dashboard_path}
end
end
end
routes.rb
namespace :provider do
get '', to: 'dashboard#index'
get 'dashboard', to: 'dashboard#index'
resources :plans, only: [:index, :create, :update], path: 'planes'
resources :prospects, only: [:index, :show, :create, :update], path: 'prospectos' do
get 'diagnostico', to: 'prospects#show', on: :member, as: :general
patch 'diagnostico', to: 'prospects#update', on: :member
get 'configuracion', to: 'prospects#configuration', on: :member, as: :configuration
end
end
I'm getting this error with all the combinations
ActionController::UrlGenerationError:
No route matches
For me the solution was call the action in spec via another controller
context 'with not allowed url' do
before do
#controller = Provider::PlansController.new
get :index
end
it { should redirect_to financial_dashboard_path }
end

ActionController::UnknownFormat (format.csv)

I know this question has been asked, but for different formats. My concern is with format.csv.
My Try
Route
match '/something.csv' => 'admin#something', via: :get
Controller
def something
respond_to do |format|
format.csv { render text: ["a", "b"].to_csv } #Just a try
#format.csv { render csv: ["a", "b"].to_csv }
end
end
It throws ActionController::UnknownFormat, when I hit http://localhost:3000/admin/something.csv
EDIT
I was following RailsCast, but could find no suggestions to alter routes like Eg:- defaults: { format: :csv } (as suggested in Kajal Ojha's answer)
I was facing a same error today and it was resolved by providing a default format in route.
In your case it is
match '/something.csv' => 'admin#something', via: :get, defaults: { format: :csv }

List all rails routes with http method associated

I use this method to list all routes of my rails application:
def routes
Rails.application.routes.routes.collect do |r|
{ path: r.path.spec.to_s }
end
end
My result is:
[
{ :path => '/my/path/' },
{ :path => '/my/path2/' },
...
]
I want to obtain also the http method used for that route. How to do it?
Exploring class documentation I couldn't find it.
The expected result is:
[
{ :path => '/my/path/', :method => :get },
{ :path => '/my/path2/', :method => :post },
...
]
There is a way to obtain the http method associated to a route? (or a list of methods)
ActionDispatch::Journey::Route has a verb method which returns a RegExp:
You could try this:
def routes
Rails.application.routes.routes.collect do |r|
{ path: r.path.spec.to_s, :verb => r.verb.source[/[a-z]+/i].to_sym }
end
end

No Route Found Error in custom rails params

I'm working on an application where I've had to put together some custom rails parameters for the routes and I keep getting no route found errors when I try to access the page associated with the show method. The application is allowing me to reach my edit pages, so I know it's working on some level but I have to have an error I'm not seeing somewhere that's messing with the normal view. The custom parameters rely on an :identifier that has been custom created for each object. Because the application manages several institutions, all with their objects and files, I've had to right several different sets of routes to handle each different thing. The routes for institutions seem to be working fine, but the second set, for :intellectual_objects are the ones that aren't working.
This is my routes file (irrelevant parts excluded):
Fluctus::Application.routes.draw do
get "institutions/:institution_identifier/objects", to: 'intellectual_objects#index', as: :institution_intellectual_objects, :constraints => { :institution_identifier => /[\w+\.]+/ }
post "institutions/:institution_identifier/objects", to: 'intellectual_objects#create', :constraints => { :institution_identifier => /[\w+\.]+/ }
#Intellectual Object Routes
#get "objects/:institution_identifier", to: 'intellectual_objects#index', as: :institution_intellectual_objects, :constraints => { :institution_identifier => /[\w+\.]+/ }
#post "objects/:institution_identifier", to: 'intellectual_objects#create', :constraints => { :institution_identifier => /[\w+\.]+/ }
patch "objects/:intellectual_object_identifier", to: 'intellectual_objects#update', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
put "objects/:intellectual_object_identifier", to: 'intellectual_objects#update', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
delete "objects/:intellectual_object_identifier", to: 'intellectual_objects#destroy', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
get "objects/:intellectual_object_identifier/edit", to: 'intellectual_objects#edit', as: :edit_intellectual_object, :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
get "objects/:intellectual_object_identifier/events", to: 'events#index', as: :intellectual_object_events, :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
post "objects/:intellectual_object_identifier/events", to: 'events#create', :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
get "objects/:intellectual_object_identifier", to: 'intellectual_objects#show', as: :intellectual_object, :constraints => { :intellectual_object_identifier => /[\w+\/\.]+/ }
#post "objects/institution_identifier/:intellectual_object_identifier/data", to: 'generic_files#create', as: intellectual_object_generic_files, :constraints => { [:intellectual_object_identifier, :institution_identifier] => /[\w+\.]/ }
#patch "objects/institution_identifier/:intellectual_object_identifier/data/:filename", to: 'generic_files#update', :constraints => { [:intellectual_object_identifier, :institution_identifier] => /[\w+\.]/ }
Blacklight.add_routes(self)
mount Hydra::RoleManagement::Engine => '/'
root :to => "catalog#index"
end
This is my IntellectualObject Controller:
class IntellectualObjectsController < ApplicationController
before_filter :authenticate_user!
#load_and_authorize_resource :institution, only: [:index, :create]
load_and_authorize_resource :through => :institution, only: :create
#load_and_authorize_resource except: [:index, :create]
before_filter :set_object, only: [:show, :edit, :update, :destroy]
before_filter :set_institution, only: [:index, :create]
include Aptrust::GatedSearch
apply_catalog_search_params
include RecordsControllerBehavior
self.solr_search_params_logic += [:for_selected_institution]
def update
if params[:counter]
# They are just updating the search counter
search_session[:counter] = params[:counter]
redirect_to :action => "show", :status => 303
else
# They are updating a record. Use the method defined in RecordsControllerBehavior
super
end
end
def destroy
resource.soft_delete
respond_to do |format|
format.json { head :no_content }
format.html {
flash[:notice] = "Delete job has been queued for object: #{resource.title}"
redirect_to root_path
}
end
end
protected
# Override Hydra-editor to redirect to an alternate location after create
def redirect_after_update
intellectual_object_path(resource)
end
def self.cancan_resource_class
CanCan::ControllerResource
end
private
def for_selected_institution(solr_parameters, user_parameters)
#puts "In for_selected_institution------------------------------------------"
#puts params[:institution_identifier]
#puts params[:intellectual_object_identifier]
if(params[:institution_identifier])
institution = Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).first
else
io = IntellectualObject.where(desc_metadata__intellectual_object_identifier_tesim: params[:intellectual_object_identifier]).first
institution = io.institution
end
#puts "INSTITUTION: #{institution.id}"
solr_parameters[:fq] ||= []
solr_parameters[:fq] << ActiveFedora::SolrService.construct_query_for_rel(is_part_of: "info:fedora/#{institution.id}")
end
# Override Blacklight so that it has the "institution_identifier" set even when we're on a show page (e.g. /objects/foo:123)
def search_action_url options = {}
institution_intellectual_objects_path(params[:institution_identifier] || #intellectual_object.institution.institution_identifier)
end
def set_institution
if params[:institution_identifier].nil? || Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).empty?
redirect_to root_url
flash[:alert] = "Sonething wrong with institution_identifier."
else
#institution = Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).first
authorize! [:create, :index], #institution if cannot? :read, #institution
end
end
def set_object
if params[:intellectual_object_identifier].nil? || IntellectualObject.where(desc_metadata__intellectual_object_identifier_tesim: params[:intellectual_object_identifier]).empty?
redirect_to root_url
flash[:alert] = "Something wrong with intellectual_object_identifier."
else
io_options = IntellectualObject.where(desc_metadata__intellectual_object_identifier_tesim: params[:intellectual_object_identifier])
io_options.each do |io|
if params[:intellectual_object_identifier] == io.intellectual_object_identifier
#intellectual_object = io
#institution = #intellectual_object.institution
end
end
if #intellectual_object.nil?
redirect_to root_url
flash[:alert] = "The object you requested does not exist."
end
#authorize! [:show, :edit, :update, :destroy], #institution if cannot? :read, #institution
end
end
end
I'm getting the following error when I try to access the show route (for example: localhost:3000/objects/test.org/126939282):
ActionController::UrlGenerationError in IntellectualObjects#show
Showing /Users/kec6en/HydraApp/fluctus/app/views/intellectual_objects/_facet_limit.html.erb where line #11 raised:
No route matches {:action=>"index", :intellectual_object_identifier=>"columbia.edu/798d6e812041532c", :controller=>"intellectual_objects", :f=>{"institution_name_ssi"=>["Columbia University"]}}
The parameters are showing:
{"intellectual_object_identifier"=>"columbia.edu/798d6e812041532c"}
And I'm getting this error when I run my spec tests on the IntellectualObjectController
Failure/Error: get :show, intellectual_object_identifier: obj1
ActionController::UrlGenerationError:
No route matches {:intellectual_object_identifier=>"kaulkedurgan.org13/39b1eb47-da8b-4145-b03b-5f1851407012", :controller=>"intellectual_objects", :action=>"show"}
I just don't understand because the routes are there, and some of them appear to be working in the application, but every single one is failing in my spec tests. Any and all help is appreciated. Thank you.
Your route to intellectual_objects#index has the constraint that the :institution_identifier should match /[\w+\.]+/, but columbia.edu/798d6e812041532c does not match that regexp. Even when you add \/ to your regexp, I am pretty sure that the slash will confuse Rails routing system.
Perhaps you want to change the route to something like this
get "institutions/:institution_identifier/:some_id/objects",
to: 'intellectual_objects#index',
as: :institution_intellectual_objects,
constraints: { institution_identifier: /[\w+\.]+/ }
And than provide columbia.edu (institution_identifier) and 798d6e812041532c (some_id) as separate values.
According to your error:
No route matches {:action=>"index"
It seems you're trying to access the index action?
Being honest, I couldn't bring myself to look through all your routes (you may want to cut out the irrelevant stuff?)
How are you calling the routes with link_to?

Resources