ERROR - Couldn't find User with 'id'=2 - unable to solve - ruby-on-rails

im using rails to make a basic chair selling website. At the moment someone can post a new chair and people can look at each individual show page. However im having issues with the show page when trying to display the email of who posted the chair.
If i click on the first chair, it works fine, however if i click on the other it says 'Couldn't find User with 'id'=2'. I have made all the chairs under 1 user.
thanks. let me know if you need anymore info.
class ChairsController < ApplicationController
def index
#chairs = Chair.all
end
def show
#chair = Chair.find(params[:id])
#user = User.find(params[:id])
end
def new
#chair = Chair.new
#user = current_user
end
def create
#user = current_user
#chair = Chair.new(chair_params)
#chair.user = #user
if #chair.save
redirect_to chairs_path
end
end
private
def chair_params
params.require(:chair).permit(:name, :description)
end
end
<h1><%= #chair.name %></h1>
posted by <%= #user.email %>

At the moment you try to load the user by the same params[:id] as the chair your show method. Change your show method to:
def show
#chair = Chair.find(params[:id])
#user = #chair.user
end

Related

Active Record: Adding "visit" counter on the model

I currently have a Subscriber model that takes in a "phone_number" and a "visit" attribute that is an integer. I want to set up a "check in" view form that will have a subscriber type in their phone_number and it will say if phone_number exists? add 1 to the visit attribute. So it will run a sql query and see if that number is in the database.
To be more clear I have to break the REST actions because the create action is already taken for the new subscribers. I'm pretty new to rails and I'm having a super hard time figuring this feature out. I'm curious if this is possible and how I should go about implementing this?
Here is my controller at the moment:
class SubscribersController < ApplicationController
def index
#subscriber = Subscriber.all
end
def new
#subscriber = Subscriber.new
end
def create
#subscriber = Subscriber.create(subscriber_params)
if #subscriber.save
flash[:success] = "Subscriber Has Been successfully Created"
redirect_to new_subscriber_path(:subscriber)
else
render "new"
end
end
def visit
end
private
def subscriber_params
params.require(:subscriber).permit(:first_name, :last_name, :email, :phone_number)
end
end
Something along those lines?
def visit
subscriber = Subscriber.find_by_phone_number(params[:phone_number])
if subscriber
subscriber.visit += 1
subscriber.save
end
end
Make sure that the default value (via DB/Migration) for visit is set to 0.
You don't need to break REST style controller though. You can create another controller which does that check. For example something like:
class Subscriber::VisitController < ApplicationController
def create
# code here
end
end

Rails Create article with other user not current_user

