Following and unfollowing events - ruby-on-rails

I've done Michael Hartl Ruby on Rails 5 tutorial and am now trying to apply the code to my own app.
What I'm trying to do is:
Follow/Unfollow an event
Display total count of users following this event
Users can see all the events that they are following
The current error appears when I try to render the conferences that current user is following.
The error that I get is:
ActionController::UrlGenerationError in Users#show
No route matches {:action=>"followers", :controller=>"conferences", :id=>nil} missing required keys: [:id]
The line that causes the problem is:
<a href="<%= followers_conference_path(#conference) %>">
Now obviously their is something wrong in my routing and I assume the following problem states that conferences is missing a required id?
Does anyone know the solution to my problem? Which is getting allowing users to follow events and see what events they are following
USER CONTROLLER SHOW
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
#managments = #user.managments.paginate(page: params[:page])
#conference = Conference.find(params[:id])
end
ROUTES.RB
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/my_conference', to: 'my_conference#show'
get '/conferences', to: 'conferences#index'
get '/conferences_list', to: 'conferences#index_admin'
get '/my_employees', to: 'employees#index'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/login', to: 'sessions#new'
put 'activate/:id(.:format)', :to => 'users#activate', :as => :activate_user
put 'deactivate/:id(.:format)', :to => 'users#deactivate', :as => :deactivate_user
put 'activate_employee/:id(.:format)', :to => 'employees#activate', :as => :activate_employee
put 'deactivate_employee/:id(.:format)', :to => 'employees#deactivate', :as => :deactivate_employee
resources :users do
member do
get :following
end
end
resources :conferences do
member do
get :followers
end
end
resources :articles
resources :users
resources :employees
resources :account_activations, only: [:edit]
resources :activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :managments
resources :conferences
resources :relationships, only: [:create, :destroy]
end
CONFERENCES_CONTROLLER.RB
class ConferencesController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
before_action :admin_user, only: :destroy
def index
#conferences = Conference.paginate(page: params[:page])
if params[:search]
#conferences = Conference.search(params[:search]).order("created_at DESC").paginate(page: params[:page])
else
#conferences = Conference.all.order('created_at DESC').paginate(page: params[:page])
end
end
def new
#user = User.new
#conference = Conference.new
end
def create
#conference = current_user.conferences.build(conference_params)
if #conference.save
flash[:success] = "conference created!"
redirect_to conferences_path
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'new'
end
end
def destroy
#conference.destroy
flash[:success] = "conference deleted"
redirect_to request.referrer || root_url
end
def following
#title = "Following"
#conference = Conference.find(params[:id])
#conferences = #conference.following.paginate(page: params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(page: params[:page])
render 'show_follow'
end
private
def conference_params
params.require(:conference).permit(:conference,:country , :month, :presence, :audience, :cost ,:picture)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
def correct_user
#conference = current_user.conferences.find_by(id: params[:id])
redirect_to root_url if #conference.nil?
end
end

Ahh, i see the issue.
Check your UsersController#show to see if #conference is being set anywhere.
If not try: <a href="<%= followers_conference_path(current_user.id) %>">

You don't want to use the user id to get the #conference object, I'm sure. Instead, you are probably generating a list of conferences the user is following. In that case, you'd use something like this
<% #user.conferences.each do |conference| %>
<%= conference.name %>
<% end %>
And, in Rails, you would usually use the link_to helper, and maybe include a count to show how many followers the conference has.
<% #user.conferences.each do |conference| %>
<%= link_to conference.name, followers_conference_path(conference) %>
(<%= pluralize conference.users.count, 'follower' %>)
<% end %>

Related

Admin function in rails: Error: Couldn't find User with 'id'=

