Passing resource from controller to view in rails/devise - ruby-on-rails

Rails 4.2.6
Devise 4.1.1
I want to redirect to a specific page after user has successfully updated his data using devise. Here is the Controller:
protected
def after_update_path_for(resource)
#email = resource.email
after_update_path
end
Here is the view:
<h3><%= #email %></h3>
Nothing shows up, any sugeestion?

you need to pass the data as parameter to another controller. because you are doing redirect not render. but probably you don't need that because since the user still have the session, you can show the data of the current user via current_user method.
so
<h3><%= current_user.email %></h3>
should work for you

Related

How to pass information from one controller to another via view rails

I am working on a reservation project and after login I want to pass the current user information from the Sessions Controller to a Reservations Controller via a home page. How can I do that? I have been following Michael Hartl's Rails Tutorial for the login. Here's what I have tried in the create section of the Sessions Controller
render home_path :local_variables[:id => user_id]
and in the home_path(users#home)
<%= link_to new_reservation_path(:user_id => :id) %>
but it shows me an undefined method error. My Reservation model has a user_id column.I am confused regarding this matter. What should I do?
render home_path :local_variables[:id => user_id]
Seems weird to me to pass locals that way (don't even know if it's possible, never seen locals used outside of rendering views/partials).
I think the best way is to redirect instead and set the user in the sessions once they have been logged in successfully, so in your login action:
user = User.find_by_email(params[:user][:email]) # or however you are finding the person trying to login
session[:user] = user
redirect_to home_path
then in users#home
#user = session[:user]
and finally, in the view:
<%= link_to new_reservation_path(:user_id => #user.id) %>
EDIT
Actually, probably not a good idea to store an object in the session, instead of
session[:user] = user
You could try:
session[:user_id] = user.id
and then to find the user:
#user = User.find(session[:user_id])
If you still get an undefined error then it's probably because the user is nil (unless the User model actually has no id attribute, which would be strange) so there might be an issue with the login part, it's hard to say without knowing what that looks like.
If you need the logged in user on every page, you could abstract the functionality out into the application controller:
before_filter :check_user
def check_user
#user = User.find(session[:user_id]) if session[:user_id]
end
Then, you can use the #user instance variable anywhere in your app.

Why won't debug work in this situation?

I'm using the gem called omniauth-facebook, with which I succeeded at implementing facebook login auth.
It looks fine but it won't pass data of the whole object to the view. It just says nil.
It should show an array of things when using 'debug' or 'inspect'. It shows the content of session[:name] fine somehow.
Controller
class SessionsController < ApplicationController
def create
#auth = request.env["omniauth.auth"]
session[:oauth_token] = #auth.credentials.token
session[:username] = #auth.extra.raw_info.username
session[:name] = #auth.extra.raw_info.name
redirect_to bookd_url, :notice => "Signed in!"
end
end
View
<% if signed_in? %>
<%= #auth.inspect %>
<%= debug #auth %><br />
<%= session[:name] %>
<% end %>
Output HTML
nil
---
...
John
Your create controller action does a redirect. After the redirect, the process will start from scratch, and #auth will no longer be defined. If you render the view at this point, #auth will be nil. This is your problem.
You need to think about what you are trying to do here. You set an #auth variable from the authentication details in the initial request. You then use this to set some data in the session, which records who is logged in for example. Then, on the next page, where the user is logged in, you want to look at #auth. This doesn't really make sense: once you've authenticated a user, all you need to care about is remembering which user is currently logged in. You don't need to store details about HOW they logged in, and in fact you probably shouldn't.
You should instead be doing something like this:
#in ApplicationController, protected section
protected
def current_user
if #current_user
return #current_user
elsif session[:username]
#current_user = User.find_by_username(session[:username])
return #current_user
end
end
This will allow you to write current_user in your controller and view code, to access the user who authenticated, originally, which is the whole reason for logging someone in and keeping them logged in.

Rails devise set flash message from another action

I'm trying to show devise error message from another action. I have Registrations Controller with subscription action.
I would like to show error message from my subscription action when the user has already signed up. So this is kind a update of existing user, but without password, just validation for attributes.
If validation fails devise shows error message via subscription action.
By default when the user get updated error message is rendered via update action.
I assume I need to reuse the code from Registrations Controller update action and apply this code to my subscription action, but no luck. Can anyone help to make to show error message from subscription action?
here devise registrations controller
Ideally, you should create a separate controller SubscriptionController which contains new and create (RESTful actions?) which enable you to display a form where you accept the user details and process it, respectively.
Here, in the SubscriptionController's create action, you can append errors to the flash hash provided by the ActionController.
class SubscriptionController < ActionController
def create
flash[:success] = 'User Registered Successfully'
end
end
In your view(layout), you can have something like this:
<% flash.each do |name, msg| %>
<div class="flash">
<%= msg %>
</div>
<% end %>
which will allow you to display the flash message.

Trying to get "current user" in Rails

In the /views/layouts directory, how do I get the current user? I am using Devise, but current_user does not work here for some reason, it describes it as an unknown method. I want to do something like:
<% if User.role? == "gen_admin" %>
<li>
<%= link_to('Admin', users ) %>
</li>
<% end %>
I do have a role? method defined in my User model, but I still get this exception:
undefined method 'role?' for #<Class:0x3fcc1e0>
So how can I get the current user, and access its fields at this level of the source tree? Thanks!
Here is the roles? method:
# in User
ROLES = %w[gen_admin teacher_admin student]
def role?(base_role)
ROLES.index(base_role.to_s) <= ROLES.index(role)
end
Your code must account for when users are logged in, and when they are not logged in.
If no user is logged in, then current_user will return nil (as in your case, which you thought was an error on Devise's part).
Your view code must handle this - eg.
<% if current_user.present? && current_user.role?('gen_admin') %>
You have defined your role? method as an instance method. This means that in order to use it you should first create the instance from User class e.g.:
#user=User.new
Now you can call #user.role?
If you want role? to be available through the model User then you should define it as class method an pass in an object for verification
def self.role?(user)
...
end
You'll need to change the code in your view to use current_user rather than User, as well as call the role? method correctly (no ==). If this is used in a view that can be accessed by a non-logged in user, you'll want to confirm that the user is logged in first (so you don't try and call role? on nil, which would raise an exception):
<% if current_user && current_user.role?("gen_admin") %>
<li>
<%= link_to('Admin', users ) %>
</li>
<% end %>
Do you forget to add before_filter :authenticate_user! in your controller? This will ensure that current_user is available in your views

Redirecting to different actions without using a query string

I am trying to figure out the best way to do the following (there are a few ways I can think of, but I want to know what the best way to handle it is):
A user is putting together a shipment, and then clicks the "Send" link, which sends him to the /shipments/:id/confirm page. The confirm action checks to see if the user has a completed ShippingAddress; if not, it sends him to the ShippingAddress#new. (If he does, it render the confirm page.
I want the user to be able to complete the ShippingAddress#new page, submit it, and then be redirect back to the /shipments/:id/confirm. How can I do that? How can I pass the :id to the ShippingAddress#new page without doing something like redirect_to new_shipping_address_path(shipment_id: #shipment.id) in the Shipment#confirm action? Or is that the best way to do that?
class ShipmentsController < ApplicationController
def confirm
#shipment = Shipment.where(id: params[:id]).first
unless current_user.has_a_shipping_address?
# Trying to avoid having a query string, but right now would do the below:
# in reality, there's a bit more logic in my controller, handling the cases
# where i should redirect to the CardProfiles instead, or where I don't pass the
# shipment_id, and instead use the default shipment.
redirect_to new_shipping_address_path(shipment_id: #shipment.id)
end
end
end
class ShippingAddressesController < ApplicationController
def new
#shipment = Shipment.where(id: params[:shipment_id]).first
end
def create
#shipment = Shipment.where(id: params[:shipment_id]).first
redirect_to confirm_shipment_path(#shipment)
end
end
[In reality, there is also a CardProfiles#new page that needs to be filled out after the shipping address is].
Try calling render instead of redirect_to, and set the id into an instance variable. Adjust the view logic to pull that instance variable if it exists.
#shipment_id = #shipment.id
render new_shipping_address_path
In the view
<%= form_for #shipment_address do |f| %>
<% if #shipment_id %>
<%= hidden_field_tag :shipment_id, #shipment_id %>
<% end %>
I don't know your view logic entirely, but giving an example.

Resources