How do I work with Rails 3 cookies and helpers? - ruby

I created a user and stored the id in a permanent cookie:
def save_user_id_cookie
cookies.permanent.signed[:user_id] = #user_id
end
Here is a link.
and then try to access it:
helper_method :current_user
private
def current_user
#current_user = #current_user || User.find(cookies.signed[:user_id])
end
Here is a link.
I see the cookie on my machine but when I try to load the homepage I get:
Couldn't find User without an ID
app/controllers/application_controller.rb:8:in `current_user'
The controller is here.

Believe this line
#current_user = #current_user || User.find(cookies.signed[:user_id])
should be
#current_user = #current_user || User.find(cookies[:user_id])
*side note: for little less code you can try assigning like
#current_user ||= User.find(cookies[:user_id])

In your save_user_id_cookie:
def save_user_id_cookie
cookies.permanent.signed[:user_id] = #user_id # may be #user.id?
puts 'saved cookie'
end
#user_id is nil. I think you should use #user.id instead.

Try this:
#current_user = #current_user || User.find(*cookies.signed[:user_id])
Notice the * before the cookies.
and yes, as #nash pointed out, that user_id should be actually user.id.
I didn't bother to look there for errors, as you said that you could see the cookie on your machine.

Related

how to write strong parameters in rails

How can i Implement the below create action using strong parameters
def create
##user = User.find(params[:user_id])
#listing = Listing.find(params[:listing_id])
if current_user != #listing.user
#reservation=Reservation.new(user_id:current_user.id,listing_id:params[:reservation][:listing_id],price:params[:reservation][:price],
total:params[:reservation][:total],start_date:params[:reservation][:sdate],end_date:params[:reservation][:edate],
driver_name:params[:reservation][:driver_name],no_of_passengers:params[:reservation][:no_of_passengers],days:params[:reservation][:days],reservation_status:false,reservation_state: 'PENDING')
else
#reservation=Reservation.new(user_id:current_user.id,listing_id:params[:reservation][:listing_id],price:params[:reservation][:price],
total:params[:reservation][:total],start_date:params[:reservation][:sdate],end_date:params[:reservation][:edate],
driver_name:params[:reservation][:driver_name],no_of_passengers:params[:reservation][:no_of_passengers],days:params[:reservation][:days],reservation_status:false,reservation_state: 'BLOCKED')
end
#reservation.save
end
I have all the attributes coming from _form.html.erb accept user_id ,reservation_status and reservation_state.I can permit some attributes as:
def reservation_params
params.require(:reservation).permit(:start_date, :end_date, :price, :listing_id,:total,:driver_name,:no_of_passengers,:days)
How can I permit all the attributes including user_id, reservation_status and reservation_state for a user to complete the reservation.
Thanks in advance!
I would start with something like this:
def reservation_params
parameters = params.require(:reservation).permit(
:listing_id, :sdate, :edate, :driver_name, :no_of_passengers, :days
)
parameters.merge!(user_id: current_user.id, reservation_status: false)
if current_user != listing.user
parameters.merge!(reservation_state: 'PENDING')
else
parameters.merge!(reservation_state: 'BLOCKED')
end
end
def listing
#listing ||= Listing.find(params[:listing_id])
end

Why can't I find an ActiveRecord instance by its auth token?

def current_user
#current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
end
I've even tried this:
begin
#current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
rescue ActiveRecord::RecordNotFound => e
#current_user ||= nil
end
But it is only returning the nil value.
Please help.
Controller:
if params[:remember_me]
cookies.permanent[:auth_token] = user.auth_token
else
cookies[:auth_token] = user.auth_token
end
EDIT:
Model:
before_create :generate_token(:auth_token)
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
I think I am having a problem with before_create. Is the way it is written correct?
This has worked for me, for those times when the browser's cookies and those saved to a user model are mis-aligned:
def current_user
#current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
rescue ActiveRecord::RecordNotFound => e
#current_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id]) # Use find_by_id to get nil instead of an error if user doesn't exist
end
helper_method :current_user
For me the issue would arise when deleting a user that was currently signed in. The above code stops any errors.
It seems that you canno't find that instance, because the cookie doesn't exist anymore in your web browser, there is a conflict. You should therefore clear your browser's datacache, and the problem will disapear.

Session data not being saved in Sinatra simple authentication

I created a simple authentication for Sinatra, however the session object seems to be cleaning up ALL custom keys. For example, when user logs in:
session[:user_id] = current_user.id
This is effectively stored in the session object for the current request. When a new request occurs the session[:user_id] is not there anymore. Session is active, cookies are enabled. I tried everything I can't figure out what it wrong (here is the all the relevant code: https://gist.github.com/ksiomelo/7656296).
application:
use Rack::Session::Cookie , :secret => "82e042cd6fde2bf1764f777236db799e"
enable :sessions # for flash messages
helpers:
def require_auth
unless session[:user_id]
flash[:error] = "You need to be logged in."
redirect to("/login")
end
end
def current_user
#current_user ||= User.find_by_id(session[:user_id]) if session[:user_id]
end
signin:
authorized_user = User.authenticate(params[:email],params[:password])
if authorized_user
# update session / redirect
session[:user_id] = authorized_user.mongo_id.to_s
session.options[:expire_after] = 2592000 unless params[:remember].nil? # 30 days
# redirect to the wizard
flash[:info] = "Welcome back #{authorized_user.first_name}"
redirect to("/home")
You should likely try to set a provider for session handling, e. g.:
use Rack::Session::Pool, :expire_after => 2592000
Glad to help.

Access OmniAuth helper in Sinatra view

I'm new to this, so forgive me if I'm being stupid!
I'm using OmniAuth for Sinatra to help authenticate users. In my layout.erb, I'd like to access the current_user helper to check if the user is logged in. The helper goes like this:
def current_user
#current_user ||= User.get(session[:user_id]) if session[:user_id]
end
But I'm not sure how to access it in my layout view. I thought this would do the trick:
<% if current_user %> Do stuff here <% end %>
But no luck. Any help would be appreciated! Like I said, I'm new to Ruby, and I'm not a strong developer.
You need to define that method inside helpers block, like this:
helpers do
def current_user
#current_user ||= User.get(session[:user_id]) if session[:user_id]
end
end
Then it will be available to the view.

Testing #current_user method using RSpec

I've been trying to do this for a couple of days now, but I can't figure it out. I have the following code in my controller:
#some_object = #current_user.some_method
In my spec, I want to attach a should_receive hook on that method, but I can't make it work. I've tried all of these, but none of them work:
assigns[:current_user].should_receive(:some_method).at_least(:once) # expected 1, got 0
User.should_receive(:some_method).at_least(:once) # expected 1, got 0
How is the correct way of testing this? I'm running this in my spec, and login is working:
setup :activate_authlogic
...
UserSession.create(users(:rune))
Thanks!
One example comes from the Ruby on Rails Tutorial. Rather than setting and reading #current_user directly, it defines two helper methods:
def current_user=(user)
#current_user = user
end
def current_user
#current_user
end
Later, they access this method in the tests using the controller method:
def test_sign_in(user)
controller.current_user = user
end
Using this methodology, you should be able to use
controller.current_user.should_receive(:some_method).at_least(:once)
You can’t call something like in the controllers:
expect(current_user).to be_present
expect(user_signed_in?).to be_true
So to do so, you can do this :
module ControllerMacros
def current_user
user_session_info = response.request.env['rack.session']['warden.user.user.key']
if user_session_info
user_id = user_session_info[0][0]
User.find(user_id)
else
nil
end
end
def user_signed_in?
!!current_user
end
end
You can either include the ControllerMacros in the top of the controller spec or include it in the spec_helper.rb like so :
RSpec.configure do |config|
config.include ControllerMacros, type: :controller
end

Resources