using ajax for acts_as_votable to avoid page reload - ruby-on-rails

I'm using acts_as_voteable for upvote/downvote on a tweets page which works fine. however it reloads the page when i do this which i want to avoid
<% #tweets.each do |tweet| %>
<div class="card">
<div class="card-description">
<h4><%= link_to tweet.user.username, user_path(tweet.user) %></h4>
<p class="tweet-content"><%= tweet.content %></p>
<p><%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %></p>
<%= link_to like_tweet_path(tweet), method: :put do %>
<p>Upvote <%= tweet.get_upvotes.size %>
<% end %>
<%= link_to dislike_tweet_path(tweet), method: :put do %>
Downvote <%= tweet.get_downvotes.size %></p>
<% end %>
</div>
</div>
<% end %>
class TweetsController < ApplicationController
before_action :authenticate_user!, :except => [:index]
def index
# #tweets = Tweet.all.order("created_at DESC")
#tweets = Tweet.paginate(page: params[:page], per_page: 7).order('created_at DESC')
#tweet = Tweet.new
#user = current_user
end
def show
#tweet = Tweet.find(params[:id])
end
def new
# #tweet = Tweet.new
end
def create
# #user = current_user
#user = User.find(params[:user_id])
#tweet = Tweet.new(tweet_params)
#tweet.user = #user
if #tweet.save
redirect_to user_tweets_path
end
end
def edit
#tweet = Tweet.find(params[:id])
end
def update
#tweet = Tweet.find(params[:id])
#tweet.update(tweet_params)
redirect_to tweets_path
end
def upvote
#tweet = Tweet.find(params[:id])
#tweet.upvote_by current_user
# redirect_to :tweets
if request.xhr?
head :ok
else
redirect_to tweets_path
end
end
def downvote
#tweet = Tweet.find(params[:id])
#tweet.downvote_by current_user
redirect_to :tweets
end
private
def tweet_params
params.require(:tweet).permit(:content)
end
end

You can use remote: true in the link_to tag.
For example:
You have <%= link_to like_tweet_path(tweet), method: :put do %>
You can have it this way <%= link_to like_tweet_path(tweet), method: :put, remote: true do %>
Then just handle the request with format.js

Related

