Using Act as Votable with Paginate, Undefined method - ruby-on-rails

I am trying to use paginate with act as votable but I'm getting a few errors. My favorites method is to display a page that shows only items that the user upvoted.
def favorites
#title = "Favorites"
#user = User.find(params[:id])
#favorites = #user.find_up_voted_items
render 'show_favorites'
end
This shows all upvoted via act as votable items. However, when I try to use paginate on the page by editing the # favorites with this:
#favorites = #user.find_up_voted_items.paginate(page: params[:page])
I get an undefined method for paginate.
I am already using paginate for other pages:
def index
#users = User.paginate(page: params[:page], per_page: 30)
end
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.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
What am I missing with my favorites method?

Related

undefined method `errors' for nil:NilClass for displaying Rails validation errors

I am getting an undefined method 'errors' for nil:NilClass error when attempting to display errors in a view from validations in Rails. I followed this example Rails validation error messages displays the error messages and array, taking its answer into account.
An example of a validation I have in the user model is:
validates_length_of :dog_name, minimum: 0, maximum: 30, message: 'cannot have more than 30 characters'
View code
<% if #user.errors.any? %>
<div id="errorExplanation">
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Users Controller
class UsersController < ApplicationController
#before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
#:following, :followers]
before_filter :requireLogin
#before_action :requireDog
def requireLogin
if session[:user_id] == nil
redirect_to "/"
end
end
def requireDog
#user = User.find(session[:user_id])
if(#user.dog_name == "Empty")
redirect_to "users/new/"
end
end
def index
#users = User.all
end
def show
#user = User.find(params[:id])
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def new
#user = User.new
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def update
#user = User.find(params[:id])
if #user.update_attributes(profile_params)
redirect_to action: "show"
# Handle a successful update.
else
render 'edit'
end
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.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
def going
#title = "Going"
#user = User.find(params[:id])
#users = #user.going.paginate(page: params[:page])
render 'show_gather'
end
def create
#user = User.new(profile_params)
if #user.save
redirect_to '/users'
else
render 'new'
end
end
private
def profile_params
params.require(:user).permit(:dog_name, :photo, :dog_breed, :dog_gender, :dog_age)
end
end
In other examples the user model/controller did not need to be further modified. The user does indeed exist. Am I missing something in the model or controller?
Firstly, you'd be better switching to the new validates methods:
#app/models/user.rb
class User < ActiveRecord::Base
validates :dog_name, length: { in: 0..30, message: 'cannot have more than 30 characters'}
end
-
Secondly, instead of setting #title each time - why don't you just use action_name?
Each time you load an action, the controller_name and action_name variables are set by default, to be used either in your controller or views. Why not just use the action_name variable in your view?
#app/views/layouts/application.html.erb
<title><%= action_name if controller_name == "Users" %></title>
To answer your question, the error is caused because you're trying to invoke a method on a non-existent variable:
for nil:NilClass
Ruby has a funny way of posting exceptions for undeclared variables -- instead of outwardly saying the variable doesn't exist, it invokes it under the NilClass class.
As a developer, you're then expected to read the message of undeclared method and surmise that it's the variable which isn't set...
The fix for your problem is therefore to find why the variable is not set:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new profile_params
redirect_to users_path if #user.save
end
end
The above should give you the ability to save the user, else it will re-render the new action (and show the error).
I think the problem you have is that you're explicitly loading the new action on validation problems, which will prevent it appending the required data.

How to prevent full image from displaying

I am using Carrierwave for my images. I added a following section to my app, however in the results it is showing the full size image. How can I modify it so that it uses the thumbnail version of the image :profile?
show.follow.html.erb:
<%= render #users %>
Users controller:
def show
#user = User.find_by(username: params[:id])
#similar_users = #user.similar.shuffle.first(8)
respond_to do |format|
format.html { render layout: 'new_application' }
end
end
def index
#user = current_user
#search = Search.new
#users = #user.present? ? User.where('id != ?',#user.id) : User.all
render layout: 'new_application'
end
def follow
#title = "Following"
#user = User.find_by(username: params[:id])
friend = User.find_by(username: params[:id])
current_user.follow! friend unless current_user.following? friend
#users = #user.followed_users(page: params[:page])
render 'show_follow', layout: 'new_application'
end
To post the profile version of your uploaded image use this in your view code.
<%= image_tag #user.image_url(:profile) %>
You can define the custom thumb size and normal size
as given below
profile :resize_to_fit => [800, 800]
version :thumb do
profile :resize_to_fill => [200,200]
end
You can resize using css to if you want

Error: undefined method `[]' for nil:Class

