Devise: How do I call `new_confirmation_path()` from a view? - ruby-on-rails

I see this new_confirmation_path(resource_name) called in generated Devise views.
I want to call this a custom view. The user isn't logged in.
new_confirmation_path(resource_name) is the way to generate a link to new confirmations page.
What is a resource_name?
How do I get it?
Is it possible to get it, in another (non-Devise) view?
Thanks.

resource_name in Devise is typically the name of the resource that you passed to devise_for in your config/routes.rb. So if you use devise_for(:users) it will be :user.
class DeviseController < Devise.parent_controller.constantize
def resource_name
devise_mapping.name
end
end
Devise uses the same views / controllers for many different models and does so through this mapping created in the routes which is injected into request.env.
If you know the model name you can also just use the named route helpers created for your app which would typically be new_user_confirmation_path.

Related

Nested resource from own controllers method - or create completely new controller?

Issue: When a user (when signed in) creates an order, they are sent to the OrderControllers show page which can only be accessed if signed in by both the buyer and seller. From here they can edit/update their order, etc.
We also have guest_user, someone who isn't signed in, and for them I need a order confirmation in the browser (I'm using Devise gem)
I have created a method:
def order_confirmation
In the OrdersController.
Although, how can I nest this within orders so the page knows which order to show.
Is this possible to nest methods under its' own controllers, or should i just create a small controller only for order confirmations?
For example: example.com/orders/1/order-confirmation
Maybe there are better ways to go about this other than just nesting and creating a controller?
I Tried:
resources :orders do
collection do
get 'order_confirmation'
end
end
With:
def order_confirmation
#order = Order.all.find(params[:id])
end
But it won't work how i want i t seems.
The rake routes gives me:
order_confirmation_orders GET /orders/order_confirmation(.:format)
How can i get?:
order_order_confirmation_orders GET /orders/id/order_confirmation(.:format)
I was able to figure this out from the help of this SO post:
Rails: Custom nested controller actions
By using:
resources :orders do
get 'order_confirmation', :on => :member
end
This creates:
order_confirmation_order GET /orders/:id/order_confirmation(.:format) orders#order_confirmation

Adding custom callback to user model with devise

I'm trying to add this callback to my User model, which I generated using Devise.
before_save :check_invite_code
def check_invite_code
if self.invite_code == 'first20'
User.save
else
{icon: 'error', message: "Sorry that's not a valid invite code"}
end
end
The issue I am having is with passing the returned hash with the else block back to my view. Typically I'd be able to use the icon and message in the flash in my controller. I'm not sure how to do that. I don't have a UsersController because devise takes care of a the routing with the path being devise/controller#action. So do I create a devise directory inside of controllers, then create the corresponding controllers like sessions, etc and override the devise methods? Looking for some guidance from someone with devise experience.
If you want to customize the UserController you can easily do that by
rails generate devise:controllers [scope]
For example
rails generate devise:controllers users
Check out the documentation here

Where can I find devise controller?

I'm trying to apply this post ( Devise update user without password ) for users don't need to insert password to update informations.
But, I'm very confused where is this controller. Devise don't create any controller in my app/controller folder. I search in all the folders but I cant find.
Where I that controller?
I see posts talking about create a new controller, but I just want to modify little things.
You don't edit (or shouldn't) the Devise controllers. Instead you create your own controller and inherent from the Devise controller.
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def update
# add custom update logic here
end
end
Notice how RegistrationsController inherets from Devise::RegistrationsController. Now you can overide the registration methods (or modify them and call super). Even the page you are referencing about overriding the devise default behavior relies on class inheritance.
JTG offers good advice, you shouldn't edit the gem directly. As a more direct answer to the question:
To print the folder of your gem:
$ bundle show devise
To open the gem in a text editor ( while being sure not to change anything )
$ bundle open devise

Alias route's name