undefined method `each' for nil:NilClass - help needed

I am teaching myself Ruby on Rails and trying to build a blog through a tutorial. I saw some of these answers, and it seems as though my syntax is right, but I'm getting the error in the title.
Here is my articles_controller code:
class ArticlesController < ApplicationController
before_action :set_article, only: [:edit, :update, :show, :destroy]
def index
#articles = Article.paginate(page: params[:page], per_page: 5)
end
def new
#article = Article.new
end
def edit
end
def create
#article = Article.new(article_params)
#article.user = User.first
if #article.save
flash[:success] = "Article was successfully created"
redirect_to article_path(#article)
else
render 'new'
end
end
def update
if #article.update(article_params)
flash[:success] = "Article was updated"
redirect_to article_path(#article)
else
flash[:danger] = "Article was not updated"
render 'edit'
end
end
def show
end
def destroy
#article.destroy
flash[:danger] = "Article was deleted"
redirect_to articles_path
end
private
def set_article
#article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:title, :description)
end
end
And here is my index.html.erb:
<h1 align="center">Listing all articles</h1>
<% #articles.each do |article| %>
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<div class="well well-lg">
<div class="article-title">
<%= link_to article.title, article_path(article) %>
</div>
<div class="article-body">
<%= truncate(article.description, length: 100) %>
</div>
<div class="article-meta-details">
<small>Created by: <%= article.user.username if article.user %>, <%= time_ago_in_words(article.created_at) %> ago, last updated: <%= time_ago_in_words(article.updated_at) %> ago</small>
</div>
<div class="article-actions">
<%= link_to "Edit", edit_article_path(article), class: "btn btn-xs btn-primary" %>
<%= link_to "Delete", article_path(article), method: :delete, data: { confirm: "Are you sure you want to delete this article?"}, class: "btn btn-xs btn-danger" %>
</div>
</div>
</div>
</div>
<% end %>
I would appreciate any help I can get. Thanks.
I think your syntax in the index method is wrong.
#articles = Article.paginate(page: params[:page], per_page: 5)
Should be
#articles = Article.all.paginate(page: params[:page], per_page: 5)

using acts as followable to only display tweets from people that a user follows

currently on my twitter clone, every tweet from every user is displayed on the index page, but i want to only display the tweets from the people that a user follows, which a user can do on another users show page. im trying to use acts as followable but im not sure how to go about it, mainly the tweets index controller and the user show view. what i have so far is below, most of which i found online, thanks. let me know if any more info needed.
<h1 class="profile-title text-primary"><%= #user.username %> </h1>
<div class="avatar-show">
<%= cl_image_tag #user.photo, height: 200, width: 200, crop: :fill %>
</div>
<% if current_user.following(#user) %>
<%= button_to "Following", {action: "unfollow", id: #user.id}, method: "post", class: "btn btn-secondary btn_unfollow", remote: true %>
<% elsif current_user != #user %>
<%= button_to "Follow", {action: "follow", id: #user.id}, method: "post", class: "btn btn-primary btn_follow", remote: true %>
<% end %>
<div id="tweets">
<% #tweets.each do |tweet| %>
<div id="tweet-<%= tweet.id %>" class="card cardspace">
<p class="photo"><%= cl_image_tag tweet.user.photo, height: 50, width: 50, crop: :fill %></p>
<h4 class = "username"><%= link_to tweet.user.username, user_path(tweet.user) %></h4>
<p class="tweet-content"><%= tweet.content %></p>
<p class="date"><%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %></p>
<p class = "icons">Upvotes <%= tweet.get_upvotes.size %> | Downvotes <%= tweet.get_downvotes.size %></p>
<% end %>
</div>
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#tweets = #user.tweets.order('created_at DESC')
authorize #user
end
def follow
#user = User.find(params[:id])
current_user.follow(#user)
redirect to user_path(#user)
# #current_user.follow(#user)
# #follow = Follow.find_by(follower: #current_user, followable: #user)
# respond_to :js
end
def unfollow
#user = User.find(params[:id])
current_user.stop_following(#user)
redirect_to user_path(#user)
# #current_user.stop_following(#user)
# respond_to :js
end
end
class TweetsController < ApplicationController
# before_action :authenticate_user!, :except => [:index]
require "open-uri"
def index
# #tweets = Tweet.all.order("created_at DESC")
# #tweets = policy_scope(Tweet).paginate(page: params[:page], per_page: 7).order('created_at DESC')
# authorize #tweets
if params[:query].present?
#tweets = policy_scope(Tweet).global_search(params[:query]).paginate(page: params[:page], per_page: 5).order('created_at DESC')
else
#tweets = policy_scope(Tweet).paginate(page: params[:page], per_page: 5).order('created_at DESC')
end
#tweet = Tweet.new
#user = current_user
url = 'https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=**************************'
article_serialized = open(url).read
#articles = JSON.parse(article_serialized)
#users = User.all.limit(5)
end
forgot the ? after follower part

No route matches {:action=>"index", :controller=>"features", :grounddetail_id=>nil} missing required keys: [:grounddetail_id]

I wanna fetch feature index page without going through grounddetail id. When i try to create a link in homepage i always get this error:
No route matches {:action=>"index", :controller=>"features", :grounddetail_id=>nil} missing required keys: [:grounddetail_id]
<%= link_to "Account Setting", edit_admin_registration_path %> |
<%= link_to "Log Out", destroy_admin_session_path, method: :delete %> |
<%= link_to "Featured Ground", grounddetail_features_path(#grounddetail) %> # Feature Link Where I get error
grounddetail controller looks :
class GrounddetailsController < ApplicationController
before_action :find_ground, only: [:show, :edit, :destroy, :update]
def index
#grounddetails = Grounddetail.all.order('created_at DESC')
#grounddetail = Grounddetail.first # With this code it run but with grounddetail id.
end
def new
#grounddetail = Grounddetail.new
end
def edit
end
def show
end
def create
#grounddetail = Grounddetail.new(ground_params)
if #grounddetail.save
redirect_to #grounddetail
else
render 'new'
end
end
def update
if #grounddetail.update(ground_params)
redirect_to #grounddetail
else
render 'edit'
end
end
def destroy
#grounddetail.destroy
redirect_to root_path
end
private
def find_ground
#grounddetail = Grounddetail.find(params[:id])
end
def ground_params
params.require(:grounddetail).permit(:name, :working_hours, :end_time, :address, :contact_no, :email, :number_of_grounds, :description, :featured_ground)
end
end
feature controller looks like :
class FeaturesController < ApplicationController
before_action :set_ground
def index
#grounddetails = Grounddetail.where(featured_ground: true).order("created_at DESC")
#features = Feature.includes(:grounddetail).where(grounddetail_id: #grounddetail.id)
end
def new
#feature = Feature.new
end
def show
#feature = Feature.find(params[:id])
end
def edit
#feature = Feature.find(params[:id])
end
def create
#feature = Feature.create(feature_params)
#feature.grounddetail_id = #grounddetail.id
if #feature.save
redirect_to grounddetail_features_path(#grounddetail)
else
render 'new'
end
end
def update
#feature = Feature.find(params[:id])
if #feature.update(feature_params)
redirect_to grounddetail_features_path(#grounddetail)
else
render 'edit'
end
end
def destroy
#feature = Feature.find(params[:id])
#feature.destroy
redirect_to grounddetail_features_path(#grounddetail)
end
private
def set_ground
#grounddetail = Grounddetail.find(params[:grounddetail_id])
end
def feature_params
params.require(:feature).permit(:featuring_start_time, :featuring_end_at)
end
end
Models:
grounddetail model:
has_many :features
feature model:
belongs_to :grounddetail
index.html.erb #feature index page
<h2>Featured Ground</h2>
<% #grounddetails.each do |grounddetail| %>
Name: <%= link_to grounddetail.name, grounddetail %><br>
Address: <%= grounddetail.address %><br>
Opening Hours: From<%= grounddetail.working_hours.strftime("%l:%M %P") %> To <%= grounddetail.end_time.strftime("%l:%M %P") %><br>
Featured : <%= check_box "Grounddetail", "Featured Ground", {checked: grounddetail.featured_ground, disabled: true} %><br>
<% if (grounddetail.featured_ground = true) && (grounddetail_id = #grounddetail.id) %>
<% #features.each do |feature| %>
Featuring Start Time : <%= feature.featuring_start_time.strftime('%e %b %Y %l:%M %P') %><br>
<%# feature.start_date_cannot_be_in_the_past %>
Featuring End At : <%= feature.featuring_end_at.strftime('%e %b %Y %l:%M %P') %><br>
<% end %>
<% end %>
<%= link_to "Add Featuring Time", new_grounddetail_feature_path(#grounddetail) %><br><br>
<% end %>
routes.rb
resources :grounddetails do
resources :features
end
Sorry for the mess up..

NoMethodError in MembersController#index undefined method `total_pages' for #<Micropost::ActiveRecord_Associations_CollectionProxy:0x007ffc26104288>