I would like to create an article with other user not current_user and for that I'm saving in a session the id to the other user and I recover this id with a collection in the view to this point everything work fine but when I'm trying to use my helper :selected_user into my articles controller with a if sentence doesn't work here is my code:
def new
if selected_user.present?
#article = selected_user.articles.build state: :step1
render_wizard
else
#article = current_user.articles.build state: :step1
render_wizard
end
end
so, I'm asking if the selected_user.present? I would like to create the article with this user_id but else I would like to create it with the current_user
my create method is:
def create
if selected_user.present?
step = :step1
#article = selected_user.articles.build article_params_step1
#article.state = step.to_s
if #article.save
redirect_to wizard_path(next_step, article_id: #article)
else
render_wizard
end
else
step = :step1
#article = current_user.articles.build article_params_step1
#article.state = step.to_s
if #article.save
redirect_to wizard_path(next_step, article_id: #article)
else
render_wizard
end
end
end
so, yeah when I run my view the controller jump to the else section.
just for clarify my selected_user not return nil but here is the implementation:
selections_controller.rb:
class SelectionsController < ApplicationController
before_action :authenticate_user!
def create
session[:selected_user_id] = params[:user][ :user_id]
redirect_to root_path
end
end
and in my application_controller.rb:
helper_method :selected_user
def selected_user
#selected_user ||= User.find(session[:selected_user_id])
end
and in the view:
<%= form_tag( { :controller => "selections", :action => "create" } , :class => "navbar-form navbar-left") do %>
<%= collection_select(:user, :user_id, User.all, :id, :name, prompt: "Escoge cliente")%>
<%= submit_tag 'Enviar' %>
<% end %>
if I try create an article without select an user from my collection appear this error:
Couldn't find User with 'id'=
but when I select my user from the collection everything works fine. so just I want when I don't select nothing create with the current_user.
Thanks for your time !
Regards !
The reason why you were seeing the error
Couldn't find User with 'id'=
when you haven't selected a user was that the session[:selected_user_id] was nil and your old selected_user with following code was throwing the error.
def selected_user
#selected_user ||= User.find(session[:selected_user_id])
end
User.find method expects either a single id or an array of ids. If you give a single id and if it finds the relevant record in the database then it will returns that instance. If you give an array of ids and if it finds those relevant records in the database, then it will return array of those instances. But if you pass nil to it, then it will through the error Couldn't find User with 'id'= as it won't find a relevant record.
But your updated selected_user implementation:
def selected_user
#selected_user ||= session[:selected_user_id] && User.find_by_id(session[:selected_user_id])
end
is working because, first you are checking for the existence of session[:selected_user_id] value and second you are using User.find_by_id instead of User.find.
User.find_by_id either returns a single instance of the record if it finds it in the database or will return nil if it doesn't find the record. It will never through an error.
Refer to ActiveRecord#find and ActiveRecord#find_by for more info.
I'm not sure why is working and what is the different but my solution for the problem it was to add this to my selected_user method:
def selected_user
#selected_user ||= session[:selected_user_id] && User.find_by_id(session[:selected_user_id])
end
and with that I don't have the nil error and entry to the if statement without errors.

Does directly visiting a url have the same effect as navigating via a link?

I have a voting system which records users' ip addresses, users can only vote once. If the array of votes contains the user's ip address, then the voting link will not be displayed to the user:
show.html.erb
<% if !ip_array.include? request.remote_ip %>
<%= link_to "Vote!", vote_user_path(#user) %>
<% else %>
You've already voted!
<% end %>
users_controller.rb
def vote
#user = User.find(params[:id])
#user.votes = #user.votes + 1
#user.save
end
But couldn't a user just directly go to www.my_website.com/users/:id/vote to bypass this? If so, how can I prevent this?
The way you prevent it is by placing the validation inside the controller action, rather than in (or in addition to) the view.
before_action :ensure_not_voted
def vote
#user = User.find(params[:id])
#user.votes = #user.votes + 1
#user.save
end
protected
def ensure_not_voted
# perform the check and stop on failure
# already_voted is a fake function, replace it with your real check
if already_voted
halt(403)
end
end
For simpler solution, you can add a session token to each user, and check if the ip contains the specific token, like
add a before_filter :auth, :only => [:vote]
def vote
#user = User.find(params[:id])
#user.votes = #user.votes + 1
#user.save
session[:token] = request.remote_ip
end
private
def auth
#ip = session[:token].to_s
if #ip != nil
redirect_to :back
flash[:notice] = "You have already voted"
return false
else
return true
end
end
the user can remove cookies to vote again(few people can), for that case you can save the ip in the db and check against it

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")

How to set up acts_as_follower

I'm using the gem acts_as_follower in a rails app. I set it up and it works (In console), however I'm clueless as to how to set it up in a view.
I want to make a button correspond to the user.follow and user.stop_following methods.
The github doesn't explain this. Help please.
You can create controller actions that you link to. For example in an app I have the following two actions added to a user controller. Once the routes are also setup I use the url helpers to link to the actions from my view, and end up displaying the flash messages via javascript callbacks.
UsersController:
def follow
#user = User.find(params[:id])
if current_user
if current_user == #user
flash[:error] = "You cannot follow yourself."
else
current_user.follow(#user)
RecommenderMailer.new_follower(#user).deliver if #user.notify_new_follower
flash[:notice] = "You are now following #{#user.monniker}."
end
else
flash[:error] = "You must <a href='/users/sign_in'>login</a> to follow #{#user.monniker}.".html_safe
end
end
def unfollow
#user = User.find(params[:id])
if current_user
current_user.stop_following(#user)
flash[:notice] = "You are no longer following #{#user.monniker}."
else
flash[:error] = "You must <a href='/users/sign_in'>login</a> to unfollow #{#user.monniker}.".html_safe
end
end
config/route.rb:
resources :users do
member do
get :follow
get :unfollow
end
end
Then in your view you can use the url helper to link to the controller action:
<%= link_to "Unfollow", unfollow_user_path(#user) %>

Resources