I need to have one path accessible through multiple names. In my routes.rb I did
get '/route' => 'controller#edit', :as => 'name_a'
get '/route' => 'controller#edit', :as => 'name_b'
This works nicely but loads the routes table for nothing. From my understanding of the documentation, :as defines a helper method when called.
So I went to my ApplicationController and added
alias_method :name_b, :name_a
and I removed the second line from routes.rb
but that fails with Uncaught exception: undefined method name_a for class ApplicationController
is there any proper way of having two names for a single path?
=================EDIT====================
Elaboration:
I use Devise gem to manage session, registration, locking, etc. of 2 kinds of users, let's call them Admin and Guest. The gem is very well put but it asks for definitive route names to behave properly.
In my case, as far as devise is concerned, only the registration process is different so I'm trying to build a structure which looks as follow:
app
controllers
users
admin
registration_controller.rb
guest
registration_controller.rb
session_controller.rb
password_controller.rb
registration_controller.rb
the Admin and Guest controllers inherit from the above registration_controller which inherit's from Devise.
Now, to work properly, Devise needs for instance the names guest_user_password and admin_user_password to create or delete password retrievals. In my case, both are under the same path so I want both names to redirect to the same 'users/password' controller.
More important, and that's why I really wanted the alaising. Is that my views should not care whether it is dealing with Admin and Guest routes when redirecting to password retrieval controller. Both are users so I want to use user_password for both.
Hence my question. :)
Also note that as I wrote it, things works. I'm just trying to get the 'most elegant way' of writing it.
How about putting the alias in your ApplicationController?
class ApplicationController < ActionController::Base
alias_method :route_new, :route_old
helper_method :route_new
Remember that it's new name first, then old name.
The helper_method call is in order to use these in your views and not just controllers.
If you like, you can then place this in an included module called something like RouteAliases
You can add something like this to your routes.rb:
Rails.application.routes.draw do
...
Rails.application.routes.named_routes.tap do |named_routes|
named_routes['new_name'] = named_routes['real_name']
end
end
This will create new_name_path and new_name_url helpers. I have tested this with Rails 5.0.6.

Rails Beginner - which controller to put functions in?

New to rails and I have what I think is a basic question.
In an admin view, there will be varying operations done on different data models. I have a layout "admin" which has various tabs the user clicks to load forms to edit various sets of data.
Should the controller for everything that can be edited in this view be in admin_controller (ie, have an edit_product, edit_user...), or is it better to leave the functions in the controller for each model (say users_controller, products_controller, orders_controller) and specify in the controllers to use the admin layout?
I'm working through my first rails project, and it seems either way works, but obviously I want to follow the right convention going forward so any hint, or a link to an article about this topic would be appreciated.
Thanks,
The proper Rails way to do this would be to use Namespaces. I'll give an example below:
Inside your controllers folder, you add a new folder called admin, and for each model you want to edit as an admin, add a controller. Here is a basic blog application:
app/
models/
views/
controllers/
users_controller.rb
posts_controller.rb
comments_controller.rb
admin/
users_controller.rb
posts_controller.rb
comments_controller.rb
Notice the new folder layer within our controller folder. Inside each of these files, you'll change the definition of the class, from:
class UsersController < ApplicationController
to:
class Admin::UsersController < ApplicationController
Now, within your congif/routes.rb file, you can namespace your routes to the admin namespace, like so:
map.namespace :admin do |admin|
admin.resources :users
admin.resources :posts
admin.resources :comments
end
Now, you can go to a URL such as: http://localhost:3000/admin/users/1 and you'll have access to whatever you specified in the admin version of your users controller.
You can read more in this StackOverflow question, and read up on the Routes here.
Good answer from Mike. I would add that you can see the "standard" rails code for this by using a generator:
# in rails 2.3
$ script/generate controller admin/users
# in rails 3.0
$ rails generate controller admin/users
The slash in the controller name defines a namespace. Also see rake routes for the named paths that it creates, e.g. admin_users_path etc.

Resources