Divya Divya - 3 months ago 24
Ajax Question

How to show flash message of before_action filter authenticate_user! on a action which is called through ajax

Application Controller

class ApplicationController < ActionController::Base

before_action :authenticate_user!, only: [:edit, :update, :destroy, :vote], not`enter code here`ice: "you must logged in first!!!"
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?

protected

def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) do |user_params|
user_params.permit(:name, :email, :password,
:password_confirmation, :avatar)
end
devise_parameter_sanitizer.permit(:account_update) do |user_params|
user_params.permit(:name, :email, :password,
:password_confirmation, :current_password, :remove_avatar, :avatar)
end
end
end


And here is the
post controller
in which vote method is called by ajax:

Posts Controller

class PostsController < ApplicationController

def index
if params[:search]
@posts = Post.search(params[:search]).order("created_at ASC")
else
@posts = Post.all.order('created_at ASC')
end
end

def show_all_post_of_current_user
@current_user_posts = current_user.posts.all
end

def show
@post = Post.find(params[:id])
end

def vote
@post = Post.find(params[:id])
@vote = @post.votes.new :user_id => current_user.id, :vote => params[:vote]
@vote.save
respond_to do |format|
format.html do
if @vote.valid?
flash[:notice] = 'Thanks for voting.'
else
flash[:error] = 'You can only vote on a post once.'
end
redirect_to :back
end
format.js
end
end

def new
@post = current_user.posts.build
end

def display_post_of_current_user
@display = current_user.posts.find(params[:id])
end

def edit
@post = current_user.posts.find(params[:id])
end

def create
@post = current_user.posts.build(post_params)
if @post.save
redirect_to display_post_path(@post)
else
render 'new'
end
end

def update
@post = current_user.posts.find(params[:id])
if @post.update(edit_post_params)
redirect_to display_post_path(@post)
flash[:success] = "Post updated successfully"
else
render 'edit'
end
end

def destroy
@post = current_user.posts.find(params[:id])
@post.destroy
redirect_to post_path
flash[:success] = "Post deleted successfully"
end

private
def post_params
params.require(:post).permit(:title, :description, :date, :category, :picture)
end

def edit_post_params
params.require(:post).permit(:title, :description)
end
end


View

<h1>Post Description</h1>
<p>
Submitted <%= time_ago_in_words(@post.created_at) %>
by <%= @post.user.email %>

</p>
<p>
<strong>Title:</strong>
<%= @post.title %>
</p>
<p>
<strong>Description:</strong>
<%= @post.description %>
</p>

<p>
<%= link_to vote_post_path(@post, vote: true), method: 'post', remote: true do %>
<span> Up </span> | <span id='post_<%=@post.id%>_votes'><%= @post.up_votes %></span>
<%end %>

<%= link_to vote_post_path(@post, vote: false), method: 'post', remote: true do %>
<span> Down </span> | <span id='post_<%=@post.id%>_votes'><%= @post.down_votes %></span>
<%end %>

<span id='post_<%=@post.id%>_votes'><%= @post.total_votes %> votes</span> |
<%= link_to "Back", posts_path %>
</p>


vote.js.erb

<% if @vote.valid? %>
$("#post_<%= @post.id %>_votes").html("<%= @post.total_votes %> votes")
$("#post_<%= @post.id %>up_votes").html("<%= @post.up_votes %>")
$("#post_<%= @post.id %>down_votes").html("<%= @post.down_votes %>")
<% else %>
alert('You can only vote on a post once.');
<% end %>


While user click on upvote or downvote link an ajax is called on vote method of post controller. and a filter on application controller restrict user to perform voting until user logged_in I use before filter for authenticate user method of devise.
But don't know how to generate flash while user click on upvote or downvote.

Answer

You can call flash message inside your js.erb file which you are calling when the user clicks on the vote.

vote.js.erb

<%= flash[:notice] %>

You might have to change your respond_to block

respond_to do |format|
  if @vote.valid?
    format.html { flash[:notice] = 'Thanks for voting.' }
    format.js   { flash[:notice] = 'Thanks for voting.' }
  else
    format.html { flash[:error] = 'You can only vote on a post once.'}
    format.js   { flash[:error] = 'You can only vote on a post once.'}
  end
end

it might also help you form_with_ajax

Update You need do your own authenticate_user! action and in this action, you can have the behaviour your want. put message what you want on js file

def authenticate_user!
  unless current_user
    render 'yourjs'
  end
end