Rails: Display pending friend requests in view - ruby-on-rails

I am trying to to have the words Pedning Request show up next to a user in the user index if the current user has requested them or if the current user has been requested by them. I have a feeling something is wring with my erb, or I am just taking the wrong approach completely. When I click the add friend link, I want it to redirect back to the index page with the updated status of the request but it still displays the add friend link.
index.html.erb
Facebook Users:
<ul><% #users.each do |user| %>
<% if current_user == user || current_user.friends.include?(user) %>
<li><%= link_to user.email, user_path(user) %></li>
<% current_user.friend_requests.each do |request| %>
<% if request.friend_id == user.id %>
<li><%= link_to user.email, user_path(user) %>
| Pending Request</li>
<% end %>
<% end %>
<% else %>
<li><%= link_to user.email, user_path(user) %> |
<%= link_to "Add Friend", friend_requests_path(friend_id: user.id), method: :post %>
</li>
<% end %>
<% end %>
</ul>
<%= link_to 'Back to your profile', user_path(current_user) %>
<%= render 'shared/error_messages', object: current_user %>
<%= params.inspect %>
class FriendRequestsController < ApplicationController
before_action :set_friend_request, except: [:index, :create]
def index
#incoming = FriendRequest.where(friend: current_user)
#outgoing = current_user.friend_requests
end
def create
#user = User.find(current_user)
#friend = User.find(params[:friend_id])
#friend_request = current_user.friend_requests.new(friend_id: #friend.id)
if #friend_request.save
flash[:notice] = "Friend request sent!"
redirect_to users_path
else
flash[:notice] = "Unable to request friend"
redirect_to users_path
end
end
def update
friend_email = User.find(#friend_request.friend_id).email
#friend_request = FriendRequest.find_by_user_id_and_friend_id(params[:friend_id], params[:id])
if #friend_request.accept
flash[:notice] = "You and #{friend_email} are now friends!"
redirect_to user_path(current_user)
end
end
def destroy
if #friend_request.destroy
flash[:notice] = "Request Declined"
redirect_to user_path(current_user)
end
end
private
def set_friend_request
#friend_request = FriendRequest.find_by_user_id_and_friend_id(params[:friend_id], params[:id])
end
end

The if block starting with...
<% if request.friend_id == user.id %>
... is INSIDE the 'if' block starting with...
<% if current_user == user || current_user.friends.include?(user) %>
So basically the "Pending Request" can only be shown if the user is yourself (the current user) or if the user is already your friend. That doesn't make sense, of course.
Better to move the code after the first if's elseand you don't really need to loop through all the requests with each, just map the friend_id's
<ul>
<% #users.each do |user| %>
<% if current_user == user || current_user.friends.include?(user) %>
<li><%= link_to user.email, user_path(user) %></li>
<% else %>
<% if current_user.friend_requests.pluck(:friend_id).include? user.id %>
<li><%= link_to user.email, user_path(user) %>
| Pending Request</li>
<% else %>
<li><%= link_to user.email, user_path(user) %> |
<%= link_to "Add Friend", friend_requests_path(friend_id: user.id), method: :post %>
</li>
<% end %>
<% end %>
<% end %>
</ul>

Related

Rails Form_for "First argument in form cannot contain nil or be empty" after logging out(sessions#destroy)

After logging in and then logging out, I keep getting the error that the first argument in the form cannot be nil or empty. How do I solve this issues while still maintaining the disappearance of the form when a user is logged in?
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-left">
<li>
<% if current_user %>
<li>
<li><%= link_to "Profile Summary", current_user %></li>
</li>
<li>
<li><%= link_to "Edit personal details", edit_user_path %></li>
</li>
<li>
<li><%= link_to "Logout", logout_path, method: "delete" %></li>
</li>
<% else %>
<li><%= form_for #user do |f| %>
<div class="form-group">
<%= f.text_field :email, :placeholder => "Email", class: "form-control" %>
</div>
<div class="form-group">
<%= f.password_field :password, :placeholder => "Password", class: "form-control" %>
</div>
<%= f.submit 'Login', class: "btn btn-default" %>
<% end %>
</li>
<% end %>
<li>
<li><%= link_to "New User", new_user_path %></li>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
<li><%= link_to 'Opinions', profile_path %></li>
</li>
<li>
<li><%= link_to 'About',contact_path %></li>
</li>
<li>
<li><%= link_to 'Contact', contact_path %></li>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
The following is my Users controller
def new
#user = User.new
end
def show
#user = User.find_by_id(session[:user_id])
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Account Created. Please Login"
redirect_to profile_path
else
flash[:danger] = "Please fill in all your information"
render :new
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user
flash[:success] = 'User profile successfully updated.'
else
render :edit
end
end
def profile
end
And this is the sessions controller
def create
user = User.find_and_authenticate_user(user_params)
if user
session[:user_id] = user.id
flash[:success] = "You are logged in."
#redirect_to refers to a get command by default as it is
#the only command to display. *_path is a combination of
#the RESTful actions
redirect_to profile_path
else
flash[:danger] = "Credentials Invalid!!"
redirect_to login_path
end
end
def destroy
session[:user_id] = nil
flash[:success] = "User logged out!!"
redirect_to root_path
end
As you have not described your current_user helper method, it is a bit difficult to answer.
But still, as per my understanding current_user method will give the user that is signed in rather than giving a boolean value.
If that is the case, for a new user, show action will not receive any session Id and as a result, #user will be null. Now, your condition will fail and else part will give you the null or empty error.
To get over that, you can either compare like session[:user_id] == #user.id in your helper method and return the boolean value as a result or use direct comparison with session ID in your view if the helper is returning complete logged in user object.
Hope this helps..

Rails how to send params[:commit] value

I am building a blog application in which I am trying to send some values like
post.id
params[:commit] (value )
So from my show action I am sending these 2 values to my edit action in my posts controller but i am unable to collect params[:commit] value ..in my case for approve it will send 'approve' and for decline it will send 'decline' but it is not sending
[posts/show.html.erb]
<div id="post_content">
<h1 class="title"><%= #post.title %></h1>
<p class="date">
Submitted <%= time_ago_in_words(#post.created_at) %> Ago
<% if user_signed_in? %>
<%= link_to 'Edit', edit_post_path(#post) %> |
<%= link_to 'Delete', post_path(#post), method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to "approve",[:edit,#post] ,commit: "Approve"%>
<%= link_to "decline",[:edit,#post],commit: "decline" %>
<% end %>
</p>
<p class="body"><%= #post.body %></p>
<div id="comments">
<h2><%= #post.comments.count %> Comments</h2>
<%= render #post.comments %>
<h3>Add a comment:</h3>
<%= render "comments/form" %>
</div>
</div>
[posts_controller.rb]
class PostsController < ApplicationController
before_action :authenticate_user!
def index
#posts = Post.user_post(current_user).order('created_at DESC').paginate(:page => params[:page], :per_page => 5)
end
def new
#post = Post.new
end
def show
#post=find_params
end
def create
#post = Post.new(post_params)
#post.user = current_user
if #post.save
Post.upload(params[:post][:files],#post.id)
redirect_to #post
else
render 'new'
end
end
def edit
#post = find_params
puts "cccccccccc#{params[:commit]}"
Post.up(#post.id,params[:commit])
end
def update
#post = find_params
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = find_params
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def find_params
Post.find(params[:id])
end
end
Change your link_to tag according to this.
<%= link_to "approve", edit_post_path(#post, commit: "Approve") %>
<%= link_to "decline", edit_post_path(#post, commit: "Decline" %>

How to combine a <div> with a Rails "link_to"?

I am creating a "to-do website". Users can log in and generate tasks as well as notes. The tasks work perfectly but I have some issues with notes for some reason. I don't use any partials for notes. If I use this on my index.html.erb as I did for the tasks:
<div class="notes">
<%= link_to 'New Note', new_note_path %>
<div class="note">
<div>
<%= link_to note_path(note) do %>
<%= note.content %>
<%= link_to 'X', note, :class => 'task-destroy', method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
</div>
<div>
<%= link_to edit_note_path(note) do %>
<%= time_ago_in_words(note.updated_at) %> ago
<% end %>
</div>
</div>
</div>
I get:
"NameError in NotesController#index" - "undefined local variable or
method `note' for #..."
notes_controller.rb
class NotesController < ApplicationController
before_action :logged_in_user
before_action :set_note, only: [:show, :edit, :update, :destroy]
def index
#notes = current_user.notes
end
def show
end
def new
#note = Note.new
end
def edit
end
def create
#note = current_user.notes.new(note_params)
if #note.save
flash[:success] = "You successfully created a Note!"
redirect_to notes_path
else
render 'new_note_path'
end
end
def update
#note.update(note_params)
if #note.save
flash[:success] = "You successfully updated a Note!"
redirect_to notes_path
else
render 'edit_note_path'
end
end
def destroy
#note.destroy
flash[:success] = "You successfully deleted a Note!"
redirect_to notes_path
end
private
def set_note
#note = Note.find(params[:id])
end
def note_params
params.require(:note).permit(:content)
end
end
Question: What is wrong with my instance variable on my controller and how can I make it work?
add loop before <div class="note"> to loop through list of notes stored in #notes in your index action.
Html should look like this:
<% #notes.each do |note| %>
<div class="note">
<div>
<%= link_to note_path(note) do %>
<%= note.content %>
<%= link_to 'X', note, :class => 'task-destroy', method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
</div>
<div>
<%= link_to edit_note_path(note) do %>
<%= time_ago_in_words(note.updated_at) %> ago
<% end %>
</div>
</div>
</div>
<% end %>
Your index.html.erb view doesn't have access to a note variable.
The instance variable from the following method is the only variable being passed to the view:
def index
#notes = current_user.notes
end
You would probably need to do something like,
<% #notes.each do |n| >
<%= link_to(n) >
<% end >

Rails withdraw_event_path 'undefined local method'

I found a great solution to a problem of mine here
I've built it into my own project, but I can't seem to call the withdraw event.
show.html.erb
<p><strong>Attendees: </strong>
<ul>
<% for attendee in #event.users %>
<% if attendee.id == current_user.id %>
<li><strong><%= attendee.name %></strong>
<%= link_to 'Withdraw From Event', withdraw_event_path(#event.id), :method => :post, :class => 'btn btn-danger' %>
</li>
<% else %>
<li><%= attendee.username %></li>
<% end %>
<% end %>
</ul>
</p>
<p>
<%= link_to 'Attend Event', attend_event_path(#event.id), :method => :post %>
</p>
event_controller.rb
def attend
#event = Event.find(params[:id])
current_user.events << #event
redirect_to #event, notice: 'You are now attending this event'
end
def withdraw
event = Event.find(params[:id])
attendee = Attendee.find_by_user_id_and_event_id(current_user.id, event.id)
if attendee.blank?
redirect_to event
end
attendee.delete
redirect_to event, notice: 'You are no longer attending this event.'
end
when I call event->show I get this error
undefined local variable or method `withdraw_event_path' for #<#<Class:0x007fd5d575a910>:0x007fd5d22a72e0>
Any ideas why the path isn't working? I'm new to rails
THanks
you need to add withdraw to your routes, that will create the method withdraw_event_path
resources :events do
member do
post 'withdraw'
end
end

Need help with implementing Railscast 198 in Rails 3

I have been trying to implement Ryan Bates Railscast 198 into rails 3 for like 4 days... at least at night if you know what I mean. Anyway, here is the code I have right now:
User controller actions (Devise setup to show the different states of approved):
def index
if params[:approved] == "false"
#users = User.find_all_by_approved(false)
elsif
#users = User.find_all_by_approved(true)
else
#users = User.all
end
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to root_path flash[:notice] = "User was successfully updated." }
else
format.html { render :action => "edit" }
end
end
end
def edit_individual
#users = User.find(params[:user_ids])
end
def update_individual
#users = User.update(params[:users].keys, params[:users].values).reject { |p| p.errors.empty? }
if #users.empty?
flash[:notice] = "Users updated"
redirect_to users_url
else
render :action => "edit_individual"
end
end
end
My User#index
<h1> Users</h1>
<%= link_to "All Users", :action => "index" %> |
<%= link_to "Users awaiting approval", :action => "index", :approved => "false"%>
|
<%= link_to "Approved Users", :action => "index", :approved => "true" %>
<%= form_tag edit_individual_users_path, :method => :put do %>
<table>
<tr>
<th>Email Address</th>
<th>Approved</th>
<th></th>
</tr>
<% for user in #users %>
<tr>
<td> <%= user.email %></td>
<td><%= check_box_tag user.id %></td>
<td> <%= link_to "Edit", edit_user_path(user) %></td>
</tr>
<% end %>
<p><%= submit_tag "Edit Checked" %></p>
</table>
<% end %>
And the User#edit_individual
<%= form_tag update_individual_users_path, :method => :put do %>
<% for user in #users %>
<%= fields_for "users[]", user do |f| %>
<h2><%=h user.name %></h2>
<p><%= check_box_tag user.id %></p>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
routes.rb
devise_for :users
resources :users do
collection do
post :edit_individual
put :update_individual
end
end
end
So I handled the basic by googling: fields_for needs an "=" stuff like that. #index shows fine but if I check a checkbox and then hit the edit checked button I get the following error:
ActiveRecord::RecordNotFound in UsersController#update
Couldn't find User with id=edit_individual
Any ideas??? thanks so much
Please check your routes.rb and controller code, as it's quite a bit off from the code on Railscast 198's page: http://railscasts.com/episodes/198-edit-multiple-individually
It's best to just copy it in if you're new to rails and adjust for using users instead of products. Then go through it to try to understand what it does.

Resources