The error output is:
NoMethodError in MembersController#index
undefined method `total_pages' for #<Micropost::ActiveRecord_Associations_CollectionProxy:0x007ffc26104288>
Application trace is:
app/views/shared/_feed.html.erb:5:in `_app_views_shared__feed_html_erb__933429040368905157_70360748756160'
app/views/members/index.html.erb:4:in `_app_views_members_index_html_erb__2919315027143638402_70360970104820'
Update:
Source near error:
arel.public_send(method, *args, &block)
else
super # marked red
end
end
end
Additional info:
app/views/members/index.html.erb renders two partials using another controller, microposts_controller. So I'll show contents of both controllers and of the two partials.
# app/views/members/index.html.erb
<%= render 'shared/micropost_form', :locals => { :micropost => #micropost } %>
<%= render 'shared/feed', :locals => { :feed_items => #feed_items } %>
MembersController
class MembersController < ApplicationController
def index
#micropost = current_user.microposts.build
#feed_items = current_user.microposts
end
end
micropost_controller.rb
# controllers/micropost_controller.rb
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to '/members'
else
#feed_items = []
render '/members'
end
end
def destroy
#micropost.destroy
flash[:success] = "Micropost deleted"
redirect_to request.referrer || '/members'
end
private
def micropost_params
params.require(:micropost).permit(:content, :picture)
end
def correct_user
#micropost = current_user.microposts.find_by(id: params[:id])
redirect_to '/members' if #micropost.nil?
end
end
_micropost_form.html.erb
# shared/_micropost_form.html.erb
<%= form_for(#micropost, html: { multipart: true }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost (420 chars max)..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<span class="picture">
<%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
</span>
<% end %>
<script type="text/javascript">
$('#micropost_picture').bind('change', function() {
size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert('Maximum file size is 5MB. Please choose a smaller file.');
}
});
</script>
_feed.html.erb
# shared/_feed.html.erb
<% if #feed_items.any? %>
<ol class="microposts">
<%= render #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
You want to paginate your records using will_paginate in view, but you didn't paginate them in your controller:
def index
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end

Nested Routes can not index all

I have nested routes as follows;
resources :boats, except: :destroy do
resources :pictures
end
So user can upload picture and everything works fine. But picture/index.html.erb. I can not see all the pictures. It returns nil. But I can see pictures in the database. Probably because I try to retrieve wrong parameter.
When I take out the if statement <% if #pictures.present? %> it throws and error;
NoMethodError in PicturesController#create
undefined method `each' for nil:NilClass
<% #pictures.each do |pic| %>
Here is #index view;
<div class="container">
<h1>Pictures#index!</h1>
<p>Find me in app/views/pictures/index.html.erb</p>
<% if #pictures.present? %> <!-- Returns nil-->
<% #pictures.each do |pic| %>
</br>
<%= pic.name %>
<%= image_tag pic.image_url(:thumb).to_s %>
<%= link_to "edit", edit_boat_picture_path(#boat, #picture) %> |
<td><%= link_to 'Destroy', [#boat, #picture], confirm: 'Are you sure?', method: :delete %></td> |
</br>
<% end %>
<% end %>
<%= link_to "edit", edit_boat_picture_path(#boat, #picture) %> |
</br>
</br>
<%= link_to "add", new_boat_picture_path(#boat, #picture) %>
</div>
So here, picture.present returns always nil, so I can not display any images.
Here is pictures controller;
class PicturesController < ApplicationController
before_action :logged_in_user
before_filter :load_parent
def index
#pictures = #boat.pictures.all
end
def new
#picture = #boat.pictures.new
end
def show
#picture = #boat.pictures.find(params[:id])
end
def create
#picture = #boat.pictures.new(picture_params)
if #picture.save
#flash[:success] = "Continue from here"
render 'index'
#redirect_to boat_path(#boat)
else
render 'new'
end
end
def edit
#picture = Picture.find(params[:id])
end
def update
#picture = #boat.pictures.find(params[:id])
if #picture.update_attributes(picture_params)
flash[:notice] = "Successfully updated picture."
render 'index'
else
render 'edit'
end
end
def destroy
#picture = #boat.pictures.find(params[:id])
#picture.destroy
flash[:notice] = "Successfully destroyed picture."
redirect_to boat_path(#boat)
end
private
def picture_params
params.require(:picture).permit(:name, :image)
end
def load_parent
#boat = Boat.find(params[:boat_id])
end
end
EDIT 1:
Log;
{"utf8"=>"✓", "authenticity_token"=>"i3FW1zbhoGW2vavipN9NJ2Fvi9R1Lk/CKDsAttuqHWb8rFNmJgXpjE2D25oAqJ3xp9BXAnd0kDmrdIxhn1Qrpw==", "picture"=>{"name"=>"", "image"=>#<ActionDispatch::Http::UploadedFile:0x007fb4a5f50f30 #tempfile=#<Tempfile:/var/folders/w0/703ccggs56l3hrc79h3rdylm0000gn/T/RackMultipart20150423-5028-1rbpgnj.jpg>, #original_filename="imgres-4.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"picture[image]\"; filename=\"imgres-4.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Done", "controller"=>"pictures", "action"=>"create", "boat_id"=>"114"}
EDIT 2:
if I add #pictures = #boat.pictures.all to create that is fine, but all pics have its own destroy button.And when I look at them all shows the same address, so clicking to destroy, destroys all of them;
All of the destroy ids are the same. I though index action lists all and destroy erases individually. This case is same for edit action too
EDIT 3:
#boats controller
class BoatsController < ApplicationController
before_action :logged_in_user, only: [:new, :show, :edit, :update]
def new
#boat = Boat.new
end
def create
#boat = current_user.boats.new(boat_params) if logged_in?
if #boat.save
#flash[:success] = "Continue from here"
render 'edit'
else
render 'new'
end
end
def show
#boat = Boat.find(params[:id])
end
def edit
#boat = Boat.find(params[:id])
end
def update
#boat = Boat.find(params[:id])
if #boat.update_attributes(boat_params)
flash[:success] = "The Boat Saved"
redirect_to root_path
else
render 'edit'
end
end
def update_years
# updates year and model based on brand selected
brand = Brand.find_by_name(params[:brand_name])
# map to name and id for use in our options_for_select
#years = brand.years.map{|a| [a.name, a.name]}.insert(0, "Select a Year") #use a.name here instead of a.id
#models = brand.models.map{|s| [s.name, s.name]}.insert(0, "Select a Model")#use s.name here instead of s.id
end
def update_models
# updates model based on year selected
year = Year.find_by_name(params[:year_name])
#models = year.models.map{|s| [s.name, s.name]}.insert(0, "Select a Model") #use s.name here instead of s.id
end
private
def boat_params
params.require(:boat).permit(:brand, :year, :model, :captained, :boat_type, :daily_price, :boat_length, :listing_tagline, :listing_description, :boat_category, :hull_material, :mast_material)
end
end
There is no #pictures in your create action.
You can try:
def create
#picture = #boat.pictures.new(picture_params)
if #picture.save
#flash[:success] = "Continue from here"
#pictures = #boat.pictures.all
render 'index'
#redirect_to boat_path(#boat)
else
render 'new'
end
end
For buttons:
<% #pictures.each do |pic| %>
</br>
<%= pic.name %>
<%= image_tag pic.image_url(:thumb).to_s %>
<%= link_to "edit", edit_boat_picture_path(#boat, pic) %> |
<td><%= link_to 'Destroy', boat_picture_path(#boat, pic), confirm: 'Are you sure?', method: :delete %></td> |
</br>
<% end %>

Resources