using acts as followable gem on tweets - ruby-on-rails

im trying to add acts a follower to my app so a user can follow other users and on the tweets index page only display the current users tweets and the tweets of the people they are following. i currently have a "follow" button on the user show page, but i would expect it to change into "following" on a click, but nothing changes. ive looked at other questions and documentation, but no luck. thank you.
Users show view:
<% if current_user.following?(#user) %>
<%= button_to "Following", {action: "unfollow", id: #user.id}, method: "post", class: "btn btn-secondary btn_unfollow", remote: true %>
<% else current_user != #user %>
<%= button_to "Follow", {action: "follow", id: #user.id}, method: "post", class: "btn btn-primary btn_follow", remote: true %>
<% end %>
Users Controller:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#tweets = #user.tweets.order('created_at DESC')
authorize #user
end
def follow
#current_user.follow(#user)
#follow = Follow.find_by(follower: #current_user, followable: #user)
# #user = User.find(params[:id])
# current_user.follow(#user)
# current_user.follow(#user)
# redirect to user_path(#user)
# respond_to :js
end
def unfollow
#user = User.find(params[:id])
#current_user.stop_following(#user)
# current_user.stop_following(#user)
# redirect_to user_path(#user)
# respond_to :js
end
end
Routes:
resources :users do
member do
get :follow
get :unfollow
end
end

You're adding an ajax response by doing remote:true. You need to add a follow.js.erb and an unfollow.js.erb view that will re-render your partial.

Try and remove the remote: true part from your view:
<% if current_user.following?(#user) %>
<%= button_to "Following", {action: "unfollow", id: #user.id}, method: "post", class: "btn btn-secondary btn_unfollow" %>
<% elsif current_user != #user %>
<%= button_to "Follow", {action: "follow", id: #user.id}, method: "post", class: "btn btn-primary btn_follow" %>
<% end %>
Add post method for both follow and unfollow actions on routes.rb:
resources :users do
member do
post :follow
post :unfollow
end
end
and try current_user instead of #current_user in your UsersController if you're using Devise as a authentication solution:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#tweets = #user.tweets.order('created_at DESC')
authorize #user
end
def follow
current_user.follow(#user)
#follow = Follow.find_by(follower: current_user, followable: #user)
# #user = User.find(params[:id])
# current_user.follow(#user)
# current_user.follow(#user)
# redirect to user_path(#user)
# respond_to :js
end
def unfollow
#user = User.find(params[:id])
current_user.stop_following(#user)
# current_user.stop_following(#user)
# redirect_to user_path(#user)
# respond_to :js
end
end

Related

Add checkbox to edit bool value of user in devise in Rails

I have created a user using devise gem. I have added a column admin to the User table which has boolean value. Now what I need is to add checkboxes after every user in users_page and give a feature so that when the checkbox is checked the value of admin column changes to true. How can I add the functionality?
users_controller.rb
class UsersController < ApplicationController
def users_page
#users = User.all
end
def change_user_role
#user = User.find(params[:id])
format.html { redirect_to users, notice: 'Role changed successfully' }
end
def destroy
#user = User.find(params[:id])
#user.destroy
if #user.destroy
redirect_to root_url, notice: "User deleted."
end
end
end
users_page.html.erb
<h1>Users</h1>
<% #users.each do |user| %>
<h5><%= user.email %></h5>
<%= user.admin %>
<%= form_tag({controller: "users", action: "change_user_role"}, method: "get") do %>
<%= check_box_tag(:admin, checked: false) %>
<p><%= submit_tag 'Submit Answer' %></p>
<% end %>
<br>
<%= link_to "Destroy", admin_destroy_user_path(user), method: :delete, data: { confirm: "You sure?" } %>
<% end %>
routes.rb
Rails.application.routes.draw do
root to: 'pages#home'
get 'users/users_page'
devise_for :users
match 'users/:id' => 'users#destroy', :via => :delete, :as => :admin_destroy_user
get 'users#change_user_role'
end
Here I should submit the value of the checkbox in users_page to change_user_role and update the value in db and redirect it to users_page. How can I do that?
First of all, change your get method to put in your routes.rb because you'll be updating the resource in database:
Rails.application.routes.draw do
root to: 'pages#home'
get 'users/users_page'
devise_for :users
match 'users/:id' => 'users#destroy', :via => :delete, :as => :admin_destroy_user
// it will require user id in your url
resources :users do
member do
put :change_user_role
end
end
end
More on routes here
Then change your view to something like this:
<h1>Users</h1>
<% #users.each do |user| %>
<h5><%= user.email %></h5>
<%= form_for(user, url: change_user_role_user_path(user)) do |f| %>
<%= f.check_box(:admin) %>
<p><%= f.submit 'Submit Answer' %></p>
<% end %>
<br>
<%= link_to "Destroy", admin_destroy_user_path(user), method: :delete, data: { confirm: "You sure?" } %>
<% end %>
More on forms here
Your controller should look something like this:
class UsersController < ApplicationController
def users_page
#users = User.all
end
def change_user_role
#user = User.find(params[:id])
// if user is updated successfully then redirect
if(#user.update_attributes(user_params)
format.html { redirect_to users, notice: 'Role changed successfully' }
end
end
def destroy
#user = User.find(params[:id])
if #user.destroy
redirect_to root_url, notice: "User deleted."
end
end
// new method added to allow specific attributes only and discarding other malicious attributes that user may send
def user_params
params.require(:user).permit(:admin)
end
end
More on parameters here

Rails: ActionController::InvalidAuthenticityToken

I'm currently working on a project involving users, likes, and posts. I have a like/unlike button that I finally got to work some of the time, but on certain user's profiles when I go to unlike a post, I get thrown this error, which says that it is coming from my destroy action in my likes controller:
ActionController::InvalidAuthenticityToken
I'm using devise, but don't know if that has to do with the cause of the issue.
Right now this is what I'm working with:
<h4>All of <%= #user.email %>'s posts:</h4>
<% #user.posts.order('created_at DESC').each do |post| %>
<li><%= post.content %></li>
<% unless current_user.likes.pluck(:post_id).include?(post.id) %>
<%= form_tag likes_path do %>
<%= hidden_field_tag 'post_id', post.id %>
<%= submit_tag "Like", :class => "like_button" %>
<% end %>
<% else %>
<% like = post.likes.where(user_id: current_user.id).first %>
<div class="unlike_button">
<%= form_tag like_path(like) do %>
<%= hidden_field_tag 'post_id', post.id %>
<%= button_to "Unlike", like_path(post), method: :delete %>
</div>
<% end %>
class LikesController < ApplicationController
def create
#post = Post.find(params[:post_id])
#like = Like.new(user_id: current_user.id, post_id: #post.id)
if #like.save
flash[:success] = "Post Liked!"
redirect_back(fallback_location: root_path)
else
flash[:notice] = "Couldn't like post"
redirect_back(fallback_location: root_path)
end
end
def destroy
#like = Like.find(params[:id])
#like.destroy
flash[:success] = "Post unliked"
redirect_back(fallback_location: root_path)
end
end
class PostsController < ApplicationController
def index
#posts = Post.all
#user = User.find(params[:user_id])
end
def new
#post = Post.new
#user = User.find(params[:user_id])
end
def create
#post = current_user.posts.build(post_params)
if #post.save
flash[:success] = "Posted!"
redirect_to user_path(current_user)
else
flash[:notice] = "Post could not be submitted"
redirect_to users_path
end
end
private
def post_params
params.require(:post).permit(:content)
end
end
There is a comment in application_controller.rb..
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
so ,you may try changing..
protect_from_forgery with: :exception
to this
protect_from_forgery with: :null_session
Hope it helps :)
I think I have figured it out.. At least have gotten it to work. I wasusing a form_for helper as well as button_to helper. I deleted the form_for helper and just stuck with
<%= button_to "Unlike", like_path(like), method: :delete %>
and it is now working
What helps me solve this problem is adding the Forward Slash in the URL
From:
= bootstrap_form_tag url: 'signup_with_phone' do |form|
To:
= bootstrap_form_tag url: '/signup_with_phone' do |form|

Rails: Image Uploading Site. Home page

class PhootosController < ApplicationController
before_action :logged_in_user
def index
#phootos = Phooto.all.sample(1)
end
def new
end
def show
#phooto = Phooto.find(params[:id])
end
def create
#phooto = current_user.phootos.build(phooto_params)
if #phooto.save
flash[:success] = "Photo created!"
redirect_to uploads_url
else
redirect_to root_url
end
end
def favorite
#phooto = Phooto.find params[:id]
if request.put?
current_user.favorites << #phooto
redirect_to :back, notice: 'You successfully favorited #{#phooto.name}'
elsif request.delete?
current_user.favorites.delete(#phooto)
redirect_to :back, notice: 'You successfully unfavorited #{#phooto.name}'
else
redirect_to :back, notice: 'Nothing happened.'
end
end
def feed
#favorites = current_user.favorites.all
end
def uploaded
#phootos = current_user.phootos.all
end
private
def phooto_params
params.require(:phooto).permit(:picture)
end
end
show.html.erb
<p><strong>Picture:</strong></p>
<%= image_tag(#phooto.picture) %>
<%= link_to("< Previous", #phooto.previous) if #phooto.previous %>
<%= link_to("Next >", #phooto.next) if #phooto.next %>
<% if current_user %>
<%= link_to "favorite", favorite_phooto_path(#phooto), method: :put %>
<%= link_to "unfavorite", favorite_phooto_path(#phooto), method: :delete %>
<% end %>
www.example.com/photos/1
Professional websites have the homepage www.example.com load with a photo already displayed. Then when you click next/previous, you are routed to www.example.com/photos/#{photo_id}
How do I get my website to do this? I also want it setup so that each day a different random photo is displayed in the homepage.
If you want to show a random photo on the homepage, you need the following:
#config/routes.rb
resources :photos, only: [:index, :show]
#app/controllers/photos_controller.rb
class PhotosController < ApplicationController
def index
random = ActiveRecord::Base.connection.adapter_name == 'MySQL' ? "RAND()" : "RANDOM()"
#phooto = Photo.order(random).first
end
def show
#phooto = Photo.find params[:id]
end
end
Refs:
https://stackoverflow.com/a/2536743/1143732 (adapter)
https://stackoverflow.com/a/25577054/1143732 (random)
--
This will allow you to populate the #phooto variable in both the index and show actions;
#app/views/photos/index.html.erb
<%= render #phooto %>
#app/views/photos/show.html.erb
<%= render #phooto %>
#app/views/photos/_photo.html.erb
<p><strong>Picture:</strong></p>
<%= image_tag(photo.picture) %>
<%= link_to("< Previous", photo.previous) if #phooto.previous %>
<%= link_to("Next >", photo.next) if #phooto.next %>
<% if current_user %>
<%= link_to "favorite", favorite_phooto_path(phooto), method: :put %>
<%= link_to "unfavorite", favorite_phooto_path(phooto), method: :delete %>
<% end %>
You'll be able to work out the rest.
In regards rendering a new random image each day, you'll have to store the "random" value each time the day changes.
This would be best done with a cron job, invoking a rake task:
#lib/tasks/new_random.rb
namespace :random do
task :generate => :environment do
# save random for the day (maybe in a model or redis)
end
end

Rails - Updating and deleting content?

EDIT: I managed to delete! i had to define teh instance variable #movies = Movie.find(params[:id]) to the delete method in the controller.
I still can't update though. I get "param is missing or the value is empty: movie"
I forgot to add my contrller! sorry!
I'm trying to replicate one of my in class exercises into another app, for practice.
The idea is to be able to add new movies into a database, and get the option to update their info, and delete them as well. I can add new content, but I can't update them or delete them.
Appreciate any inputs I can get.
Routes.rb
Rails.application.routes.draw do
root "movies#index"
get "/movies", to: "movies#index"
get "/movies/new", to: "movies#new", as: "new_movie"
get '/movies/:id', to: "movies#movie_page", as: "movie_page"
post "/movies", to: "movies#add"
get "/movies/:id/edit", to: "movies#edit", as: "movie_edit"
put "/movies/:id", to: "movies#update"
patch "/movies/:id", to: "movies#update", as: "update_movie"
delete "/movies/:id", to: "movies#delete", as: "delete_movie"
end
Controller
class MoviesController < ApplicationController
def index
#movies = Movie.all
end
def movie_page
#movies = Movie.find(params[:id])
end
def new
#movies = Movie.new
end
def add
#movies = Movie.create(movie_params)
redirect_to movies_path
end
def edit
#movies = Movie.find(params[:id])
end
def update
#movies.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
def delete
#movies = Movie.find(params[:id])
#movies.destroy
# flash[:notice] = "Shirt was deleted."
redirect_to root_path, notice: "Shirt was deleted."
end
def movie_params
params.require(:movie).permit(:title, :description, :year_released)
end
# def set_movie
# #movies = Movie.find(params[:id])
# end
end
Form partial
<%= form_for #movies do |m| %>
<p>
<%= m.label :title %><br>
<%= m.text_field :title %>
</p>
<p>
<%= m.label :description %><br>
<%= m.text_field :description %>
</p>
<p>
<%= m.label :year_released %><br>
<%= m.text_field :year_released %>
</p>
<p>
<%= m.submit %>
</p>
<% end %>
Movie page html (individual movies, labeled by IDs)**I can't update or Delete, no route matches Delete.
When I press Update - I get param is missing or the value is empty: movie
<h1><%= #movies.title %></h1>
<h2>Released on : <%= #movies.year_released %> </h2>
<p> <%= #movies.description %> </p>
<%= link_to "Update", movie_edit_path(#movies) %>
<%= link_to "Delete", movies_path, method: :delete %
Edit page *I cant access this link. the form is the problem
<h1>Edit <%= #movies.title %> Info </h1>
<%= render "form" %>
<%= link_to "Cancel Edit", movie_edit_path(#movies) %>
Many thanks guys
def update
#movie = Move.find(params[:id])
#movie.update(movie_params)
redirect_to movie_path(#movie)
end
on your routes. all you need is resources :movies
you are getting param is empty because you have to pass in the id of the movie to update.
The major issue is that you do not load the variable #movies from the DB before you use it.
def update
#movies.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
def update
#movies.find(params[:id])
#movie.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
Aside from that you have tons of duplication and quite a few idiosyncrasies.
Rails uses these naming conventions for actions:
index
show (not movie_page)
new
create (not add)
edit
update
destroy (not delete)
You should follow them unless you have a damn good reason not to.
class MoviesController < ApplicationController
# cuts the duplication
before_filter :set_movie, except: [:new, :index]
def index
#movies = Movie.all
end
# GET /movies/:id
def show
end
# GET /movies/new
def new
#movie = Movie.new
end
# POST /movies
def create
#movie = Movie.create(movie_params)
redirect_to movies_path
end
# GET /movies/edit
def edit
end
# PUT|PATCH /movies/:id
def update
#movie.update(movie_params)
redirect_to #movie, notice: "Shirt was updated."
end
# DELETE /movies/:id
def destroy
#movie.destroy
redirect_to action: :index
end
private
def movie_params
params.require(:movie).permit(:title, :description, :year_released)
end
def set_movie
# Use the singular form when naming a variable with a single record
# failure to do so may result in tarring and feathering
#movie = Movie.find(params[:id])
end
end

Ruby on Rails - show_user_path NoMethodError in Users#show

I am a begginer in Rails, im following code from a book and i am trying stuff to see if it breaks/works, anyway heres my UserControllers classUserController
class UsersController < ApplicationController
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def show
#user = User.find(params[:id])
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user, :notice => 'Cadastro realizado'
else
render :new
end
end
end
And heres my show.html.erb
<p id="notice"><%=notice%></p>
<h2>Perfil: <%=#user.full_name %></h2>
<ul>
<li>Localização: <%= #user.location %> </li>
<li>Bio: <%= #user.bio %></li>
</ul>
<%= link_to 'Editar Perfil', edit_user_path(#user) %>
<%= link_to 'Mostrar Perfil', show_user_path(#user) %>
My problem is in the last line, when i try to acess this page i get a NomethodError,i am trying to understand why, why can i just change that to #user and the page works?
Try:
<%= link_to 'Mostrar Perfil', user_path(#user) %>
or even just
<%= link_to 'Mostrar Perfil', #user %>
In order to see how to name the routes, open a console and run
rake routes

Resources