The error says that there is an: "undefined method []"
My questions is simply how to solve the error
My user.rb file where the error says the error is and where i think the error is
def your_questions(params)
questions.paginate(page: params[:page], order: 'created_at DESC', per_page: 3)
end
My questions controller a.k.a app/controllers/questions_controller.rb
class QuestionsController < ApplicationController
before_filter :auth, only: [:create, :your_questions, :edit, :update]
# def index
# #question = Question.new
# #questions = Question.unsolved(params)
# end
def self.unsolved(params)
order('created_at DESC').where(solved: false).paginate(page: params[:page],per_page: 3)
end
def create
#question = current_user.questions.build(params[:question])
if #question.save
flash[:success] = 'Your question has been posted!'
redirect_to #question
else
#questions = Question.unsolved(params)
render 'index'
end
end
def new
#question = Question.new
end
def show
# raise FOO
puts params
#question = Question.find(params[:id])
#answer = Answer.new
end
def your_questions
#questions = current_user.your_questions(params[:id])
end
def edit
#question = current_user.questions.find(params[:id])
end
def update
#question = current_user.questions.find(params[:id])
if #question.update_attributes(params[:question])
flash[:success] = 'Your question has been updated!'
redirect_to #question
else
render 'edit'
end
end
def search
#questions = Question.search(params)
end
end
You pass params[:id] into your_questions method, while it expects params. What I'd do is:
def your_questions(page)
questions.paginate(page: page, order: 'created_at DESC', per_page: 3)
end
It's because this method doesn't need to know about your whole params hash. Then you call this method simply with params[:page]:
current_user.your_questions(params[:page])
Your are passing only id when you have called your_questions in your controller. However you are trying to fetch a key :page from id (string)
Just Do following change in your controller's your_questions
#questions = current_user.your_questions(params[:page])
In your user.rb just use page instead of params[:page]
def your_questions(page)
questions.paginate(page: page, order: 'created_at DESC', per_page: 3)
end

Couldn't find User with id=UserNameHere when clicking followers/following

I am trying to implement Michael Hartl's follow feature into my application, so I've had to make some little changes as I've gone along.
Problem is when I click the followers/following button. I get the error
Here is my UsersController
class UsersController < ApplicationController
def show
#user = User.find_by_username(params[:id])
end
def user_params
params.require(:user).permit(:avatar)
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.followed_users.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
end
If you need more information to get help me solve this problem, do not hesitate to let me know.
Since you are passing the name of the user instead of the id, you should use:
User.find_by(name: "user_name")

Best way to avoid duplication of related objects in the actions new and create

To create an user in the example bellow I have to load #projects and #companies as they are mandatory for creating user.
class UsersController < ApplicationController
def new
#user = User.new
# duplication here
#projects = Project.all
#companies = Company.all
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
# and here
#projects = Project.all
#companies = Company.all
render :action => "new"
end
end
end
I have to load these dependencies in both (duplication) cases, for the new and create action when the user is invalid.
I can refactor by encapsulating these dependencies in a method load_user_dependencies.
class UsersController < ApplicationController
def new
#user = User.new
load_user_dependencies
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
load_user_dependencies
render :action => "new"
end
end
private
def load_user_dependencies
#projects = Project.all
#companies = Company.all
end
end
Or by adding them as a helper_methods.
class UsersController < ApplicationController
helper_method :projects, :companies
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
def projects
#projects ||= Project.all
end
def companies
#companies ||= Company.all
end
end
I can also create a View Object
class UserView
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = User.new
#user_view = UserView.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to #user
else
#user_view = UserView.new
render :action => "new"
end
end
end
Other option is to use a Presenter
class UserPresenter < SimpleDelegator
def products
#products ||= Product.all
end
def companies
#companies ||= Company.all
end
end
class UsersController < ApplicationController
def new
#user = UserPresenter.new User.new
end
def create
#user = UserPresenter.new User.new(params[:user])
if #user.save
redirect_to #user
else
render :action => "new"
end
end
end
How do you guys usually deal with scenario?
It's a bit of a personal taste issue, but in our projects if it's suitable we do it in the view, and if it's complex we do it in a before_filter.
View - suitable if it's something that doesn't have any logic, no need to create a variable for this. Super useful if your form is contained in a partial as it's only done once so easily maintained.
<%= form.select :project_id, Project.all, :id, :name %>
If it's something that can change depending on any factors then a before_filter in controller:
MyController
before_filter :find_projects, :except => [:destroy, :some_method] # Will load the values but not for the destroy or some_method actions
def find_projects
#projects = Project.where(:some conditions => true)
end

Resources