Ruby on Rails - Heroku problems & User sign-in - ruby-on-rails

First post here on SO. I am relatively new to Ruby on Rails and I have been reading through Michael Hartl's book, "Ruby on Rails Tutorial - Learn by Example". However, I have the following problems when running my application that I would be gracious to get solved.
1) When trying to run my application in 'production' mode, I have updated the file 'config/environments.rb' as follows:
# force Rails into production mode when
# you don't control web/app server and can't set it the proper way
ENV['RAILS_ENV'] ||= 'production'
However, when I run the application, I can still see the debugger facility present from the file 'app/views/layouts/application.html.erb'
<!-- Debug applies only to 'development' environment -->
<%= debug(params) if Rails.env.development? -%>
<!-- as determined by "if Rails.env.development?" -->
This leads me to believe that I am still running the application in development mode.
2) For those that have already asked questions about the signin_path problem, I still cannot see a solution that fixes it for me. I am able to sign up users, then automatically redirect them to their profile space. However, the navigation menu does not change accordingly:
<nav class="round">
<ul>
<li><%= link_to "Home", root_path -%></li>
<li><%= link_to "Support", support_path -%></li>
<% if signed_in? %>
<li><%= link_to "Users", users_path -%></li>
<li><%= link_to "Profile", current_user -%></li>
<li><%= link_to "Settings", edit_user_path(current_user) -%></li>
<li><%= link_to "Sign out", signout_path, :method => :delete -%></li>
<% else %>
<li><%= link_to "Sign in", signin_path -%></li>
<% end %>
Here is the code from the 'app/helpers/sessions_helper.rb' file:
def current_user # GET current_user
#current_user ||= user_from_remember_token
end
def signed_in?
!self.current_user.nil?
end
.
.
.
private
def user_from_remember_token
User.authenticate_with_salt(*remember_token)
end
def remember_token
cookies.signed[:remember_token] || [nil, nil]
end
Any help with this is most welcome. I am currently trying to host my application Heroku, but not getting the support I need unfortunately.
Cheers.

check the link if the question is related to heroku server . And if you want to run on local , rails s -p3001 -e production may work

It seems like your signed_in? helper returns not what you want. So at first debug what signed_in? returns like this:
<%= signed_in? %>
or you can raise error with signed_in? as a message.
Also it seems like you forget current_user setter method, which should be called after session is created. You need to have three methods like these:
def current_user
#current_user ||= User.find_by_id(session[:user_id])
end
def user_signed_in?
!!current_user
end
def current_user=(user)
#current_user = user
session[:user_id] = if #current_user ? current_user.id : nil
end
I recommend you to move this methods to ApplicationController as protected methods.
And one last advice:
!self.current_user.nil?
looks really bad. Try to avoid using bang!, this should work for you:
self.current_user

Related

How to use boolean conditions

