Devise+Omniauth, routes versioning - ruby-on-rails-4

I have a model Candidate which is devise omniauthable (linkedin).
So far, my routes.rb looked like this :
namespace :v1 do
devise_for :candidates, only: :omniauth_callbacks
...
end
Everything worked well till I had to add a new version :
namespace :v2 do
devise_for :candidates, only: :omniauth_callbacks
...
end
namespace :v1 do
devise_for :candidates, only: :omniauth_callbacks
...
end
With the current configuration, I get this error :
`set_omniauth_path_prefix!': Wrong OmniAuth configuration. If you are getting this exception, it means that either: (RuntimeError)
1) You are manually setting OmniAuth.config.path_prefix and it doesn't match the Devise one
2) You are setting :omniauthable in more than one model
3) You changed your Devise routes/OmniAuth setting and haven't restarted your server
It's kind of annoying since I want to be able to authenticate the candidate on both versions.
What can I do ?

Alright, let's recap a little bit here, Devise doesn't allow you to call the devise_for method inside a scope or a namespace route defined in the config/routes.rb file, right?
My namespace'd route looks like this:
namespace :api, constraints: { format: :json } do
devise_for :users, skip: [ :registrations, :passwords, :confirmations ]
resources :profiles, only: :show
end
And it works!
What did I do to make it work? the answer lies in the config/initializers/devise.rb file.
Check out near the bottom of the File it says...
# When using omniauth, Devise cannot automatically set Omniauth path,
# so you need to do it manually. For the users scope, it would be:
The next commented line shows you an example, uncomment that line and modify it according to your needs, for my case(ie. for the namespaced route I have above) I have:
config.omniauth_path_prefix = "/api/users/auth"
And that's it! .... I did that and it all started to work perfectly!
Hope it helps!

Related

generated path does not match custom route?

(Rails 4.2)
I have a miss-match of routes that's in the routes.rb file vs the generated from my page. What is it I am doing wrong?
This is the raked route I want to access :
see_hint_deck_card_tracker GET /decks/:deck_id/cards/:card_id/trackers/:id/see_hint(.:format) trackers#see_hint
I am actually taken to what I think is the correct url, but it tells me I don't have a route for this page:
http://localhost:3000/decks/9/cards/2/trackers/1/see_hint
I have the following routes:
resources :decks do
resources :cards do
resources :trackers do
member do
get 'see_hint'
end
end
end
end
app/controllers/tracker_controller.rb :
class TrackerController < ApplicationController
def show_hint
puts 'we found this'
end
end
inside my /decks/:id/cards/:id/show I have this link_to: (get_tracker, calls for a helper method to get the correct tracker)
<%= link_to "Reveal Hint", see_hint_deck_card_tracker_path(#card.deck, #card, get_tracker), id: "reveal_hint_button" %>
I think your error message is probably telling you you don't have a Controller for that route, not that the Route is missing. This is because you're using the plural resources in your routes.rb, but your controller name is singular:
# Your Code:
resources :trackers
controller TrackerController
# Expected Code:
resources :trackers
controller TrackersController
^^^
You'll also want to make sure your controller is available at app/controllers/trackers_controller.rb (note the plurality).

correct way to use routes.rb namespace rails?

I'm trying to create a back-end area to my application, so I've created a folder named backend and backend_controller.rb inside it. I need the folder because the backend area will have multiple folders, so it's better-separated from my others.
my routes.rb looks like:
namespace :backend do
get 'index'
end
my backend_controller.rb:
class BackendController < ApplicationController
def index
end
end
But in this mode Rails will search for my backend_controller.rb inside the controllers folder, not in controller>backend. I've tried many variations, and I get routing errors.
So what is correct way to do that? To set the path /backend to index action instead of /backend/index?
Thanks
What i've done:
based on all answers, principally the one from Cyril DD
I've created the backend_controller.rb on the app/controller folder and in the sub-folder app/controller/backend i created the static_pages_controller.rb and all files looks like this:
app/controllers/backend_controller.rb:
class BackendController < ApplicationController
end
app/controller/backend/static_pages_contter.rb:
class Backend::StaticPagesController < BackendController
def dashboard
end
end
routes.rb:
namespace :backend do
resource :static_pages, path: '', only: [] do
root to:'static_pages#dashboard'
end
this works fine, but cause i'm newbie on rails i must ask. This is a good or a conventional way to do that? to administrate the permissions which user can see on the backend i use the backend_controller.rb right? and at last wy i must use resource: instead just get ''
Answering your question
Alright, namespace :something is a shorthand for scope 'something', module: 'something', as: 'something'
Now your declaration is very ambiguous, because you don't specify a controller. Typical declarations look like (assume you have a controller controllers/backend/some_resources_controller.rb and you want to generate default routes)
namespace :backend do
resources :some_resources
end
Now what you did
namespace :backend
get 'index'
end
is really ambiguous and I'm not surprised it doesn't do what you want. Basically you just tell rails to "look inside subfolder 'backend' and define the route 'index'". oO ? Which file/controller are we even talking about ?
What is your backend_controller.rb supposed to do ? Is it some kind of Control Panel ? Dashboard ? If so you're probably gonna have a lot of non-CRUD actions, but anyways you should go for the following syntax
namespace :backend
# Below line of code will auto-generate the `index` for /backend/backend_controller
resource :backend, only: [:index], path: '' do # we need " path: '' " otherwise we'll have https://xxx/backend/backend/dashboard
# If you have non-CRUD actions, put them here !
get 'dashboard' # https://xxx/backend/dashboard
...
end
# However, this will create URLs like "https://xxx/backend/dashboard", etc.
# If you want to redirect https://xxx/backend/ to your backend_controller#index, use root
root to: 'backend#index' # https://xxx/backend/
end
Last thing as mentionned by other guys, when you namespace a file like your Backend_controller inside /backend/ subfolder, you must rename the class like (/controllers/backend/backend_controller)
class Backend::BackendController < ApplicationController
Remark : if you only have like one or two controller actions, instead of using the resource method, you can declare singular resources
namespace :backend do
root to: 'backend#dashboard'
get 'dashboard', to: 'backend#dashboard' # singular resource
end
An Example of what you may actually really want to do...
I'm not sure you are clear yourself about what you want to do. As an example, here is my architecture
Files
/controllers/application_controller.rb
/controllers/backend_controller.rb
/controllers/backend/static_pages_controller.rb
/controllers/backend/***.rb
The class /controllers/backend_controller.rb will not serve any action, but will override ApplicationController to tune it for backend access (but maybe you don't need to do so)
class BackendController < ApplicationController
# Do you need to change user_access method ? Or any other backend-wide config ?
# If so put this config here, otherwise leave empty
end
Now for every file that goes in the /backend/ subfolder, I inherit the backend_controller
class Backend::StaticPagesController < BackendController
def index
end
# Note : if your index is some kind of dashboard, instead I would declare
def dashboard
end
end
class Backend::SomeResourcesController < BackendController
...
end
Routes
namespace :backend do
root to 'static_pages#index' # https://xxxx/backend/
resource :static_pages, only: [:index], path: '' # https://xxxx/backend/index
resources :some_resources
end
If you choose the dashboard solution in your controller, write instead :
namespace :backend do
root to: static_pages#dashboard # https://xxxx/backend/
resource :static_pages, path: '', only: [] do
get 'dashboard' # https://xxxx/backend/dashboard
end
resources :some_resources
end
Then it's simply
# routes.rb
Rails.application.routes.draw do
namespace :backend, shallow: true do
resource :backend, path:''
end
end
Then in your app/controllers/backend/backend_controller.rb, it'd look like this.
class Backend::BackendController < ApplicationController
def index
end
end
When I use rake routes it shows
Prefix Verb URI Pattern Controller#Action
backend_backends GET /backend(.:format) backend/backends#index
Hope this helps.

Switching language (locale) in ActiveAdmin without passing a parameter

I want to be able to switch my locale in an ActiveAdmin app of mine.
So far I've followed this guide on switching-locale, which actually mentions the problem I'm having:
You will notice, however, that all links keep the default locale of your app.
So in my case, once I switch the locale, the urls stay
localhost:3000/en/admin/users instead of
localhost:3000/de/admin/users
The guide also proposes a solution:
You can override this default locale by passing the locale to all _path methods.
But this seems error-prone and quite a lot of work.
So looks like ActiveAdmin uses I18n.locale once to create all the urls and does not consider changes to I18n.locale after that.
Meaning if you this in your ApplicationController:
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
I've tried overriding
ActiveAdmin::Helpers::Routes.default_url_options
in my ApplicationController, which did not help.
Does anyone have an idea how I could resolve this issue?
Edit:
I also set these and tried different variations of the scope method.
Routes
scope '(/:locale)', locale: /en|de/, defaults: { locale: I18n.locale }
ActiveAdmin.routes(self)
end
ApplicationController
def default_url_options(options={})
{ locale: I18n.locale }.merge options
end
Ok so I've finally figured out what was going on.
I originally followed the rails guide and set my routes.rb:
# config/routes.rb
scope "/:locale" do
resources :books
end
which resulted in an error like:
No route matches {:action=>"index", :controller=>"admin/users"} missing required keys: [:locale]
this was "fixed" by setting
scope ':locale', defaults: { locale: I18n.locale } do
ActiveAdmin.routes(self)
end
as suggested in the current version of the Switching locale guide.
But this has the side-effect of all subsequent url_helpers using this locale for url generation. BTW at least one other person ran into this.
My current work-around can be found here:
lib/active_admin/helpers/routes/url_helpers.rb
def self.default_url_options
(Rails.application.config.action_mailer.default_url_options.merge({locale: ::I18n.locale})) || {}
end
Now urls are generated as expected.
First of all you need define :locale scope as optional, this can be done with this code:
scope '(:locale)' do
#your routes
end
After in ApplicationController put that code for enable default scoping:
def default_url_options(options={})
options.merge({locale: I18n.locale})
end

uninitialized constant Api::Doorkeeper

I have API engine inside my Rails app and I've mounted the engine under in the main app routes
Rails.application.routes.draw do
mount Api::Engine => "/api"
end
and I want to add the doorkeeper routes using use_doorkeeper function in my routes like this
Api::Engine.routes.draw do
use_doorkeeper :scope => "api/oauth"
end
this doesn't work because it tries to find controllers under api/doorkeeper/controller_name instead of doorkeeper/controller_name
as a workaround I've added doorkeeper routes in main app routes.rb with a scope like this
Rails.application.routes.draw do
mount Api::Engine => "/api"
use_doorkeeper :scope => "api/oauth"
end
But I want to know if there is a solution so I can still add the routes to api/config/routes.rb and make reference the correct controllers path
my colleague suggested this solution found here and it worked for me :)
MyEngine::Engine.routes.draw do
old_scope = #scope[:module]
#scope[:module] = nil
use_doorkeeper
#scope[:module] = old_scope
end

Rails 4 renaming route for "create" action

# routes.rb
resource: :users, only: :create, path_names: { create: 'register' }
Following the routing guide at guides.rubyonrails.org, this line is expected to replace /users with /users/register, but the path_names argument seems to have no effect whatsoever. What am I doing wrong?
EDIT:
Interesting that it only applies to new and edit. In any case, this is the work around I used
resource :users, only: :nothing do
post "register", to: :create
end
Done this way to make it slightly easier to enable more actions for users in the future
From rails guide:
The :path_names option lets you override the automatically-generated
"new" and "edit" segments in paths
It seems that you can't rename the create action.