Finish an especific user's session - ruby-on-rails

At this time I want to put a button in the user's list "Disconnect" to finish the session when I need it
I'm using sorcery authentication
I added a new route in "routes.rb"
get "killsession" => "users#killsession", :as => "killsession"
I also Have a method in the "users_controller.rb"
def killsession
session[:user_id] = nil
redirect_to root_url
end
And in the view in the file "index.html.erb" I have it
<% #users.each do |user| %>
<tr>
<td><%= image_tag "#{user.definir_status_icono}" %></td>
<td><%= user.id %></td>
<td><%= user.username.capitalize %></td>
<td><%= user.name %></td>
<td><%= user.last_login_at.strftime("%l:%M %p, %B %d, %Y") rescue nil %></td>
<td>
<%= user.last_logout_at.strftime("%l:%M %p, %B %d, %Y") rescue nil %>
</td>
<td>
<%= link_to "Ver Mas", edit_user_path(user),
:class => 'btn btn-mini btn-primary' %>
<%= link_to 'Eliminar', user_path(user),
:confirm => "Esta seguro ?",
:method => :delete,
:remote => true,
:class => 'btn btn-mini btn-danger' %>
<% if user.online == 1 %>
<%= link_to "Disconnect", killsession_path(user),
:class => 'btn btn-mini btn-warning' %>
<% else %>
<%= link_to "Disconnect", '',
:class => 'btn btn-mini btn-warning',
:disabled => true %>
<% end %>
</td>
</tr>
<% end %>
I don't know how to do that button because when I clicked the button just finish the current session, and doesn't finish the especific user's session
Thanks for your help

The session hash is local to, well, your session. Read about it here. So when you modify it, it affects no one else. This approach won't work.
Generally, you don't have direct access to other users' session data. If you use cookie store (default!), it is stored locally in their browser. If you used for example ActiveRecordStore, you could possibly tamper with database table directly. But I would strongly discourage it - for security reasons as well as possibility to change session store easily.
So now, you want to sign out another user - any authentication library should allow it. If you use devise, it's as simple as sign_out user. If you wrote your own authentication module, you should know how to destroy a session (maybe resetting user's session token in users table?)

Why not just follow this ASCIIcast and log the user out? This seems simpler than actually trying to destroy a user's session manually.

Maybe because your routes are wrong ? Destroy a session is a DELETE not a GET and you set a params in your index.html.erb using killsession_path(user)
# The :as is useless
delete "/killsession/:id_of_selected_user" => "users#killsession"
and your button have to be like that :
<%= button_to 'Logout', killsession_path(:id_of_selected_user => user.id), :method => :delete %>

Related

how to stop cache from interfering with application logic

