I'm making my first solo rails project. It's a facebook clone, and at the moment I can't get a user to accept a friend request. Please let me know if the information posted isn't sufficient enough to help work towards an answer.
friend_request_controller.rb
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[:id])
#friend_request = current_user.friend_requests.new(friend_id: friend)
if #friend_request.save
redirect_to user_path(current_user)
end
end
def update
friend = User.find(params[:id])
#friend_request = current_user.friend_requests.find(friend_id: friend)
#friend_request.accept
end
show.html.erb
Hello my my email is <%= #user.email %>
<% if user_signed_in? %>
<li>
<%= link_to 'Logout', destroy_user_session_path, :method => :delete %></li>
<li><%= link_to 'All Users', users_path %>
</li>
<% else %>
<li>
<%= link_to('Login', new_user_session_path) %>
</li>
<% end %>
<ul>
<% current_user.friend_requests.each do |request| %>
<h4>You have new friend requests from:</h4>
<li>
<%= User.find(request.friend_id).email %>
<%= link_to "Accept", friend_request_path(friend_id: #friend),method:"put" %>
<%= link_to "Decline", "#" %>
</li>
<% end %>
</ul>
I know something is wrong with my link_to helper here
user.rb
class User < ApplicationRecord
has_many :friend_requests, dependent: :destroy
has_many :pending_friends, through: :friend_requests, source: :friend
has_many :friendships, dependent: :destroy
has_many :friends, through: :friendships
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
friend_request.rb
class FriendRequest < ApplicationRecord
belongs_to :user
belongs_to :friend, class_name: 'User'
def accept
user.friends << friend
destroy
end
def destroy
end
end
Do what #araratan has mentioned + in your frined_request controller, replace params[:id] with params[:friend_id].
Instead of:
<%= link_to "Accept", friend_request_path(friend_id: #friend),method:"put" %>
Try to change #friend to request.friend_id:
<%= link_to "Accept", friend_request_path(friend_id: request.friend_id),method:"put" %>
Related
Trying to learn ruby on rails by creating a reddit clone.
So now I'm trying display the username of the user who created the post, but I'm only getting it displayed as u/username everywhere.
Also when I try to click on u/username to see if I can get data about user by going to his page, all I'm getting is an error saying:
undefined method `username' for nil:NilClass
This is my partial _list class that displays data about post:
<% posts.each do |post| %>
<%= link_to post.community.name %> | Posted by <%= link_to post.account.username, profile_path(:username) %> <%= time_ago_in_words post.created_at%> ago. </p> </small>
<%= link_to post.title, community_post_path(post.community_id, post) %>
<%= truncate post.body, length: 200 %>
<% end %>
profile.html.erb just to display username for now:
<%= #profile.username %>
account.rb:
class Account < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts
has_many :communities
validates_presence_of :username
end
public_controller:
class PublicController < ApplicationController
def index
#communities = Community.all.limit(5)
#posts = Post.order(id: :desc).limit(20)
end
def profile
#profile = Account.find_by_username params[:username]
end
end
post.rb:
class Post < ApplicationRecord
belongs_to :account
belongs_to :community
validates_presence_of :title, :body, :account_id, :community_id
end
and routes.rb:
Rails.application.routes.draw do
devise_for :accounts
get "u/:username" => "public#profile", as: :profile
resources :communities do
resources :posts
end
root to: "public#index"
end
Full repo here
I installed Acts_as_follower. I used the methods from the documentation in my console so I've determined that user 1 follows user 2(using devise) in ActiveRecord, and on my front end in the users/show.html.erb page it shows the appropriate follow/unfollow portion of the button I've implemented. Unfortunately whenever I press the follow/unfollow button nothing changes or happens.
I'm thinking it's the routing but wondering if anybody has an idea of why nothing happens. I've confirmed the lack of action from my console.
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
acts_as_followable
acts_as_follower
has_attached_file :image, :styles => { :medium => "300x300>", :thumb=> "100x100>" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
has_many :articles
has_many :comments
end
routes.rb
Rails.application.routes.draw do
devise_for :users
resources :articles do
member do
put "Like", to: "articles#upvote"
put "Disike", to: "articles#downvote"
end
resources :comments
end
resources :users do
get :follow
get :unfollow
end
root 'welcome#index'
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#user_articles = #user.articles
end
def create
#user = User.find(params[:user_id])
current_user.follow(#user)
end
def destroy
#user = User.find(params[:user_id])
current_user.stop_following(#user)
end
end
followers_controller.rb
class FollowsController < ApplicationController
before_action :authenticate_user!
respond_to :js
def create
#user = User.find(params[:user_id])
current_user.follow(#user)
end
def destroy
#user = User.find(params[:user_id])
current_user.stop_following(#user)
end
end
The button in users/show.html.erb
<div class="follow">
<% if #user.followed_by?(current_user) %>
<%= form_tag user_unfollow_path(user_id: #user.id), method: :post, remote: true do %>
<center><%= button_tag 'unfollow', class: 'btn btn-primary' %></center>
<% end %>
<% else %>
<%= form_tag user_follow_path(user_id: #user.id), method: :post, remote: true do %>
<center><%= button_tag 'follow', class: 'btn btn-success' %></center>
<% end %>
<% end %>
</div>
</div>
Your suspicion is correct, this is indeed a routing issue. But you get an A for effort as the documentation doesn't discuss the front end, good on you for getting this far :)
Your routes should look more like:
resources :users do
post :follow, to: "#followers#create"
delete :unfollow, to: "followers#destroy"
end
Note that unfollow is calling destroy, so by convention it's delete, also by convention create should be post.
Given that, make sure your view will look like:
<div class="follow">
<% if #user.followed_by?(current_user) %>
<%= form_tag user_unfollow_path(user_id: #user.id), method: :delete, remote: true do %>
<center><%= button_tag 'unfollow', class: 'btn btn-primary' %></center>
<% end %>
<% else %>
<%= form_tag user_follow_path(user_id: #user.id), method: :post, remote: true do %>
<center><%= button_tag 'follow', class: 'btn btn-success' %></center>
<% end %>
<% end %>
</div>
I'm trying to implement voting on comments within pits in my app and I keep getting a no method error. I've tried rearranging my code a number of different ways to get it to work but its not cooperating. My error in terminal shows this
Parameters: {"pit_id"=>"1", "comment_id"=>"2"}
Pit Load (0.2ms) SELECT "pits".* FROM "pits" WHERE "pits"."id" = ? LIMIT 1 [["id", 1]]
Completed 500 Internal Server Error in 2ms
NoMethodError (undefined method `comments' for nil:NilClass):
app/controllers/comments_controller.rb:22:in `upvote'
Its finding the "pit id" and the "comment id" but something is clearly a bit off. Would somebody with a better understanding of whats going on to point out what that it is. Thanks.
As it is now my code
_comment.html.erb
<div class = "well">
<p>
<strong>Comment:</strong>
<%= comment.body %>
<p>posted by: <%= comment.user.name %></p>
<%= link_to "Upvote", pit_comment_like_path(#pit, comment), method: :put, :remote => true %>
<%= link_to "Downvote", pit_comment_dislike_path(#pit, comment), method: :put, :remote => true %>
</p>
<p>
<%if comment.user == current_user %>
<%= link_to 'Destroy Comment', [#pit, comment],
method: :delete,
data: { confirm: 'Are you sure?' } %>
<% end %>
</p>
</div>
Comments Controller
class CommentsController < ApplicationController
def create
#pit= Pit.find(params[:pit_id])
#comment = #pit.comments.build(comments_params)
#comment.user = current_user
#comment.save
redirect_to pit_path(#pit)
end
def destroy
#pit = Pit.find(params[:pit_id])
#comment = #pit.comments.find(params[:id])
#comment.destroy
redirect_to pit_path(#pit)
end
def upvote
#comment = Pit.find(params[:pit_id])
#comment = #pit.comments.find(params[:id])
#comment.upvote_by current_user
redirect_to pit_path(#pit)
end
def downvote
#comment = Pit.find(params[:pit_id])
#comment = #pit.comments.find(params[:id])
#comment.downvote_by current_user
redirect_to pit_path(#pit)
end
Routes
Rails.application.routes.draw do
devise_for :users, :controllers => { registrations: 'registrations' }
devise_scope :user do
get 'users/sign_in' => 'devise/sessions#new'
get 'users/sign_out' => 'devise/sessions#destroy'
match 'users/:id', to: 'users#show', as: 'user', via: 'get'
end
resources :pits do
resources :comments do
put "like", to: "comments#upvote"
put "dislike", to: "comments#downvote"
end
end
root to: 'pages#home'
get '/about' => 'pages#about'
end
User Class
class User < ActiveRecord::Base
acts_as_voter
has_many :pits
has_many :comments
enum role: [:user, :vip, :admin]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
def name
name = first_name + ' ' + last_name
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Comment Class
class Comment < ActiveRecord::Base
acts_as_votable
belongs_to :pit
belongs_to :user
end
I have a simple blog and I only want admin access to the create admin options and view. I have installed Devise and used authenticate_admin! in my controllers but when I test it out, the page is still accessible and allows anyone to sign out for admin options. I have limited options to the admin once signed in. The problem is that anyone can sign in. If I can basically just prevent access to the admin sign up page then I'm golden. At least in this case. I'm curious if somebody can point out my error or errors. Let me know if you need anything else. Thanks
class AdminsController < ApplicationController
before_action :authenticate_admin!
def index
end
def created
end
end
Articles Controller
class ArticlesController < ApplicationController
before_action :authenticate_admin!, :except => [:index, :show]
def new
#article = Article.new
end
def index
#article = Article.all
#articles = Article.order('created_at DESC')
#articles_by_month = Article.find(:all, :order => 'created_at DESC').group_by { |article| article.created_at.strftime("%B %Y") }
end
def month_count
#articles_by_month = Article.find(:all, :order => 'created_at DESC').group_by { |article| article.created_at.strftime("%B %Y") }
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def show
#article = Article.find(params[:id])
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text, :image)
end
end
Articles Index view
<div class="bit-75">
<% #article.each do |article| %>
<h2 id="title"><%= link_to article.title, article_path(article) %></h2>
<br>
<ul id="article-links">
<div id="article-image"><%= image_tag article.image_url %></div>
<br>
<li id="article-text"><%= article.text %></li>
<p>Posted on <%= article.created_at %></p>
<br>
<% if admin_signed_in? %>
<li><%= link_to 'Edit', edit_article_path(article) %></li>
<li><%= link_to 'Destroy', article_path(article),
method: :delete, data: { confirm: 'Are you sure?'} %></li>
<li><%= link_to 'New article', new_article_path %></li>
<% else %>
<li><%= link_to 'Make a Comment', article_path(article) %><p>Comments(<%= article.comments.count %>)</p></li>
</ul>
<% end %>
<% end %>
<div id="new-article-path"></div>
</div>
<div class="bit-5">
<h2>Recent Posts</h2>
<br>
<% #article.each do |article| %>
<ul id="recent-article">
<li><%= link_to article.title, article_path(article) %></li>
</ul>
<% end %>
<br>
<br>
<h2>Archives</h2>
<% #articles_by_month.each do |monthname, articles| %>
<h4 id="month-archive"><%=link_to monthname, archives_path %></h4>
<% end %>
<!-- <h2>Tags</h2> -->
</div>
Admin model
class Admin < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Article Model
class Article < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true,
length: { minimum: 5 }
mount_uploader :image, ImageUploader
default_scope -> { order('created_at DESC') }
end
Routes
Blog::Application.routes.draw do
devise_for :admins
devise_scope :admin do get "/admins/sign_out", to: 'devise/sessions#destroy'
end
devise_scope :admin do
get "/admins/sign_in", to: "devise/sessions#new"
end
devise_for :users
root 'articles#index'
resources :articles do
resources :comments
end
get "welcome/index"
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
match '/archives', to: 'archives#index', via: 'get'
You can remove registerable in your Admin model to prevent people from signing up as an admin:
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
but having devise_for :admins and then :users hints that it may be time for you to look into using a permission management gem like CanCanCan.
undefined method avatar?' for nil:NilClass
undefined methodname' for nil:NilClass
Hi, I'm receiving the following errors in my partial. The reason I listed both is because after commenting out the line causing the first error message, I get the second error which leads me to believe the problem isn't with "avatar" or "name" specifically, but with something else,though I don't know what. In rails console, I'm able to call user and name on a comment. I also seeded the database using Faker if that matters. Here's the partial.
<%= content_tag :div, class: 'media', id: "comment-#{comment.id}" do %>
<%= link_to '#', class: 'pull-left' do %>
<%= image_tag(comment.user.avatar.small.url) if comment.user.avatar? %>
<% end %>
<div class="media-body">
<small>
<%= comment.user.name %> commented <%= time_ago_in_words(comment.created_at) %> ago
<% if policy(comment).destroy? %>
| <%= link_to "Delete", [#topic, #post, comment], method: :delete %>
<% end %>
</small>
<p><%= comment.body %></p>
</div>
<% end %>
Also, please see the render.
<div class="col-md-4">
<% if policy(Comment.new).create? %>
<h4>Leave a comment</h4>
<br/>
<%= render partial: 'comments/comment', locals: { topic: #topic, post: #post, comment: #comment } %>
<% end %>
</div>
The below are my user model and comments_controller
class UsersController < ApplicationController
before_filter :authenticate_user!
def update
if current_user.update_attributes(user_params)
flash[:notice] = "User information updated"
redirect_to edit_user_registration_path(current_user)
else
render "devise/registrations/edit"
end
end
private
def user_params
params.require(:user).permit(:name, :avatar)
end
end
Comments_controller
def create
#topic = Topic.find(params[:topic_id])
#post = #topic.posts.find(params[:post_id])
#comments = #post.comments
#comment = current_user.comments.build(comment_params)
#comment.post = #post
#new_comment = Comment.new
authorize #comment
if #comment.save
redirect_to [#topic, #post], notice: "Comment was submitted successfully."
else
flash[:error] = "There was an error submitting the comment. Please try again."
end
end
I've already reset the database, but to no avail. Stuck as to what the issue is. Thanks for your help.
Please see below for my User and Comment models.
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
default_scope { order('created_at DESC') }
validates :body, length: { minimum: 5 }, presence: true
after_create :send_favorite_emails
private
def send_favorite_emails
self.post.favorites.each do |favorite|
if favorite.user_id != self.user_id && favorite.user.email_favorites?
FavoriteMailer.new_comment(favorite.user, self.post, self).deliver
end
end
end
end
User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :posts
has_many :comments
has_many :votes, dependent: :destroy
has_many :favorites, dependent: :destroy
mount_uploader :avatar, AvatarUploader
def role?(base_role)
role == base_role.to_s
end
def favorited(post)
self.favorites.where(post_id: post.id).first
end
def voted(post)
self.votes.where(post_id: post.id).first
end
private
end
If you're getting
undefined method foo for nil:NilClass
it's that the thing you're calling your method on is nil.
So in your case, you're calling avatar? and name on something nil.
Looking at your code, it's clear comment.user is (a) what those methods are called on, and hence (b) what is nil.
Result: your comment has no user. Either enforce all comments (including new/empty/stub ones) to have an user (blank user?), or make your view so that a user is not necessary.
The issue was discovered. In the partial render
comment: #comment
should be
comment: comment