Having trouble associating two users when adding a friend - ruby-on-rails

Thanks for visiting
Whenever I click on Add a friend I get "friend added" but upon checking my console it says Friendship id: 10, user_id: 2, friend_id: 0, created_at: "2015-09-11 05:05:27", updated_at: "2015-09-11 05:05:27"> meaning it's adding but not associating with a friend_id. Can someone help me figure out why it's not saving friend_id whenever I click add a friend. Thank you for all your help.
Schema.rb
create_table "friendships", force: true do |t|
t.integer "user_id"
t.integer "friend_id"
t.datetime "created_at"
t.datetime "updated_at"
end
Routes.rb
root "users#index"
resources :friendships, only: [:create, :destroy]
resources :sessions, only: [:new, :create, :destroy]
resources :users
Users/show
<% #users.each do |user| %>
<% if user.user_name != current_user.user_name %>
<% if #friendshiplink.nil? %>
<%= user.user_name %>
<%= link_to "Add Friend", friendships_path(friend_id: user), method: :post %>
<% else %>
<%= link_to(
("Unfollow"),
"/friendships/#{ #friendshiplink.id }",
method: :delete) %>
<% end %>
<% end %>
<% end %>
User Model
has_many :friendships
has_many :friends, through: :friendships
has_many :inverse_friendships, class_name: "Friendship", foreign_key: "friend_id"
has_many :inverse_friends, through: :inverse_friendships, source: :user
Friendship Model
belongs_to :user
belongs_to :friend, class_name: "User"
User Controller
def show
#users = User.all
#user = User.friendly.find(params[:id])
current_user
if #current_user
#followerlink = Follower.where(leader_id: #user.id,
follower_id: #current_user.id).first
#friendshiplink = Friendship.where(user_id: #user.id,
friend_id: #current_user.id).first
end
end
Friendship Controller
def create
#friendship = current_user.friendships.build(friend_id: params[:friend_id])
if #friendship.save
flash[:notice] = "Added friend."
redirect_to root_url
else
flash[:error] = "Unable to add friend."
redirect_to root_url
end
end
def destroy
#friendship = current_user.friendships.find(params[:id])
#friendship.destroy
flash[:notice] = "Removed friendship."
redirect_to current_user
end
def friendship_params
params.require(:friendship).permit(:friend_id, :user_id)
end
Thanks again for all the help. If there are any question or I'm missing a part of my code which may be needed, Please ask.

This may not be the issue but give it a try:
<%= link_to "Add Friend", friendships_path(friend_id: user.id), method: :post %>
OR
<%= link_to "Add Friend", { action: :create, controller: 'friendship',:friend_id => user.id }, method:"post" %>
Also to make sure of error please add your params from your console
UPDATE: do it in simplest way
def create
#friendship = current_user.friendships.build
#friendship.friend_id = params[:friend_id]
#friendship.user_id = current_user.id
if #friendship.save

Related

I cannot make a function to delete likes