I'm trying to use Rails 4 cache digests in my app, but am finding that it interferes with a lot of application logic. For example, in this code, the links that are supposed to only be revealed where the current_user's id matches #user.id aren't working properly when I have the cache surrounding the code. Those links are visible to anyone who views the page.
<% cache #languages do %>
<% for language in #languages%>
<tr>
<td><%= language.name %> </td>
<% if current_user && current_user.id == #user.id %>
<td><%= link_to "edit", {:controller => 'lawyer_profiles', :action =>'show', :language_id =>"#{language.id}"}, {:class => "editarea #{language.id}"}%></td>
<td><%= link_to "destroy", language, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
<% end %>
In this code, the cache was interfering with the #question instance variable. For example, due to the presence of the cache, when I clicked on the link to "Add An Answer," it had my answering a different #question than the one I should have been answering, because the cache kept a memory of the instance variable on a page that I had already navigated away from.
<% cache #answers do %>
<% if #answers.empty? %>
<div class="row">
<h5>This question hasn't been answered yet: <% if can? :create, #answer %>
<% if current_user && !current_user.answers.map(&:question_id).include?(#question.id) %>
<%= link_to "Add an answer", new_question_answer_path(#question) %>
<% end %>
<% end %> </h5>
....some code not included
How can I stop the cache from interfering with logic like this?
You'll have to add the logic into the cache key.
So...
cache [#answers, current_user.answers.map...]
This will base the view on what the user's answer is...you may want to break down the rest into more fragment caches in addition to the above.

Link_to another view ruby on rails

I am trying to use the link_to feature to link one view to another.
The view i am calling link_to is app/views/instructors/show.html.erb and that snippet of code looks like this (namely, the second to last line of it)
<% provide(:title, #instructor.login) %>
<% courses = Course.where(:instructor_ID => #instructor.id) %>
<div class="span2">
<h1 align=center ><%= #instructor.login %></h1>
<%= link_to "Add course", new_course_path(:instructor_ID\
=> #instructor.id), :class => "btn" %>
<br>
<br>
<%= link_to "Remove course", delete_course_path(courses), :class => "btn"%>
</div>
The view I am trying to link to is is app/views/courses/show_all.html.erb and looks like this:
<% #courses.each do |course| %>
<tr>
<td><%= course.course_name %></td>
<td><%= course.instructor_ID %></td>
<td><%= link_to 'Show', course %></td>
<td><%= link_to 'Edit', edit_course_path(course) %></td>
<td><%= link_to 'Destroy', course, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
delete_course_path routes to app/views/courses/show_all.html.erb shown above. When I try the code above, I get the following error:
undefined method `each' for nil:NilClass
At this line:
<% #courses.each do |course| %>
Any ideas what i'm missing in my link_to?
In your show_all action, you should define a #courses instance variables. This is
<% courses = Course.where(:instructor_ID => #instructor.id) %>
not passed to show_all.html.erb.
An instance variables is a variable passed from action of controller to the view corresponding.
I suppose when you show page of instructor, your route will like this: /instructors/:id, so maybe in your show_all action of instructor controller, you need something like:
def show_all
#courses = Course.where(instructor_ID: params[:id])
render 'courses/show_all'
end
This means that #courses is nil. Did you set it in your show_all action of your controller? E.g.
def show_all
#courses = Course.all
end
Also, in your show view, you set courses to a collection of Course objects, but your "Remove course" link looks like you only want to delete one course. Why do you use the delete_course route to link to your show_all view?

How to make the controller action that is adjustable to multiple hash parameters

If I check multiple records in my view then hit the delete button,
discard action will be called.
Now I only can delete(untrash) 1 record at once.
Why can't I delete all of them at once even if I check multiple records???
view
<%= form_tag(:action => discard, :via => 'put') do %>
<% #messages.each do |m| %>
<tr>
<td><%= check_box_tag "id",m.id %></td>
<td><%= m.last_message.id %></td>
<td><%= 'unread' if m.is_unread?(current_user) %></td>
<td><%= m.last_message.created_at.to_s(:jp) %></td>
<td><%= m.last_sender.username %></td>
<td><%= link_to m.subject, show_messages_path(m) %></td>
</tr>
<% end %>
<%= submit_tag "delete", :class => 'btn' %>
<% end %>
controller
def discard
conversation = Conversation.find_all_by_id(params[:id])
if conversation
current_user.trash(conversation)
flash[:notice] = "Message sent to trash."
else
conversations = Conversation.find(params[:conversations])
conversations.each { |c| current_user.trash(c) }
flash[:notice] = "Messages sent to trash."
end
redirect_to :back
end
routes
match 'messages/discard(/:id)' => 'messages#discard' , :as => :discard_messages
When there are multiple inputs of the same name the last one 'wins' - params[:id] will be the value of the last submitted input, so only one message is deleted (this is easily visible by inspecting the value of the params hash)
If the input name ends with [] (i.e. in your case set the name to id[] then rails will instead collect all the values into an array.

ActiveRecord::RecordNotFound Error in Lynda Rails Training (Ch 9 - Delete/Destroy)

I'm new, so forgive my complete ignorance. I'm on Rails 3.2.3 and am doing the Lynda Ruby on Rails Essentials course. I've completed the chapter listed in the title, but am getting an error page after confirming the delete button. Here is a video to show you the error in action.
I've reviewed the following docs to confirm that I've not made typing errors.
Here is my list.html.erb
<div class="subject list">
<h2>Subjects</h2>
<%= link_to("Add New Subject", {:action => 'new'}, :class => 'action new') %>
<table class="listing" summary="Subject List">
<tr class="header">
<th> </th>
<th>Subject</th>
<th>Visible</th>
<th>Pages</th>
<th>Actions</th>
</tr>
<% #subjects.each do |subject| %>
<tr>
<td><%= subject.position %></td>
<td><%= subject.name %></td>
<td class="center"><%= subject.visible ? 'Yes' : 'No' %></td>
<td class="center"><%= subject.pages.size %></td>
<td class="actions">
<%= link_to("Show", {:action => 'show', :id => subject.id}, :class => 'action show') %>
<%= link_to("Edit", {:action => 'edit', :id => subject.id}, :class => 'action edit') %>
<%= link_to("Delete", {:action => 'delete', :id => subject.id}, :class => 'action delete') %>
</td>
</tr>
<% end %>
</table>
Here is my delete.html.erb
<%= link_to("<< Back to List", {:action => 'list'}, :class => 'back-link') %>
<div class="subject delete">
<h2>Delete Subject</h2>
<%= form_for(:subject, :url => {:action => 'destroy'}, :id => #subject.id) do |f| %>
<p>Are you sure you want to permanently delete this subject?</p>
<p class="reference-name">Subject name: <%= #subject.name %></p>
<div class ="form-buttons">
<%= submit_tag("Delete Subject") %>
</div>
<% end %>
</div>
Here is my subjects_controller.rb
class SubjectsController < ApplicationController
def index
list
render('list')
end
def list
#subjects = Subject.order("subjects.position ASC")
end
def show
#subject = Subject.find(params[:id])
end
def new
#subject = Subject.new
end
def create
# Instantiate a new object using form parameters
#subject = Subject.new(params[:subject])
# Save the object
if #subject.save
# If save succeeds, redirect to the list action
redirect_to(:action => 'list')
else
# If save fails, redisplay the form so user can fix problems
render('new')
end
end
def edit
#subject = Subject.find(params[:id])
end
def update
# Find object using form parameters
#subject = Subject.find(params[:id])
# Update the object
if #subject.update_attributes(params[:subject])
# If save succeeds, redirect to the list action
redirect_to(:action => 'show', :id => #subject.id)
else
# If save fails, redisplay the form so user can fix problems
render('edit')
end
end
def delete
#subject = Subject.find(params[:id])
end
def destroy
Subject.find(params[:id]).destroy
redirect_to(:action => 'list')
end
end
Here is the resulting error page referenced in the video above.
If I can get some help in understanding why I can't get this properly delete the file, that would be great.
I'm sorry, I have never heard of "Lynda Ruby on Rails Essentials course" but I can see from your posted code that your delete form looks totally messed up, you have a form_for but you are using a submit_tag! That doesn't make sense. The problem is that if you look in your log file you will see that the params passed in to the delete action do not include an id therefore when you use #subject = Subject.find(params[:id]) you will get the error you are seeing.
The solution - change the submit_tag to f.submit OR change the form_for to a form_tag and make sure the correct route is called, that way the id should be passed back through the params hash.
Your log file stack trace is ALWAYS your very best friend, learn to understand it ASAP and you will find your life a lot easier.
UPDATE
For a large number of reasons I think your best option would be to change your form to look like this
<%= link_to("<< Back to List", {:action => 'list'}, :class => 'back-link') %>
<div class="subject delete">
<h2>Delete Subject</h2>
<p>Are you sure you want to permanently delete this subject?</p>
<p class="reference-name">Subject name: <%= #subject.name %></p>
<div class ="form-buttons">
<%= button_to "Delete", subject_path(#subject), method: :delete %>
</div>
</div>
The reason the first way did not work is because you missed the leading opening tag "<" which is why the text got displayed instead of the button
you don't need the form, you are entering no data so just use the button_to and tell it to go to the delete action.
I haven't tested the code but it should be fine

I am having trouble with my first project in ruby on rails

Here's my index action in the books controller: http://pastebin.com/XdtGRQKV
Here's the view for the action i just mentioned: http://pastebin.com/nQFy400m
Here's the result without being logged in: http://i.imgur.com/rQoiw.jpg
Here's the result when i'm logged in with the user 'admin': http://i.imgur.com/E1CUr.jpg
So the problem is that, in the view, before line 25 the 'user' variable seems to be empty ( or not loaded), and after line 25 the variable 'user' has the expected values.
I have tried initializing a variable in the index method of the books controller but get exactly the same results.
Thanks in advance!
BTW had to make the links text because of stackoverflow limit.
This:
user = User.find_by_id(session[:user_id])
should be in controller, not in view (MVC!) like this:
#user = User.find_by_id(session[:user_id])
Then in your view, as #Voyta answered, use <%= #user.username %>. Code inside <% %> is evaluated, but not rendered, so if you want to put result in your html, you need to add =.
And all yours if user and if user.admin == 1 would look much better this way:
<% if user %>
<td><%= link_to 'Show', book %></td>
<% if user.admin == 1 %>
<td><%= link_to 'Edit', edit_book_path(book) %></td>
<td><%= link_to 'Delete', book, :confirm => 'Are you sure?', :method => :delete %></td>
<% end
end
%>
If you use if in single line like here:
<%
if user
if user.admin == 1
%>
<%= link_to 'New book', new_book_path %>
<%
end
end
%>
You can write the same like this:
<%= link_to 'New book', new_book_path if user && user.admin == 1 %>
You didn't output user.username. It should be <%= user.username %>, not <% user.username %>

Resources