Destroying Sessions Issue Rails 4 - ruby-on-rails

I'm having problems destroying the session, the link doesn't seem to work, the URL changes in the address bar from /dashboard to /log_out but the page does not redirect to the log in page. I'm rather baffled at this.
Dashboard View:
<% if logged_in? %>
<% if request.env['mobvious.device_type'] == :mobile %>
<div class="container" style="width: 90%" >
<table>
<tr>
<td class="dash_cont">
<%= link_to "Logout", log_out_path %>
</td>
</tr>
<tr>
<td class="dash_cont">
<h1 class="form-signin-heading" >Welcome to your personal Twitter Manager!</h1>
<p>Use this site to keep track of your followers, see how many posts they've made and many more features!</p>
<p>It's a really cool site, check it out! It's free!</p><br/><br/>
</td>
</tr>
</table>
</div>
<% elsif request.env['mobvious.device_type'] == :desktop %>
<div class="container" style="width: 70%;" >
<table>
<tr>
<td class="dash_cont">
<%= link_to "Logout", log_out_path %>
</td>
</tr>
<tr>
<td class="dash_cont">
<h1 class="form-signin-heading" >Welcome to your personal Twitter Manager!</h1>
<p>Use this site to keep track of your followers, see how many posts they've made and many more features!</p>
<p>It's a really cool site, check it out! It's free!</p><br/><br/>
</td>
</tr>
</table>
</div>
<% end %>
<% else %>
<script type="text/javascript">
window.location.href="/" // put your correct path in a string here
</script>
<% end %>
Log In View:
<% if logged_in? %>
<script type="text/javascript">
window.location.href="/dashboard" // put your correct path in a string here
</script>
<% else %>
<% if request.env['mobvious.device_type'] == :mobile %>
<div class="container" style="width: 90%" >
<table>
<tr class="login-cont">
<td class="login-tcell">
<h1 class="form-signin-heading" >Log in</h1>
<%= form_tag sessions_path, class: "form-signin" do %>
<%= text_field_tag :email, params[:email], class: "form-control", autofocus: "", required: "", placeholder: "Email address" %>
<%= password_field_tag :password, nil, class: "form-control", required: "", placeholder: "Password" %></br>
<p class="button"><%= submit_tag "Log in", class: "btn btn-lg btn-primary btn-block" %></p>
<% end %>
<%= link_to "Register", "/sign_up" %>
<% if defined?(#error) %>
<div class="error">
<%= "*" + #error %>
</div>
<% end %>
<% if defined?(#notice) %>
<div class="error">
<%= "*" + #notice %>
</div>
<% end %>
</td>
</tr>
</table>
</div>
<% elsif request.env['mobvious.device_type'] == :desktop %>
<div class="container" style="width: 70%" >
<table>
<tr class="login-cont">
<td class="login-tcell">
<h1 class="form-signin-heading" >Log in</h1>
<%= form_tag sessions_path, class: "form-signin" do %>
<%= text_field_tag :email, params[:email], class: "form-control", autofocus: "", required: "", placeholder: "Email address" %>
<%= password_field_tag :password, nil, class: "form-control", required: "", placeholder: "Password" %></br>
<p class="button"><%= submit_tag "Log in", class: "btn btn-lg btn-primary btn-block" %></p>
<% end %>
<%= link_to "Register", "/sign_up" %>
<% if defined?(#error) %>
<div class="error">
<%= "*" + #error %>
</div>
<% end %>
<% if defined?(#notice) %>
<div class="error">
<%= "*" + #notice %>
</div>
<% end %>
</td>
<td class="welcome-msg white">
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<h1 class="form-signin-heading" >Welcome to your personal Twitter Manager!</h1>
<p>Use this site to keep track of your followers, see how many posts they've made and many more features!</p>
<p>It's a really cool site, check it out! It's free!</p><br/><br/>
</td>
</tr>
</table>
</div>
<% end %>
<% end %>
Dashboard Controller:
class DashboardController < ApplicationController
helper_method :logged_in?
def new
end
def logged_in?
if defined? session[:user_id]
true
else
false
end
end
end
Sessions Controller:
class SessionsController < ApplicationController
helper_method :logged_in?
# Use this to detect device type:
# request.env['mobvious.device_type']
def new
end
def create
user = User.authenticate(params[:email], params[:password])
if user
session[:user_id] = user.id
#notice = "Logged in!"
redirect_to "/dashboard"
else
#error = "Invalid email or password"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Logged out!"
end
def logged_in?
if defined? session[:user_id]
redirect_to "/dashboard"
else
redirect_to "/"
end
end
end
Routes:
TwitterApp::Application.routes.draw do
get "dashboard/new"
get "users/new"
get "sessions/new"
get "log_out" => "sessions#destroy", :as => "log_out"
get "" => "sessions#new", :as => "log_in"
get "sign_up" => "users#new", :as => "sign_up"
get "dashboard" => "dashboard#new", :as => "dashboard"
root :to => "sessions#new"
resources :users
resources :sessions
end

Don't use defined? to check for the presence of hash values. It will always return a non false value:
some_hash = { :some_key => nil }
defined? some_hash[:some_key] # => "method"
defined? some_hash[:i_dont_exist] # => "method"
See the docs on this for more info.
In rails you can use session[:user_id].present?. This will check that the value at that key is not blank or nil. Also a better way to delete from the session is to call delete on it: session.delete(:user_id) or session.clear if you want to wipe everything.

Related

Add export option to Rails Admin Custom Page

I have the following custom page in Rails Admin:
require 'rails_admin/config/actions'
require 'rails_admin/config/actions/base'
module RailsAdminSapSaeQualifiedSearch
end
module RailsAdmin
module Config
module Actions
class SapSaeQualifiedSearch < RailsAdmin::Config::Actions::Base
RailsAdmin::Config::Actions.register(self)
register_instance_option :collection? do
true
end
register_instance_option :link_icon do
'fa fa-search'
end
register_instance_option :visible? do
authorized? && bindings[:abstract_model].model == Customer
end
register_instance_option :http_methods do
[:get, :patch]
end
register_instance_option :controller do
Proc.new do
if request.get?
#users = []
elsif request.patch?
#users = User.send(params[:qualification], params[:start_at], params[:stop_at], params[:zip])
end
render :action => #action.template_name
end
end
end
end
end
end
...along with this associated view:
<br>
<%= form_tag sap_sae_qualified_search_path(#abstract_model), method: :patch, class: "form-inline" do %>
<div class="form-group">
<%= label_tag :qualification, "Qualification Type:" %>
<%= select_tag :qualification, options_for_select([['SAP', 'sap_qualified'], ['SAE', 'sae_qualified']]), class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :start_at, "Between:" %>
<%= text_field_tag :start_at, params[:start_at] ||= 3.years.ago.to_date, class: "form-control customedate" %>
</div>
<div class="form-group">
<%= label_tag :stop_at, "and:" %>
<%= text_field_tag :stop_at, params[:stop_at] ||= Date.today, class: "form-control customedate" %>
</div>
<div class="form-group">
<%= label_tag :zip, "Zip Code:" %>
<%= text_field_tag :zip, params[:zip] %>
</div>
<%= button_tag "Search", class: "btn btn-default"%>
<% end %>
<script>
$( ".customedate" ).datepicker();
</script>
<% if #users.any? %>
<%= #users.length %> Users found
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Qualified Courses</th>
<th>Licences</th>
<th></th>
</tr>
</thead>
<% #users.each do |user| %>
<tr>
<td width="1%" nowrap><%= user.full_name %></td>
<td width="1%" nowrap><%= user.email %></td>
<td width="1%" nowrap><%= user.phone_1 %></td>
<td style="white-space: normal;"><%= user.sap_courses_passed.where('class_registrations.exam_completed_at >= ? AND class_registrations.exam_completed_at <= ?', params[:start_at].to_date.beginning_of_day, params[:stop_at].to_date.beginning_of_day).collect{|c| "<small><b>#{c.exam_completed_at.strftime('%F')}</b> -- #{c.course_class.title}</small>"}.join('<br>').html_safe %></td>
<td><% user.licenses.each do |l| %>
<%= l.profession %>, <%= l.number %>, <%= l.state %><br>
<% end %>
</td>
<td width="1%" nowrap><%= link_to "Details", {:action => :show, :controller => 'rails_admin/main', :model_name => "Customer", :id => user.id }, class: "btn btn-default", target: "_blank" %></td>
</tr>
<% end %>
</table>
<% end %>
For context here is what the view looks like:
I'd like to add a Rails Admin Export button to this view. I tried something like
register_instance_option :export do
true
end
...with no luck. Any help or ideas appreciated.
You have to do it on the rails admin config
config/initializers/rails_admin.rb
RailsAdmin.config do |config|
[...]
config.actions do
[...]
sap_sae_qualified_search do
only %w{ Customer }
end
end
end
And if that does not work you try also registering the action on that same file before the config block like this :
RailsAdmin::Config::Actions.register(
:sap_sae_qualified_search,
RailsAdmin::Config::Actions::SapSaeQualifiedSearch
)

Nested Resource Rails

I have two models namely todo and tasks. Have set up a Has_many, Belongs_to assosciation between them (todo has many tasks, task belongs to todo).
I have set up a nested resource between them as shown below in my routes file
resources :todos do
resources :tasks
end
My form for creating new task is as shown below:
<%= form_for([#todo, #task], html:{class:'form-horizontal'}) do |f| %>
<% if #task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#task.errors.count, "error") %> prohibited this todo from being saved:</h2>
<ul>
<% #task.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<script type="text/javascript">
$(document).ready(function () {
$('#datep').on('change', function () {
$('.datepicker').hide();
});
});
</script>
<div class="container">
<table style="width:70%" class="table">
<tr>
<td><%= f.label :title , "Task Title"%>
<%= f.text_field :title,:class=>'form-control input-sm' %></td>
</tr>
<tr>
<td><%= f.label :description,"Task Description"%>
<%= f.text_field :description,:class=>'form-control input-sm' %></td>
</tr>
<tr>
<td><%= f.label :deadline,"Task DeadLine"%>
<h id="datep"><%= f.text_field :deadline, :class=>'form-control input-sm', "data-provide" => "datepicker" ,"data-date-format" => "mm-dd-yyyy"%></h></td>
</tr>
<tr>
<td><%= f.label :assignee,"Task Assignee" %><br/>
<%= f.collection_select :assignee, User.all, :name, :name, {}, :class => "btn btn-default dropdown-toggle"%></td>
</tr>
<tr>
<td><%= f.label :tags,"Tags for Task"%>
<%= f.text_field :tags,:class=>'form-control input-sm' %></td>
</tr>
<tr>
<td><%= f.label :state,"Task Status"%><br/>
<%= f.select :state, ['Yet To Start', 'In Progress', 'Finished'], {}, :class => "btn btn-default dropdown-toggle"%></td>
</tr>
</table>
</div>
<br />
<div class="actions form-group">
<div class="container">
<%= f.submit 'Create New Task', class:'btn btn-success'%>
<%= link_to todos_path, class: 'btn btn-warning' do %>
<i class="glyphicon glyphicon-hand-left"></i> Back To List
<% end %>
</div>
</div>
<% end %>
My tasks controller code is shown below:
class TasksController < ApplicationController
def new
#task = Task.new
end
def create
#todo = Todo.find.(params[:todo_id])
#task = #todo.tasks.build(task_params)
if #task.save
redirect_to [#todo, #task]
else
redirect_to root_path
end
end
private
def set_todo
#todo = Todo.find(params[:todo_id])
end
def task_params
params.require(:task).permit(:assignee, :deadline, :state, :tags, :title, :description)
end
end
However when i want to add a new task to an particular todo i get this error saying
undefined method `tasks_path' for #<#<Class:0x007fd16a9c8810>:0x007fd169c95a80>
Did you mean? asset_path
Need help to know what am I doing wrong here???
redirect_to only accepts hash, record or string so this line redirect_to [#todo, #task] won't work. See http://api.rubyonrails.org/classes/ActionController/Redirecting.html. You can change it to redirect_to todo_tasks_path(#todo) which is reasonable here.
I also just noticed you didn't put before_filter :set_todo in the controller. You can remove #todo = Todo.find.(params[:todo_id]) in create action as it's no longer needed.
Hope it helps.

rails attribute changes in spite of not being in form

I have rails app where users can assign tasks to each other. Every task has one assigner and one executor. By default the task creator(current_user) is always the assigner. Both of the assigner and executor are allowed to edit the same task.
My problem is the following. Let's say user.id=2 the assigner and user.id=1 is the executor. If the assigner (id=2) edits the task later on everything works fine, but if the executor (id=1) edits it then he becomes the assigner as well, so task.executor_id = 1 and task.assigner_id = 1. There is no option to change the assigner in the new/edit form. When assigner creates it he is the default assigner as current user and when sby tries to edit it he/she can't change the assigner. What causes this issue?
It's weird since it worked well earlier and I'm kinda sure that I have been experiencing this problem since I've changed to using the _task.html.erb partial with <%= render #tasks %> instead of going w/ the plain old #tasks.each do |task| version. I first thought it happened because I made some mistakes w/ the new AJAXified version, but after git reset --hard it seems to be something else.
def task_params
params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company)
.merge(assigner_id: current_user.id)
end
class Task < ActiveRecord::Base
belongs_to :assigner, class_name: "User"
belongs_to :executor, class_name: "User"
_task.html.erb
<% if current_user.id == task.assigner.id %>
<tr style="background: #eaeaea" id="task_<%= task.id %>">
<td class="col-md-3">
<%= link_to user_path(id: task.executor.id) do %>
<%= task.executor.profile.first_name %> <%= task.executor.profile.last_name%> / <%= task.executor.profile.company %>
<% end %>
</td>
<% else %>
<tr id="task_<%= task.id %>">
<td class = "col-md-3">
<%= link_to user_path(id: task.assigner.id) do %>
<%= task.assigner.profile.first_name %> <%= task.assigner.profile.last_name%> / <%= task.assigner.profile.company %>
<% end %>
</td>
<% end %>
<td class="cold-md-4">
<%= link_to user_task_path(id: task.id) do %>
<%= task.content %>
<% end %>
</td>
<td class="col-md-3">
<%= task.deadline %>
</td>
<td class="col-md-2" style="padding:0px">
<% if current_user.id == task.assigner.id %>
<table class="table table-bordered inside-table" style="background:#eaeaea">
<% else %>
<table class="table table-bordered inside-table">
<% end %>
<tr>
<td class="col-md-4" style="border-top:0px;border-bottom:0px;border-left:0px">
<% if task.completed_at == nil %>
<%= link_to complete_user_task_path(id: task.id), action: :complete, remote: true, method: :patch do %>
<i class="fa fa-check"></i>
<% end %>
<% else %>
<%= link_to uncomplete_user_task_path(id: task.id), action: :uncomplete, remote: true, method: :patch do %>
<i class="fa fa-check"></i>
<% end %>
<% end %>
</td>
<td class="col-md-4" style="border-top:0px;border-bottom:0px;">
<%= link_to edit_user_task_path(id: task.id), type: "button" do %>
<i class="fa fa-pencil"></i>
<% end %>
</td>
<td class="col-md-4" style="border-top:0px;border-bottom:0px;border-right:0px">
<%= link_to user_task_path(id: task.id), method: :delete, data: { confirm: "Are you sure?" }, remote: true do %>
<i class="fa fa-trash"></i>
<% end %>
</td>
</tr>
</table>
</td>
</tr>
_form.html.erb
<%= form_for ([#user, #task]) do |f| %>
<%= render 'layouts/error_messages', object: f.object %>
<div class="field form-group">
<%= f.label :Name_or_Company %>
<%= f.text_field :task_name_company, data: {autocomplete_source: user_tasknamecompanies_path}, class: "form-control task_name_company" %>
</div>
<div class="field form-group">
<%= f.label :content %>
<%= f.text_area :content, class: "form-control" %>
</div>
<div class="field form-group">
<%= f.label :deadline %>
<%= f.date_select :deadline, class: "form-control" %>
</div>
<div class="actions">
<%= f.submit "Create Task", class: 'btn btn-primary', "data-sid" => current_user.id, "data-rip" => :executor_id %>
</div>
<% end %>
UPDATE:
Problem solved based on Rich Peck's and miler350's answers. I did the following:
before_action :set_assigner, only: :create
private
def set_assigner
#task.assigner.id = current_user.id
end
def task_params
params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company).merge(assigner_id: current_user.id)
end
You are setting the assigner id to current_user every time you pass in the params.
I would remove the merge, and just have strong params like this:
params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company, :assigner_id)
Then, in your create action, before you do:
#task.save
Add this:
#task.assigner_id = current_user.id
Then you can define your permissions however you choose (must be assigner, must be executor), but as long as you don't add anything crazy to update, it'll work fine.
By default the task creator(current_user) is always the assigner
This should not matter - someone is the assigner and someone is the executor.
miler350 is correct - your params are constantly setting your assigner_id: current_user.id (looks like one of my suggestions).
The fix is to remove the .merge from your params & set it in your controller action (as per miler350's answer & like this):
#app/controllers/tasks_controller.rb
class TasksController < ApplicationController
def new
#task = Task.new
end
def create
#task = Task.new task_params
#task.assigner = current_user
#task.save
end
def edit
#task = Task.find params[:id]
end
def update
#task = Task.find params[:id]
#task.update task_params
end
private
def task_params
params.require(:task).permit(:executor_id, :name, :content, :deadline, :task_name_company, :assigner_id)
end
end
By letting users "edit" an assignment, you should not have different assigner / executor defined each time.

recipient checklist with text_area form

I am working on implementing a form where a user can compose a message and choose multiple recipients from a checklist in the same form.
I have already built and tested the messaging system which is working but now I want to create the proper form for my desired functionality.
When I use a multipart select form it works fine and looks like this.
<%= form_for #message do |f| %>
<div class="modal-body">
<%= f.text_area :body, class: "form-control"%>
</div>
<!-- displays the current users frinds their following -->
<%= f.select :user_tokens, #user.collect {|x| [x.name, x.id]}, {}, :multiple => true, class: "form-control" %>
<br>
<div class="modal-footer">
<%= f.button :submit, class: "btn btn-primary" %>
</div>
<% end %>
But I want to instead display the users in a checklist, this is what I have so far which displays everything with no errors, but dosent send messages.
<div class="results">
<%= form_tag new_message_path, method: 'get' do %>
<div class="modal-body">
<%= text_area :body, class: "form-control"%>
</div>
<table class="table-bordered">
<thead>
<tr>
<td class="col-md-1">Select</td>
<td class="col-md-1">User</td>
</tr>
</thead>
<% #user.each do |user| %>
<tbody>
<tr>
<td><%= radio_button_tag :user_tokens, user.id %></td>
<td><%= user.name %></td>
</tr>
</tbody>
<% end %>
</table>
<%= submit_tag "Send Message", :name => nil, class: "btn btn-primary" %>
</div>
<% end %>
</div>
Here is my controller
class MessagesController < ApplicationController
before_action :authenticate_user!
def new
#message = Message.new
#user = current_user.following
#users = User.all
end
def create
#message = current_user.messages.build(message_params)
if #message.save
flash[:success] = "Message Sent!"
redirect_to messages_path
else
flash[:notice] = "Oops!"
render 'new'
end
end
def index
#user = User.find(current_user)
#messages = Recipient.where(:user_id => #user).order("created_at DESC")
end
private
def message_params
params.require(:message).permit(:body, :sender_id, user_tokens: [])
end
end
My question is what is the best way to get this functionality?
Let me know if you need to see any other info, thanks.
I ended up figuring it out Thanks to this previous post I found, rails 3 has_many :through Form with checkboxes.
<%= form_for #message do |f| %>
<%= f.text_field :body %>
<p>
<% #user.each do |user| %>
<div>
<%= check_box_tag "message[user_tokens][]", user.id, #message.users.include?(user) %>
<%= user.name %>
</div>
<% end %>
</p>
<p><%= f.submit %></p>
<% end %>

errors uploading a file "name cant be blank"

I am trying to add the option to upload and download files in my Rails application, but I keep getting this error when I try to upload my file:
name can't be blank
Here's my code:
newsletters_controller.rb:
class NewslettersController < ApplicationController
def index
#newsletters = Newsletter.all
end
def new
#newsletter = Newsletter.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #newsletter }
end
end
def create
#newsletter = Newsletter.new(newsletter_params)
if #newsletter.save
redirect_to newsletters_path, notice: "The newsletter #{#newsletter.name} has been uploaded."
else
render "new"
end
end
def destroy
#newsletter = Newsletter.find(params[:id])
#newsletter.destroy
redirect_to newsletters_path, notice: "The newsletter #{#newsletter.name} has been deleted."
end
private
def newsletter_params
params.require(:newsletter).permit(:newsletter, :attachment)
end
end
index.html.erb:
<% if !flash[:notice].blank? %>
<div class="alert alert-info">
<%= flash[:notice] %>
</div>
<% end %>
<br />
<%= link_to "New Newsletter", new_newsletter_path, class: "btn btn-primary" %>
<br />
<br />
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Download Link</th>
<th> </th>
</tr>
</thead>
<tbody>
<% #newsletters.each do |newsletter| %>
<tr>
<td><%= newsletter.name %></td>
<td><%= link_to "Download Newsletter", newsletter.attachment_url %></td>
<td><%= button_to "Delete", newsletter, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{newsletter.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
new.html.erb:
<% if !#newsletter.errors.empty? %>
<div class="alert alert-error">
<ul>
<% #newsletter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="well">
<%= form_for #newsletter, html: { multipart: true } do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :attachment %>
<%= f.file_field :attachment %>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
</div>
routes.rb:
resources :newsletters, only: [:index, :new, :create, :destroy]
root "newsletters#index"
get "newsletters/index"
get "newsletters/new"
get "newsletters/create"
get "newsletters/destroy"
change:
params.require(:newsletter).permit(:newsletter, :attachment)
to:
params.require(:newsletter).permit(:newsletter, :attachment, :name)
This way, the model will receive the name from the form and validation will succeed.

Resources