I try to make simple voting system for comments.
Just one button "voteup", and if the user has already clicked it, it changes to "delete vote". And everything seems to work, except for the voice removal feature. If I click "delete vote" an error Couldn't find Post with 'id'=11 appears.
And I do not understand why this is so, because this is, in fact, one method that is used both for voting and for removing one's vote. Only in one case does everything work, but in the other not.
votes_controller:
class VotesController < ApplicationController
before_action :find_comment
before_action :find_vote, only: [:destroy]
def create
if already_voted?
flash[:notice] = "You can't like more than once"
else
#comment.votes.create(author_id: current_author.id)
end
redirect_to post_path(#post)
end
def destroy
if !(already_voted?)
flash[:notice] = "Cannot unlike"
else
#vote.destroy
end
redirect_to post_path(#post)
end
private
def find_comment
#post = Post.find(params[:post_id])
#comment = Comment.find(params[:comment_id])
end
def already_voted?
Vote.where(author_id: current_author.id, comment_id:
params[:comment_id]).exists?
end
def find_vote
#vote = #comment.votes.find(params[:id])
end
end
Votes elements in _comment.html.erb:
<% pre_vote = comment.votes.find { |vote| vote.author_id == current_author.id} %>
<% if pre_vote %>
<%= button_to 'Delete Vote', post_comment_vote_path(comment, pre_vote), method: :delete %>
<% else %>
<%= button_to 'UpVote', post_comment_votes_path(post, comment), method: :post %>
<% end %>
<p><%= comment.votes.count %> <%= (comment.votes.count) == 1 ? 'Like' : 'Likes'%></p>
UPD
This post has id - 3, not 11.
The comment has id 11.
For some reason, it confused everything during the removal of like.
UPD 2
Migration:
def change
create_table :votes do |t|
t.references :comment, null: false, foreign_key: true
t.references :author, null: false, foreign_key: true
t.timestamps
end
end
vote.rb :
class Vote < ApplicationRecord
belongs_to :comment
belongs_to :author
end
comment.rb and author.rb : has_many :votes, dependent: :destroy
It looks like you're missing an argument from your delete link. Try adding post as the first argument:
<%= button_to 'Delete Vote', post_comment_vote_path(post, comment, pre_vote), method: :delete %>

Calling certain comments from the data base

How can I call comments + user information that is specified to the specific post the comment was created under. For example:
/articles/8
new comment created with user_id = 3
Page will show Username + comment + created_at
This is my current code:
Post Show Page
<%= #post.title %>
<%= render '/comments/form' %>
<% #post.user.comments.reverse.each do |comment| %>
<li>
<%= comment.user.email %>
<%= comment.comment %>
</li>
<% end %>
I grab user information associated with the comment but the problem is, it's listing all the comments. How do I make only comments with article_id of 8 for example appear.
Post Controller
def create
#post = Post.new(post_params)
#post.user = current_user
if #post.save!
flash[:notice] = "Successfully created..."
redirect_to posts_path
else
flash[:danger] = "failed to add a post"
render 'new'
end
end
def show
#comment = Comment.new
#comments = Comment.find(params[:id])
end
Comment Controller
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(comment_params)
#comment.user = current_user
if #comment.save
flash[:notice] = "Successfully created..."
redirect_to post_path(#post)
else
flash[:alert] = "failed"
redirect_to root_path
end
end
Routes
resources :sessions, only: [:new, :create, :destroy]
resources :users
resources :posts do
resources :comments
end
Schema of the comments
create_table "comments", force: :cascade do |t|
t.text "comment"
t.integer "user_id"
t.integer "post_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
I am assuming that your model looks like
class Comments < ApplicationRecord
belongs_to :user
belongs_to :post
end
class User < ApplicationRecord
has_many :posts
has_many :comments
end
class Post < ApplicationRecord
belongs_to :user
has_many :comments
end
We want to get all the comments for a post so we we can do something like this
# Note that I took the user from this line
<% #post.comments.reverse.each do |comment| %>
<li>
<%= comment.user.email %>
<%= comment.comment %>
</li>
<% end %>
I hope that this should work.

Implement "add to favorites"

I am creating an app where a user can favorite a room. I started with a has_and_belongs_to_many association. But then I just noticed that it is very tricky to implement a remove button with drestroy. So I decided to do it this time with a has_many through association. I have a users who should add rooms to favorite or wishlist. Unfortunately when I click on the favorite button I am getting this error:
What I am missing how can I make this work?
If you need further information just let me know. I have used this as a direction.
Implement "Add to favorites" in Rails 3 & 4
favorite_room.rb
class FavoriteRoom < ApplicationRecord
belongs_to :room
belongs_to :user
end
room.rb
belongs_to :user
has_many :favorite_rooms
has_many :favorited_by, through: :favorite_rooms, source: :user
user.rb
has_many :rooms
has_many :favorite_rooms
has_many :favorites, through: :favorite_rooms, source: :room
routes.rb
resources :rooms do
put :favorite, on: :member
end
rooms_controller.rb
before_action :set_room, only: [:show, :favorite]
...
...
def favorite
type = params[:type]
if type == "favorite"
current_user.favorites << #room
redirect_to wishlist_path, notice: 'You favorited #{#room.listing_name}'
elsif type == "unfavorite"
current_user.favorites.delete(#room)
redirect_to wishlist_path, notice: 'Unfavorited #{#room.listing_name}'
else
# Type missing, nothing happens
redirect_to wishlist_path, notice: 'Nothing happened.'
end
end
private
def set_room
#room = Room.find(params[:id])
end
show.html.erb
<% if current_user %>
<%= link_to "favorite", favorite_room_path(#room, type: "favorite"), method: :put %>
<%= link_to "unfavorite", favorite_room_path(#room, type: "unfavorite"), method: :put %>
<% end %>
create_favorite_rooms.rb (migration file)
class CreateFavoriteRooms < ActiveRecord::Migration[5.0]
def change
create_table :favorite_rooms do |t|
t.integer :room_id
t.integer :user_id
t.timestamps
end
end
end

Dealing With Multiple Objects

I am new to Rails and currently trying to add a patient to an existing dentist appointment. I am having difficulty setting up my views and controllers properly. How can I properly accomplish this?
Note: With the way I have set things up, I can create an appointment and tie it to a dentist. Of course, the patient_id is missing.
Models:
class Dentist < ActiveRecord::Base
has_many :appointments
has_many :patients, :through => :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :dentists
belongs_to :patients
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :dentists, :through => :appointments
end
Schema:
ActiveRecord::Schema.define(version: 20151107052115) do
create_table "appointments", force: :cascade do |t|
t.integer "dentist_id"
t.integer "patient_id"
t.datetime "appt_date"
end
create_table "dentists", force: :cascade do |t|
t.string "name"
end
create_table "patients", force: :cascade do |t|
t.string "name"
end
end
Routes:
Rails.application.routes.draw do
concern :commentable do
resources :appointments
end
resources :dentists, concerns: :commentable
resources :patients, concerns: :commentable
end
Dentists Controller:
class DentistsController < ApplicationController
def new
#dentist = Dentist.new
end
def create
#dentist = Dentist.new(dentist_params)
if #dentist.save
redirect_to dentists_path
else
render :new
end
end
...
end
Appointments Controller:
class AppointmentsController < ApplicationController
def new
#dentist = Dentist.find(params[:dentist_id])
#appointment = #dentist.appointments.new
end
def create
#dentist = Dentist.find(params[:dentist_id])
#appointment = #dentist.appointments.new(appt_params)
if Appointment.exists?(:appt_date => #appointment.appt_date)
render :new
else
#appointment.save
redirect_to dentist_path(#dentist)
end
end
...
end
Patients Controller:
TBD
Dentists View (Show):
<p><%= #dentist.name %> DDS</p>
<% if #dentist.appointments.any? %>
<% #dentist.appointments.each do |appt| %>
<ul>
<li><%= appt.appt_date %></li>
<p><%= link_to "Edit", edit_dentist_appointment_path(#dentist, appt) %> |
<%= link_to 'Delete', dentist_appointment_path(#dentist, appt), :method => :delete,
data: {:confirm => 'Are you sure you want to delete this record?'} %> |
<%= link_to 'Add Patient', new_patient_path %></p>
</ul>
<% end %>
<% else %>
<p>There are currently no appointments scheduled</p>
<% end %>
<p><%= link_to 'Delete Dentist', dentist_path(#dentist), :method => :delete,
data: {:confirm => 'Are you sure you want to delete this record?'} %></p>
<p><%= link_to 'Create an appointment', new_dentist_appointment_path(#dentist) %></p>
<p><%= link_to 'Return to list', root_path %></p>
I am new to Rails
Welcome!
You need to change your belongs_to references to be singular:
class Appointment < ActiveRecord::Base
belongs_to :dentist
belongs_to :patient
end
--
Because I can't see where you're trying to achieve this functionality, I'll show you what I'd do (using the appointment#edit action):
#app/controllers/appointments_controller.rb
class AppointmentsController < ApplicationController
def edit
#appointment = Appointment.find params[:id]
end
def update
#appointment = Appointment.find params[:id]
#appointment.save appointment_params
end
private
def appointment_params
params.require(:appointment).permit(:dentist_id, :patient_id, :appt_date)
end
end
#app/views/appointments/edit.html.erb
<%= form_for #appointment do |f| %>
<%= f.collection_select :patient_id, Patient.all, :id, :name %>
<%= f.submit %>
<% end %>
--
If you're trying to set the patient from your appointments#create method, you'll be best doing this:
#app/controllers/appointments_controller.rb
class AppointmentsController < ApplicationController
def new
#dentist = Dentist.find params[:id]
#appointment = #dentist.appointments.new
end
def create
#dentist = Dentist.find params[:id]
#appointment = #dentist.appointments.new appointment_params
end
private
def appointment_params
params.require(:appointment).permit(:dentist_id, :patient_id, :appt_date)
end
end
#app/views/appointments/new.html.erb
<%= form_for #appointment do |f| %>
<%= f.collection_select :patient_id, Patient.all, :id, :name %>
<%= f.submit %>
<% end %>
I think what you are asking, is can you create an appointment through both the Dentist model and the Patient model at the same time eg. #dentist.#patient.apointment.new
you cannot do that. Based on the relationships you have set up, you will either want to create the appt from the Dentist, like you have now, and pass in the patient ID as an attribute, or vice-versa. OR, create through your Appointment model eg. Appointment.new(dentist: #dentist, patient: #patient, ...)

Rails returning all Conversation records, not just relevent ones.

I'm working on a basic private messaging system for my application. I started with this tutorial on Medium.
I discovered an issue though. It returns all conversations, not just the ones that the current user is actually involved in. The view only shows the ones you're in but all the records are there. Obviously that is horrible if you have more than a handful of users.
I've tweaked the controller to what I thought was the solution but I'm still getting all records so I'm thinking the issue is in the model.
Conversations Controller
class ConversationsController < ApplicationController
before_action :authenticate_user!
before_action :set_conversation, only: [:destroy]
def index
#user = current_user
#conversations = Conversation.where(:sender_id == #user.id || :recipient_id == #user.id)
end
def create
if Conversation.between(params[:sender_id],params[:recipient_id])
.present?
#conversation = Conversation.between(params[:sender_id],
params[:recipient_id]).first
else
#conversation = Conversation.create!(conversation_params)
end
redirect_to conversation_messages_path(#conversation)
end
Conversation Model
class Conversation < ActiveRecord::Base
belongs_to :sender, :foreign_key => :sender_id, class_name: 'User'
belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User'
has_many :messages, dependent: :destroy
validates_uniqueness_of :sender_id, :scope => :recipient_id
scope :between, -> (sender_id,recipient_id) do
where(sender_id: [sender_id,recipient_id], recipient_id: [sender_id,recipient_id])
end
def unread_message_nr_for(user_id)
messages.where('messages.read = ?', false).where('messages.user_id != ?', user_id).count
end
end
Conversation View
<div class="ibox-content no-side-borders">
<% #conversations.each do |conversation| %>
<div class="conversation-member">
<% if conversation.sender_id == current_user.id || conversation.recipient_id == current_user.id %>
<% if conversation.sender_id == current_user.id %>
<% recipient = User.find(conversation.recipient_id) %>
<% else %>
<% recipient = User.find(conversation.sender_id) %>
<% end %>
<span class="<%= 'current-conversation' if (params['conversation_id'].to_i == conversation.id) %>">
<% if recipient.avatar.present? %>
<%= image_tag(recipient.avatar_url(:navigation), class: "img-circle m-r-xs") %>
<% end %>
<%= link_to recipient.first_name + " " + recipient.last_name, conversation_messages_path(conversation)%>
</span>
<% if conversation.unread_message_nr_for(current_user.id) > 0 %>
<span class="badge-inline">
<%= conversation.unread_message_nr_for(current_user.id) %>
</span>
<% end %>
<% end %>
</div>
<% end %>
</div>
Conversations Schema
create_table "conversations", force: :cascade do |t|
t.integer "sender_id"
t.integer "recipient_id"
t.datetime "created_at"
t.datetime "updated_at"
end
How can I get only the conversations where the current user is the sender_id or the recipient_id?
You can't use ruby in the where clause. See the guides for more info
Conversation.where("sender_id = ? OR recipient_id = ?", #user.id, #user.id)

Resources