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
Related
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
Let's take the following router :
Rails.application.routes.draw do
scope ":locale", locale: /en|nl/ do
get "/:slug", to: "pages#prefixed_action", constraints: { slug: /.*/ }
end
root to: "pages#simple_action"
get "/:slug", to: "pages#simple_action", constraints: { slug: /.*/ }
end
If the request specifies a locale, the scope catches it and forwards it to pages#prefixed_action. If not the request is forwarded topages#simple_action.
My issue is that if I enter localhost:3000/en in the browser, it won't be catched by the scope. How can I arrange that ?
Edit1: I'd like the request to be routed to "pages#prefixed_action"
Edit2: added a root declaration in the code sample
One of the possibilities is to specify root inside the scope:
scope ":locale", locale: /en|nl/ do
root 'pages#prefixed_action'
get "/:slug", to: "pages#prefixed_action", constraints: { slug: /.*/ }
end
Maybe simply like this:
get '/:locale', to: "pages#prefixed_action", constraints: { locale: /(en|nl)/ }
get '/:locale', to: "pages#simple_action", constraints: { locale: /.*/ }
If your goal is to send to pages#prefixed_action with paths /en and /nl and all other to pages#simple_action. If so, put
get '/:locale', to: "pages#simple_action", constraints: { locale: /.*/ }
As a last route in your routes
I am using devise_saml_authenticatable gem in my rails application to integrate it with external SSO, I have configured my application but I am getting Completed 401 Unauthorized in 119ms from devise/saml_sessions controller.
My config/initializers/devise.rb
config.saml_create_user = true
config.saml_update_user = true
config.saml_default_user_key = :email
config.saml_session_index_key = :session_index
config.saml_use_subject = true
config.idp_settings_adapter = CidpSettingsAdapter
IDP Settings Adapter
class CidpSettingsAdapter
def self.settings(idp_entity_id)
{
issuer: 'https://devidentity.greenfence.com/users/saml/metadata',
assertion_consumer_service_url: 'https://devidentity.greenfence.com/saml/consume',
assertion_consumer_service_binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
#assertion_consumer_logout_service_url: 'https://devidentity.greenfence.com/users/saml/sign_out',
idp_entity_id: 'https://cargill.identitynow.com',
authn_context: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport',
name_identifier_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
idp_sso_target_url: 'https://prd02-useast1-sso.identitynow.com/sso/SSOPOST/metaAlias/cargill/idp',
idp_slo_target_url: 'https://prd02-useast1-sso.identitynow.com/sso/IDPSloPOST/metaAlias/cargill/idp',
security: {
authn_requests_signed: false,
logout_requests_signed: false,
logout_responses_signed: false,
metadata_signed: false,
digest_method: XMLSecurity::Document::SHA1,
signature_method: XMLSecurity::Document::RSA_SHA1
},
idp_cert: <<-CERT.chomp
-----BEGIN CERTIFICATE-----
MIIDQDCCAiigAwIBAgIEIZbEtDANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEOMAwGA1U
CBMFVGV4YXMxDzANBgNVBAcTBkF1c3RpbjESMBAGA1UEChMJU2FpbFBvaW50MR4wHAYDVQQDExVw
cmQwMi11c2Vhc3QxLWNhcmdpbGwwHhcNMTYwMTE5MDM0OTQwWhcNMjYwMTE2MDM0OTQwWjBiMQsw
CQYDVQQGEwJVUzEOMAwGA1UECBMFVGV4YXMxDzANBgNVBAcTBkF1c3RpbjESMBAGA1UEChMJU2Fp
bFBvaW50MR4wHAYDVQQDExVwcmQwMi11c2Vhc3QxLWNhcmdpbGwwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCRlr1CRIYLomUqTt9Igdrs9dwSW45lLS7lRDh+7WAgIbqIRxLjDH0fJgMi
T14i2gZD+bKyv43epVi6DG8pWrP2qjf8/U1VTr2hMnLrty5ycB9c8DSSh8YSARRIRjxUKrETp70i
BspeMtA3+ZMEnrrz38WlU5zuctzRSr6Q75Yf96tIk1wO+EqRASiNUy+oe/+/LClvPiJLnwdUEnNY
SXgidUvAGxgM639yD0C4cKs++zimwUBcTOgdvPbSJhpG1/CoQcrrdPt78a1RxC3MJJBVG9015SW1
ZkQ5u5sJjFWPzvqd9POgszzc/cj9SjLnh4Y6BFbxZOqkg5Ghn9b8vaElAgMBAAEwDQYJKoZIhvcN=
-----END CERTIFICATE-----
CERT
}
end
end
My config/routes.rb
devise_scope :user do
get 'users/sign_out', to: 'devise/sessions#destroy'
get 'users/submit_verification_code', to: 'aws_cognito#submit_verification_code'
get 'users/request_verification_code', to: 'aws_cognito#request_verification_code'
scope 'users', controller: 'saml_sessions' do
get :new, path: 'saml/sign_in', as: :new_user_saml_session
post :create, path: 'saml/auth', as: :user_saml_session
get :destroy, path: 'saml/sign_out', as: :destroy_user_saml_session
get :metadata, path: 'saml/metadata', as: :metadata_user_saml_session
match :idp_sign_out, path: 'saml/idp_sign_out', via: [:get, :post]
get :sso_dashboard
end
post '/saml/consume' => 'saml_sessions#create'
end
Issue fixed by providing correct issuer name in CidpSettingsAdapter.
I am creating an application with Rails and Angular. I am using ui.router. When I visit a route via a ui-sref link, it loads. However, if I refresh that page, I get the following error:
Missing template posts/show, application/show with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder]}.
The home page (root of the site) does not have this problem. Also, if I type in a url, say /posts/1, I will get the same message, but if I click a ui-sref link for that post, the page will load. (Though refreshing that page will break it.) Another behavior that might shed light on the misconfiguration is that I can click a ui-sref link to get to the route /login – this route is undefined on the rails side, but defined in my angular routes (app.js). However, when I try to reach /login by any other means, or if I refresh /login, I get the error: 'No route matches [GET] "/login"'
routes.rb
Rails.application.routes.draw do
devise_for :users, :skip => [:registrations]
root to: 'application#angular'
resources :posts, only: [:create, :index, :show, :update, :destroy] do
resources :comments, only: [:show, :create] do
member do
put '/upvote' => 'comments#upvote'
put '/downvote' => 'comments#downvote'
end
end
member do
put '/upvote' => 'posts#upvote'
put '/downvote' => 'posts#downvote'
end
end
resources :users, only: [:show], to: 'users#show', via: 'get', layout: false
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
respond_to :json, :html
before_action :configure_permitted_parameters, if: :devise_controller?
def angular
render 'layouts/application'
end
private
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
posts_controller.rb
class PostsController < ApplicationController
def show
respond_with Post.find(params[:id])
end
end
app.js
angular.module('appName', ['ui.router', 'templates', 'Devise', 'ui.bootstrap', 'angularMoment'])
.config([
'$stateProvider',
'$urlRouterProvider',
'$locationProvider',
function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$stateProvider
.state('home', {
url: '/',
templateUrl: 'home/_home.html',
controller: 'MainCtrl',
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
})
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts/_posts.html',
controller: 'PostsCtrl',
resolve: {
post: ['$stateParams', 'posts', function($stateParams, posts) {
return posts.get($stateParams.id);
}]
}
})
//more stuff here
.state('login', {
url: '/login',
templateUrl: 'auth/_login.html',
controller: 'AuthCtrl',
onEnter: ['$state', 'Auth', function($state, Auth) {
Auth.currentUser().then(function (){
$state.go('home');
})
}]
})
.state('register', {
url: '/register',
templateUrl: 'auth/_register.html',
controller: 'AuthCtrl',
onEnter: ['$state', 'Auth', function($state, Auth) {
Auth.currentUser().then(function (){
$state.go('home');
})
}]
});
$urlRouterProvider.otherwise('home')
}])
posts.rb (factory)
angular.module('appName')
.factory('posts', [
'$http',
function($http){
var o = {
posts: [],
};
o.get = function(id) {
return $http.get('/posts/' + id + '.json').then(function(res){
return res.data;
});
return o;
}])
My guess is that something needs to be changed in the configuration on the Angular side.
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