I am trying to write an update function, which allows to pick a user in a list of users and update that user to make it an admin. The important function in the controller should be def change_admin.
Thanks for your help!
I tried several options, but I run into that error:
Couldn't find User with 'id'=
My Controller:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def new
#user = User.new
end
def index
#users = User.where(activated: true).paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
redirect_to root_url and return unless #user.activated
end
def edit
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "Der Nutzer wurde gelöscht"
redirect_to users_url
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to root_path
else
render 'edit'
end
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Bitte öffnen Sie Ihr E-Mail Postfach, um den Account zu aktivieren."
redirect_to root_url
else
render 'new'
end
end
def admin
#users = User.where(activated: true).paginate(page: params[:page])
end
def change_admin
#user = User.find(params[:id])
#user.update_attribute(:admin,true)
respond_to do |format|
format.html { redirect_to admin_path }
end
end
# Before filters
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation,
:mat_number, :ects, :grade_avg, :enrolled, :matched_institute)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
I also tried to delete the user.find line, but that gives me another error:
undefined method `update_attribute' for nil:NilClass
My routes file:
Rails.application.routes.draw do
resources :preferences
resources :institutes
get 'password_resets/new'
get 'password_resets/edit'
get '/users_show', to: 'users#show'
get '/users/new'
root 'static_pages#home'
get '/home', to: 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/matching', to: 'static_pages#matching'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/admin', to: 'users#admin'
post '/change_admin', :to => 'users#change_admin', as: 'change_admin'
get '/performance_show', to: 'users#performance_show'
get '/performance_update', to: 'users#performance_update'
post 'preferences/create_all', :to => 'preferences#create_all'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
post 'preferences/delete_matching', :to => 'preferences#delete_matching'
post 'preferences/read_and_show_ofv', :to => 'preferences#read_and_show_ofv'
post 'preferences/read_matching', :to => 'preferences#read_matching'
post 'preferences/optimize_matching', :to => 'preferences#optimize_matching'
post 'preferences/optimize', to: 'preferences#optimize'
end
Your routes are in pretty bad shape. You have tons of duplication as well as routes that are missing the :id segment to make them work:
get '/users_show', to: 'users#show'
get '/users/new'
post '/change_admin', :to => 'users#change_admin', as: 'change_admin'
resources :users already declares a proper show route as GET /users/:id and new as /users/new.
To add additional RESTful routes you should instead pass a block to resources:
resources :users do
# this should be PATCH not POST
patch :change_admin
end
This will create the proper route as /users/:id/change_admin.
You are also using the wrong HTTP verb in many places like for example get '/performance_update', to: 'users#performance_update'. Never use GET for actions that create or alter a resource as the call ends up in the browsers history and may be cached.
Adding update, change, create in the path of your route should be a big red flag that you´re doing it wrong.
I would recommend that you read the guides thoroughly before adding more cruft.

Render show view from another controller

I have previewed all questions with similar topics and none of those solutions help me. I am attempting to create a twitter like feed that will display posts of a certain category in rails.
This is my industries controller:
class IndustriesController < ApplicationController
def index
#wads = Wad.order('created_at DESC')
end
def music
#music_wads = Wad.where(category: "Music").paginate(page: params[:page], per_page: 20)
#wad = #music_wads.pluck(:id)
end
end
This is part of my posts controller:
class WadsController < ApplicationController
before_action :find_wad, only: [:show, :edit, :update, :destroy]
def index
#wads = Wad.all
end
def show
#wad = Wad.find(params[:id])
end
def new
#wad = Wad.new
end
def create
#wad = current_user.wads.build(wad_params)
if #wad.save
redirect_to #wad
else
flash[:error] = 'Error try again'
render 'new'
end
end
end
And this is my show view for my industries controller:
<h1>Music Wads</h1>
<%= will_paginate #music_wads %>
<% #music_wads.each do |music_wad| %>
<%= link_to 'wads/:id' do %>
<div class="flex-rectangle">
<%= music_wad.user.name %>
<%= music_wad.short_form %>
<% end %>
</div>
<%= will_paginate #music_wads %>
<% end %>
Here is my routes file:
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/industries', to: 'industries#index'
get '/music', to: 'industries#music'
get '/tech', to: 'industries#tech'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :wads
end
I am attempting to make it so that clicking on a post among the lists of post carries you to page of that post (/wads/id). I've been baffled all day and am now at my wits end. I am aware I am a noob and this is a nooby question but any help would gladly be appreciated.
Thanks
resources :wads will create some routes that you can use.
Running rails routes (on rails 5) or rake routes (on rails 4 and lower) in the console will give you the list of your routes.
Under the prefix column you could find the correct route name you should use and under the URI Pattern you could see the actual address it links to.
You asked for wads/:id so the link should be <%= link_to wad_path(wad_music) do %> (the prefix is wad_path and you need to give it the object which holds the id - or an id...)
Since you want to link to a singular action - meaning that the action will get and id of an object - and get it (gets a single object!) the link prefix will be in singular form as well: wad_path and not wads_path
(wads_path will link to the index action in the controller and doesn't need to get any object or id)

Rails 5: PUT doesn't work using friendly_id

Ok... so now I'm at day 2 trying to figure out why on my development env, it works but when I deploy my app to production it doesn't work.
I'm simply trying to create a "like/upvote" button and count the "likes/upvotes" on every post, and then do the same for every comment in a post.
Since I'm using friendly_id to create a slug from the :title field, I'm getting this in my Heroku Logs:
ActionController::RoutingError (No route matches [GET] "/posts/test/upvote"):
I obviously get the "This page doesn't exist" error...
Here's the code:
routes.rb
resources :posts, only: [:create, :index, :show, :destroy, :edit, :update] do
resources :comments, only: [:show, :create, :destroy, :edit, :update] do
member do
put '/upvote' => 'comments#upvote'
end
end
member do
put '/upvote' => 'posts#upvote'
end
end
end
post_controller.rb
def upvote
#post = Post.friendly.find(params[:id])
#post.increment!(:upvotes)
redirect_to root_path
end
comments_controller.rb
def upvote
#post = Post.friendly.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.increment!(:upvotes)
redirect_to #post
end
post index.html.erb
<%= link_to "like", upvote_post_path(post), method: :put, style: "color: white;" %>
What's missing here that I'm not seeing?

How to create an admin user with Ruby on Rails

I'm new to ruby on rails, and so far, I have created the user login, signup, signout, but I wanna create an admin user, and I have no idea how to do this.
route.rb is:
Rails.application.routes.draw do
get 'courses/index'
get 'courses/new'
get 'courses/edit'
get 'courses/show'
get 'course/index'
get 'course/new'
get 'course/edit'
get 'course/show'
get 'sessions/signin'
get 'sessions/main'
get 'sessions/profile'
get 'sessions/setting'
get 'users/new'
get 'home/index'
resources :users, path_names: {new: "signup"} do
collection do
get "main", action: :new
end
end
resources :sessions, path_names: {new: "signin", destroy: "signout"} do
collection do
get :signin
get :main
get :profile
get :setting
end
end
resources :home, only: [], path: "" do
get :about
end
root 'home#index'
resources :courses, only: [:index, :new, :edit, :show]
#resources :course, only: [:index, :new, :edit, :show]
resources :courses
resources :course_groups
patch 'course_groups/:id/add_course', to: 'course_groups#add_course', as: 'course_group_add_course'
delete 'course_groups/:id/delete_course', to: 'course_groups#destory_course', as: 'course_group_destory_course'
resources :rules
patch 'rules/:id/add_group', to: 'rules#add_group', as: 'rule_add_course_group'
delete 'rules/:id/delete_group', to: 'rules#destroy_group', as: 'rule_destroy_course_group'
resources :requirements
patch 'requirements/:id/add_rule', to: 'requirements#add_rule', as: 'requirement_add_rules'
delete 'requirements/:id/delete_rule', to: 'requirements#destroy_rule', as: 'requirement_destroy_rules'
#resources :plans
resources :users do
resources :plans
end
patch 'users/:user_id/plans/:id/add_course', to: 'plans#add_course', as: 'plan_add_course'
delete 'users/:user_id/plans/:id/delete_course', to: 'plans#destory_course', as: 'plan_destory_course'
match '/about', to: 'home#about', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match ':controller(/:action(/:id))(.:format)', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/main', to: 'users#new', via: 'get'
#match '/profile', to: 'sessions#profile', via: 'get'
match '/setting', to: 'sessions#setting', via: 'get'
match '/editname', to: 'users#edit', via: 'get'
match '/show', to: 'users#show', via: 'get'
match '/profile', to: 'users#profile', via: 'get'
#match '/info', to: 'users#info', via: 'get'
#match '/changepass', to: 'users#edit', via: 'get'
end
and my users_controller.rb is:
class UsersController < ApplicationController
before_filter :check_if_signned_in, only: [:show, :edit, :update, :delete]
before_filter :signed_in_user, only: [:edit, :update]
before_filter :skip_password_attribute, only: :update
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to #user, notice: 'User was sucessfully created!'
else
render action: "new"
end
end
#if current user exits, then it can get back to the main page of user
def show
if current_user.nil?
#user = User.find(params[:id])
else
#user = User.find(current_user)
end
end
def edit
##user = User.find(params[:id])
##user = User.find(current_user)
#user = current_user
#user.save
#title = "Edit profile"
end
def update
#user = User.find(params[:id])
##user = User.find(current_user)
#if #user.update_attributes(user_params)
if #user.update_attributes(user_params)
flash[:success] = "Profile updated."
#sign_in #user_params
redirect_to #user
else
#title = "Edit profile"
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def signed_in_user
redirect_to signin_path, notice: "Please sign in." unless signed_in?
end
def edit_user
params.require(:user).permit(:name)
end
def skip_password_attribute
if params[:password].blank? && params[:password_confirmation].blank?
params.except!(:password, :password_confirmation)
end
end
end
the application_controller.rb is:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
#protect_from_forgery with: :exception
protect_from_forgery
#before_filter :session_expire
#before_filter :update_active_time
include SessionsHelper
def check_if_signned_in
deny_access unless signed_in?
end
#def update_active_time
# session[:expires_at] = default_expire
#end
def is_owner
current_user.id == params[:id]
end
#private
# def get_session_time_left
# expire_time = session[:expires_at] #|| default_expire
# a = expire_time
# b = Time.now
# #session_time_left = (a - b).do_i
##session_time_left = (expire_time - Time.now).do_i
# end
end
Anyone can teach me how to create an admin user please? When the admin user logins, it will go to another different page.
Thank you in advance!
Without being rude, your code really needs to be cleaned up.
Your routes alone are a mess - I think I remember giving you some code to help them the other day, and it appears you've used it! However, you've left the other routes in there still - which is likely going to cause big issues down the line
Routes
Firstly, you need to get your routes in order:
#config/routes.rb
resources :courses
resources :users, path_names: {new: "signup"} do
collection do
get "main", action: :new
end
end
resources :sessions, path_names: {new: "signin", destroy: "signout", index: "main", edit: "profile", update: "setting"}
resources :home, only: [], path: "" do
get :about
end
root 'home#index'
resources :courses, only: [:index, :new, :edit, :show]
resources :course_groups do
patch :add_course
delete :delete_course
end
resources :rules do
patch :add_group
delete :delete_group
end
resources :requirements do
patch :add_rule
delete :delete_rule
end
resources :users do
resources :plans do
patch :add_course
delete :delete_course
end
end
match '/about', to: 'home#about', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match ':controller(/:action(/:id))(.:format)', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/main', to: 'users#new', via: 'get'
match '/setting', to: 'sessions#setting', via: 'get'
match '/editname', to: 'users#edit', via: 'get'
Simply, everything in Rails is resource / object - orientated. This includes the routes, and you should therefore make sure that every route you have is constructed around a resource (that's why you can define routes as resources etc)
--
Admin
To create an admin user, there are several options available to you:
Have a separate admin model
Create an admin attribute in your User model
I would strongly recommend including an admin attribute in your User model - make it a boolean column like this:
#new migration
add_column :users, :admin, :boolean
This will allow you to call the following
#user = User.find params[:id]
#user.admin? #-> true / false
This will allow you to use several conditional statements in both the controllers & views of your application, to determine if the user had admin privileges or not

Routing Error in Topics

I am writing an application , which User can create Topics and others can make posts on that topic.
I am stuck with this error :
No route matches {:action=>"show", :controller=>"topics", :id=>nil}
my route.rb :
MyPedia2::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :topics, only: [:show, :create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
root to: 'static_pages#home'
match '/topics/:id', to: 'topics#show'
my rake route shows :
topics POST /topics(.:format) topics#create
topic GET /topics/:id(.:format) topics#show
DELETE /topics/:id(.:format) topics#destroy
root / static_pages#home
/topics/:id(.:format) topics#show
and my topics controller is:
# encoding: utf-8
class TopicsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def show
#topic = Topic.find_by_id(params[:id])
end
def create
#topic = current_user.topics.build(params[:topic])
if #topic.save
flash[:success] = "Konu oluşturuldu!"
redirect_to root_path
else
render 'static_pages/home'
end
end
def destroy
#topic.destroy
redirect_to root_path
end
private
def correct_user
#topic = current_user.topics.find_by_id(params[:id])
redirect_to root_path if #topic.nil?
end
end
Is there a fix for this ?
EDIT : I found that _topics.html.erb fails
I found what breakes the code :
<% for topic in #topics do %>
<li><%=link_to topic.title, topic_path(#topic) %></li>
<%= will_paginate #topics %>
<% end %>
topic_path(#topic] part is wrong. How can i make it to use id?
It's not working because your collection is '#topics', and each element is 'topic', not '#topic'. But you're close. Try this:
<li><%=link_to topic.title, topic_path(topic) %></li>
Try this:
<li><%=link_to topic.title, topic_path(:id => #topic.id) %></li>
I think your routes should probably read:
resources :sessions, :only => [:new, :create, :destroy]
resources :topics, :only => [:show, :create, :destroy]
After hours of thinking , now i can see my mistake. I used show method in my topics controller but i did not have show.html.erb in my views/topics.
If you want to show your topics you must use these methods:
1) in config/routes.rb use :
match '/topics/:id', to: 'topics#show'
2) in the model i used
belongs_to :user,:foreign_key => "user_id"
3) link as :
<li><%=link_to topic.title, **topic_path(topic)** %></li>
4) and prepare the template you mentioned in the route.
I hope this help anyone.

Resources