So I'm obviously confused with boolean flow because I run into a problem each time. NOTE: I am teaching myself to program, you are all my only hope in learning! I am trying to define a method that checks if a user is an admin, so that I can display certain objects in views to ONLY admins simple enough...or not, for some reason it's not recognizing that I'm an admin (when I truly am, I've checked!). With this all being said, I am a newb so go easy on me!
helpers/sessions_helper is used by both my User and Blogpost models:
def current_user #determines if user is logged out or is the current user of the session/cookie of profile
if (user_id = session[:user_id])
#current_user ||= User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(cookies[:remember_token])
log_in user
#current_user = user
end
end
end
def current_user?(user)
user == current_user
end
def is_an_admin
if current_user && current_user.admin?
end
end
<div class="col-xs-12">
<h1><%= #blogpost.title %></h1>
<p><%= #blogpost.content %></p>
<% if is_an_admin %>
<%= link_to "Return to blog", blogposts_path %>
<%= link_to "Edit Post", edit_blogpost_path, class: 'btn btn-primary' %> |
<%= link_to "Delete Post", blogpost_path(#blogpost),
method: :delete, data: {confirm: "Are you sure?"}, class: 'btn btn-danger' %>
<% else %>
<%= link_to "Return to blog", blogposts_path %>
<% end %>
</div>
I'm unsure if maybe I have the method in the wrong place? I have tried placing it inside my applications controller and my user controller to no avail. I must be missing something.
Your sintax got messed up, but I think you're always returning nil on the is_an_admin method:
def is_an_admin
if current_user && current_user.admin?
end
end
It does nothing if the condition is true so it's always returning nil
Change it to something like:
def is_an_admin?
current_user and current_user.admin? # or shorter: current_user.try('admin?')
end

Showing edit button to current_user only (Rails 4)

I'm trying to allow users to show the edit button only if the profile belongs to them. Currently, they're only allowed to edit the profile if it belongs to them but I can't seem to hide the button. I have this so far
<% if request.original_url == request.base_url + "current_user.id" %>
<%= link_to "Edit Profile", edit_user_path(current_user), class: "btn btn-primary btn-xs" %>
<% end %>
This is what I'm trying to compare:
request.original_url => localhost:3000/users/random_user
request.base_url + "users/" + current_user.id => localhost:3000/users/current_user
Thanks in advance.
Authorization
To give you some perspective, you'll be looking for something called authorization.
This is different from authentication because it deals with permissions, rather than identifying your identity. I'll get into how this works in a minute.
To solve your problem, here's what you need to do:
<%= link_to "Edit Profile", edit_user_path(current_user), class: "btn btn-primary btn-xs", if user_signed_in? && current_user == #user %>
I'm guessing you're showing this on a user#show action, which can be invoked using the following code:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find params[:id]
end
end
This means that if you have the following routes:
#config/routes.rb
resources :users
you'll have access to #user and current_user. It's important to note that current_user != #user. Although weezing's answer is succinct, it does not validate whether the user is the one which owns the page authorized; just that the user is authenticated
Thus, you have several specifications:
You need to know if the user is actually logged in
You need to make sure your logged-in user has the authorization to edit the profile (IE is it theirs)
I would highly recommend looking into the use of gems such as CanCanCan or Pundit. I'll show you CanCanCan:
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
can :edit, Article, id: user.id
end
end
#app/views/users/show.html.erb
<%= link_to "Edit", edit_user_path(#user) if can? :edit, #user %>
There is a great resource here.
This should work (little bit simpler):
<% if current_user %>
<%= link_to "Edit Profile", edit_user_path(current_user), class: "btn btn-primary btn-xs" %>
<% end %>

Devise's current_user doesn't work?

I rather clumsily replaced my own auth system (based on Michael Hartl's tutorial) with the Devise gem today.
I've got most things working again but have a lot of errors relating to use of current_user.
This, for instance, doesn't work any more:
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
I previously had current_user defined in a sessions helper as follows:
module SessionsHelper
def sign_in(user)
remember_token = User.new_remember_token
cookies.permanent[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
self.current_user = user
end
end
def current_user=(user)
#current_user = user
end
def current_user
remember_token = User.encrypt(cookies[:remember_token])
#current_user ||= User.find_by(remember_token: remember_token)
end
def current_user?(user)
user == current_user
end
I've done away with that, thinking that devise provided the same functionality but that doesn't seem to be the case. In almost all of the situations where I was previously using current_user I now get undefined methodcurrent_user?'`. I'm hoping there is something global I can do to make the old usages work?
Any pointers much appreciated. I've had by far my worst day of rails in the six months I've been using it.
EDIT: The comments explain that I no longer have current_user? defined. I've tried adding the following to my users_controller but it doesn't seem to have worked:
def current_user?(user)
user == current_user
end
You deleted your current_user?(user) method with sessions_helper. Now Devise do all the necessary for you, but Devise has only current_user method, no current_user?(user).
You can define it by yourself in any helper, methods from all of them works in any view and any controller.
In fact, if you have many conditions, where you need to check if user is admin, and user isn't a current_user. You can make a separate helper for it. But, as I remember from Michael Hartl's tutorial, there is not many such blocks (:
Something like:
def not_admin?(user)
current_user.admin? && !current_user?(user)
end
So, you can refactor you view:
<% if not_admin?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
Also you can make it more clear with:
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } if not_admin?(user) %>

How to I get the destroy action to work with administrative control in Rails?

I am going through Michael Hartl's book, "Ruby on Rails Tutorial Learn Web Development with Rails". In the section where he explains how to get administrative access to delete users, I can't seem to get this to work. The delete link won't show up on the web app, and I am mystified as to why this is occurring. This is my unfactored code below, which sits in the directory of: app/views/users/index.html.erb
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= will_paginate %>
<ul class="users">
<% #users.each do |user| %>
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "Are you sure?" } %>
<% end %>
</li>
<% end %>
</ul>
<%= will_paginate %>
The methods of current_user.admin? && !current_user?(user) are methods located in: app/helpers/sessions_helper.rb
def current_user
remember_token = User.encrypt(cookies[:remember_token])
#current_user ||= User.find_by(remember_token: remember_token)
end
def current_user?(user)
user = current_user
end
I've been stuck on this problem for quite a while and have tried many different things to solve the problem, and none of them have worked. I'm running Rails on Windows 7 using the Rubymine IDE. The tutorial was done on a Mac OS X operating system, and I'm thinking maybe the problem might be associated with my setup.
Also are there known issues with tests failing using the Windows cmd when running RSpec versus running it on Mac OS X?
Any help would be much appreciated.
Thank you.
I just figured out what was wrong!
This method was written incorrectly
def current_user?(user)
user = current_user
end
The correct method to get the corresponding code above to work is this:
def current_user?(user)
user == current_user
end
Thank you for all your input!
Make sure in your controller you're calling the destroy action in your controller. Your code looks fine thus far and I'm assuming you're not using cancan for authorization.
In view file
<% if current_user.admin? && !current_user?(user) %>
<%= link_to "delete", user, method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
Controller
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_path }
format.json { head :no_content }
end
end

I have two user models using Omniauth

I have two user models one is
1. User.rb (this is my own authentication system which handles users that just sign up within my site.
Authenticate.rb (this is the OmniAuth authentication for users that want to signup through facebook.
Im having a hard time handling both models.....for example here is the code for my navigation
- if fb_signed_in?
.nav.pull-right.padding-top
%li
- if fb_signed_in?
%li#fat-menu.dropdown
%a.dropdown-toggle{"data-toggle" => "dropdown", :href => "#"}
%span
Signed in as
= fb_current_user.email
%ul.dropdown-menu
%li= link_to "Profile", "#"
%li.divider
%li= link_to "Sign out", leave_path, method: "get"
- else
.nav.pull-right
%span.light_color Already a Member?
= link_to "Sign in", signin_path, class: 'light_color'
%span.light_color or
= link_to "Sign up", signup_path, class: 'light_color'
- else
.nav.pull-right.padding-top
%li
- if signed_in?
%li#fat-menu.dropdown
%a.dropdown-toggle{"data-toggle" => "dropdown", :href => "#"}
%span
Signed in as
= current_user.email
%ul.dropdown-menu
%li= link_to "Profile", "#"
%li.divider
%li= link_to "Sign out", signout_path, method: "get"
- else
.nav.pull-right
%span.light_color Already a Member?
= link_to "Sign in", signin_path, class: 'light_color'
%span.light_color or
= link_to "Sign up", signup_path, class: 'light_color'
So i have defined a fb_signed_in? adn a signed_in? which basically does the same thing though..also with current_user and fb_current_user but heres the code for both
current_user
def current_user
#current_user = #current_user ||
User.find_by_remember_token(cookies[:remember_token])
end
and this is for fb_current_user
def fb_current_user
#fb_current_user ||= Authenticate.find(session[:user_id]) if session[:user_id]
end
so they do do different things....but is there a way to make those two one...since it will be a lot cleaner and im trying to create a comment system that will print users name and gravatar image and im getting confused on how to write the code for that since it uses gravatar_for #user and i would also have to do gravatar_for #authenticate for fb users.
Im basically using Hartl's authentication and trying to integrate Omniauth with it
Please let me know if the question is confusing or unclear and i will try to explain better
Thank You
How about:
def current_user
if session[:user_id]
#current_user ||= Authenticate.find(session[:user_id])
else
#current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
end
def signed_in?
current_user.is_a?(User) || current_user.is_a?(Authenticate)
end
Although this may cause problems in other places since you don't know what a current_user is without testing its type.
In my projects I have just one User model which has many Authorizations, where I put the omniauth-related stuff (so current_user is always a User).

Resources