Displaying total votes count with thumbs_up - ruby-on-rails-3

I am trying to display total votes cast on a post with thumbs_up gem but it does not seem to work.
Here is my code
def vote_up
begin
post = Post.find(params[:id])
current_user.vote_for(post)
redirect_to :back
flash[:sucess] = "You have voted successfully"
#votes_total = post.votes_for
rescue ActiveRecord::RecordInvalid
redirect_to :back
flash[:error] = "You have already voted for this one"
end
end
In the view :-
<%="Total votes = #{#votes_total}"%>
I get the flash message "You have voted successfully" but my votes count are not getting displayed.
This is what I have in my log files :-
[1m[36m (0.3ms)[0m [1mSELECT COUNT(*) FROM "votes" WHERE
"votes"."voteable_id" = 12 AND "votes"."voteable_type" = 'Post' AND
"votes"."vote" = 't'[0m 0
--- Update ---
Update my post controller with this code :-
def vote_up
begin
post = Post.find(params[:id])
current_user.vote_for(post)
#votes_total = post.votes_for
render :template => "home/index"
flash[:sucess] = "You have voted successfully"
rescue ActiveRecord::RecordInvalid
redirect_to :back
flash[:error] = "You have already voted for this one"
end
end
Help please.

It does not display because you are redirecting. When redirecting you are basically doing a new request and the instance variables of the former request won't be available anymore. Flash does work, because it uses the session. Solution: either set #votes_total in the action you are redirecting to or use render instead of redirect_to.

try changing
#votes_total
to the
#post.votes_for or corresponding equivalent
in the view.

Related

Redirect rails app to home page on crash

I want my app to redirect to my home page ie posts#index. It is a rails2 app which I am trying to migrate to rails 3.
def rescue_action_in_public(exception)
flash[:notice] = "There was an error. Please try again." # #{exception}
redirect_to :controller => :posts, :action => :index
end
This method I presume does this task. How ever, It won't work in rails 3 and I see the 'Sorry something went wrong!' page
How can I get this functionality working in rails 3? If any more info is, needed I am willing to paste here.
in rails 3 try this
def rescue_action_in_public(exception)
status = status_code(exception)
locale_path = "#{public_path}/#{status}.#{I18n.locale}.html" if I18n.locale
path = "#{public_path}/#{status}.html"
if locale_path && File.exist?(locale_path)
render(status, File.read(locale_path))
elsif File.exist?(path)
render(status, File.read(path))
else
render(status, '')
end
end
from apidock
You can right this way!
def rescue_action_in_public(exception)
flash[:notice] = "There was an error. Please try again." # #{exception}
redirect_to posts_path
end

Statement invalid when attempting to implement password_reset Railscast

I'm attempting to implement Railscast #274 in my app so I can provide a password reset option. I got to the point where I can type my email into a form for password resets and receive an email with a link to reset the password. Things start to go wrong when I enter my new password and attempt to save it. I ended up with an Action Controller:Exception caught. Here is what my log showed after I sent myself an email with the password_reset link:
Started GET "/password_resets/new" for 127.0.0.1 at 2012-01-26 00:50:42 -0500
Processing by PasswordResetsController#new as HTML
Clicking the password_reset link:
Started GET "/password_resets/qlslPnuOhdyMCNseMnV3bA/edit" for 127.0.0.1 at 2012-01-26 00:51:08 -0500
Processing by PasswordResetsController#edit as HTML
Parameters: {"id"=>"qlslPnuOhdyMCNseMnV3bA"}
Adding a new :password and :password_confirmation yields the error:
Started POST "/password_resets/qlslPnuOhdyMCNseMnV3bA" for 127.0.0.1 at 2012-01-26 00:53:08 -0500
Processing by PasswordResetsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"2egfT2lr35FhuVPWDB72vcS2zPlqC75tcyctRp61ZHw=", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "commit"=>"Update Password", "id"=>"qlslPnuOhdyMCNseMnV3bA"}
Started GET "/profiles/qlslPnuOhdyMCNseMnV3bA" for 127.0.0.1 at 2012-01-26 00:53:09 -0500
Processing by ProfilesController#show as HTML
Parameters: {"id"=>"qlslPnuOhdyMCNseMnV3bA"}
Profile Load (0.9ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."id" = 'qlslPnuOhdyMCNseMnV3bA' LIMIT 1
PGError: ERROR: invalid input syntax for integer: "qlslPnuOhdyMCNseMnV3bA"
LINE 1: ...ofiles".* FROM "profiles" WHERE "profiles"."id" = 'qlslPnuOh...
^
: SELECT "profiles".* FROM "profiles" WHERE "profiles"."id" = 'qlslPnuOhdyMCNseMnV3bA' LIMIT 1
Completed in 57ms
ActiveRecord::StatementInvalid (PGError: ERROR: invalid input syntax for integer: "qlslPnuOhdyMCNseMnV3bA"
LINE 1: ...ofiles".* FROM "profiles" WHERE "profiles"."id" = 'qlslPnuOh...
^
: SELECT "profiles".* FROM "profiles" WHERE "profiles"."id" = 'qlslPnuOhdyMCNseMnV3bA' LIMIT 1):
app/controllers/profiles_controller.rb:41:in `show'
In profiles_controller.rb:41 in show:
def show
#profile = Profile.find(params[:id])
#user = User.find(#profile.user_id)
..
end
Before doing this I dumped my database, ran rake:db create, then rake:db migrate before re-seeded the db. Could this be because I haven't run a script to give existing users a password_reset_token?
UPDATE: Including password_resets_controller.rb:
class PasswordResetsController < ApplicationController
def new
end
def create
#user = #User.find_by_email(params[:email])
if user
user.send_password_reset
redirect_to new_password_reset_path, :notice => "Check your email for password reset instructions."
else
redirect_to new_password_reset_path, :notice => "Sorry, we couldn't find that email. Please try again."
end
end
def edit
#user = User.find_by_password_reset_token!(params[:id])
end
def update
#user = User.find_by_password_reset_token!(params[:id])
if #user.password_reset_sent_at < 2.hours.ago
redirect_to new_password_reset_path, :alert => "Your password reset link has expired."
elsif #user.update_attributes(params[:user])
redirect_to profile_path, :notice => "Great news: Your password has been reset."
else
render :edit
end
end
end
Looks like the problem is in your PasswordResetsController#update:
def update
#user = User.find_by_password_reset_token!(params[:id])
if #user.password_reset_sent_at < 2.hours.ago
redirect_to new_password_reset_path, :alert => "Your password reset link has expired."
elsif #user.update_attributes(params[:user])
redirect_to profile_path, :notice => "Great news: Your password has been reset."
else
render :edit
end
end
The redirect_to profile_path in particular.
If you look at the logs, you'll see this sequence:
POST "/password_resets/qlslPnuOhdyMCNseMnV3bA"
GET "/profiles/qlslPnuOhdyMCNseMnV3bA"
and the routes should be /password_resets/:id and /profiles/:id. The /password_resets wants the 'qlslPnuOhdyMCNseMnV3bA' token but /profiles wants the user's numeric ID.
Going back to the controller we see this:
redirect_to profile_path, :notice => "Great news: Your password has been reset."
You don't tell profile_path which user to use so apparently it is grabbing params[:id] to build the incorrect /profiles/qlslPnuOhdyMCNseMnV3bA URL. Try telling profile_path which user to use with something like this:
redirect_to profile_path(#user), :notice => "Great news: Your password has been reset."

Need help Rspec test

I'm trying to learn RSpec and writing test for CRUD actions. Here is my controller:
class ArticlesController < ApplicationController
respond_to :html, :json
before_filter :authenticate_user!
# GET /articles
# GET /articles.json
def index
#articles = current_user.articles.all
respond_with(#articles)
end
# GET /articles/1
# GET /articles/1.json
def show
#article = current_user.articles.find(params[:id])
respond_with #article
end
# GET /articles/new
# GET /articles/new.json
def new
#article = current_user.articles.build
respond_with #article
end
# GET /articles/1/edit
def edit
#article = get_article(params[:id])
end
# POST /articles
# POST /articles.json
def create
#article = current_user.articles.build(params[:article])
flash[:notice] = "Article was successfully created!" if #article.save
respond_with(#article, location: articles_path)
end
# PUT /articles/1
# PUT /articles/1.json
def update
#article = get_article(params[:id])
if #article.update_attributes(params[:article])
flash[:notice] = "Article was successfully updated."
end
respond_with #article
end
# DELETE /articles/1
# DELETE /articles/1.json
def destroy
#article = get_article(params[:id])
#article.destroy
respond_with #article
end
private
def get_article(article_id)
current_user.articles.find(article_id)
end
end
And my articles rspec:
describe ArticlesController do
def valid_attributes
{
:title => "Introducting Node.js",
:content => "Node.js is an event-driven...."
}
end
let(:article) do
build(:article, valid_attributes)
end
describe "PUT 'update'" do
before(:each) do
controller.stub_chain(:current_user, :articles, :build) { article }
end
context "success" do
before(:each) do
article.should_receive(:update_attributes).and_return(true)
put :update, id: article.id
end
it "sets notice" do
flash[:notice].should eq("Article was successfully updated!")
end
end
end
describe "POST 'create'" do
before(:each) do
controller.stub_chain(:current_user, :articles, :build) { article }
end
context "success" do
before(:each) do
article.should_receive(:save).and_return(true)
post :create
end
it "sets notice" do
flash[:notice].should eq("Article was successfully created!")
end
it "should redirect to article path" do
response.should redirect_to(articles_path)
end
end
context "failure" do
before(:each) do
article.should_receive(:save).and_return(false).as_null_object
post :create
end
it "assigns #article" do
assigns(:article).should == article
end
end
end
end
My question is when I run rspec on PUT UPDATE test is failed. But POST test is passed. I don't have any idea what is going on. I'm using Rails 3.1.1 with omniauth. I'm not using Devise. Here is the test result. Why? Please help me guys?
Failures:
1) ArticlesController PUT 'update' success sets notice
Failure/Error: put :update, id: article.id
NoMethodError:
undefined method `find' for #<Object:0xa3cfd20>
# ./app/controllers/articles_controller.rb:61:in `get_article'
# ./app/controllers/articles_controller.rb:44:in `update'
# ./spec/controllers/articles_controller_spec.rb:46:in `block (4 levels) in <top (required)>'
Finished in 24.09 seconds
5 examples, 1 failure
Here's the thing.
When you're stubbing, you're just saying "if this method chain is called, return this." There are two issues with that. 1) the code doesn't ever call build, and 2) there's no actual associations.
I believe you'd need to stub current_user.articles to return an article collection. The problem is that AR associations aren't actual arrays, they're proxies.
See this SO post and this SO post for more details. A regular array won't treat the find method like the AR method it really is, and you're not returning a single article.
Since you have the article ID, you could just return that particular article, but your goal is to return that article from within the user's articles to avoid updating someone else's (I assume).
This SO post may also help, and this.
In other words, you may want a real user there, with real associated objects, so things like find will work w/o hackery.
(I fully recognize this isn't a real answer; I've never done this via stubbing, I've used factories/etc.)

Rails 3 Devise Update Password Without Logging Out

I'm Using Devise in my Rails 3.0.9 application for User Authentication. As I wanted to be able to manage Users, I created the following Users Controllers:
class UsersController < ApplicationController
def index
#users = User.all
end
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Successfully created User."
redirect_to users_path
else
render :action => 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
params[:user].delete(:password) if params[:user][:password].blank?
params[:user].delete(:password_confirmation) if params[:user][:password].blank? and params[:user][:password_confirmation].blank?
if #user.update_attributes(params[:user])
if current_user.update_with_password(params[:user])
sign_in(current_user, :bypass => true)
end
flash[:notice] = "Successfully updated User."
redirect_to users_path
else
render :action => 'edit'
end
end
def destroy
#user = User.find(params[:id])
if #user.destroy
flash[:notice] = "Successfully deleted User."
redirect_to users_path
end
end
end
I this works for showing, creating and deleting Users, but I have run into a problem when updating the passwords.
When I Update the password for the currently logged in account it automatically logs me out.
In the controller I tried to fix this using: (you can see it in the code above)
if current_user.update_with_password(params[:user])
sign_in(current_user, :bypass => true)
end
But that gives me this error ->
undefined method `update_with_password' for nil:NilClass
What I'm really looking for, is the ability to update any accounts password, without logging them out ( as admins have ability to change regular users password ).
It is not necessary to write
This code in the controller
if current_user.update_with_password(params[:user])
sign_in(current_user, :bypass => true)
end
Instead you should go ahead with below one
if #user.update_attributes(params[:user])
sign_in(current_user, :bypass => true)
redirect_to users_path
end
cheers :)
The easiest way to do this is call
sign_in(current_user, :bypass => true)
After the update.
This is what my controller action looks like:
def update_password
if current_user.update_with_password(params[:user])
sign_in(current_user, bypass: true)
flash[:notice] = "Updated Password Successfully"
else
flash[:error] = "There was an error updating your password, please try again."
end
end
I think this is basically what #challenge proposed but I just wanted to make a little cleaner and easier to understand.

How do I make a route to a custom controller action in Rails 3?

I'm new to Rails, and a bit confused about routes:
I have a Devices controller:
#devices_controllers.rb
class DevicesController < ApplicationController
def index
#devices = Device.all
end
def show
#device = Device.find(params[:id])
end
def new
#device = Device.new
end
def create
#device = Device.new(params[:device])
if #device.save
flash[:notice] = "Successfully created device."
redirect_to #device
else
render :action => 'new'
end
end
def edit
#device = Device.find(params[:id])
end
def update
#device = Device.find(params[:id])
if #device.update_attributes(params[:device])
flash[:notice] = "Successfully updated device."
redirect_to #device
else
render :action => 'edit'
end
end
def destroy
#device = Device.find(params[:id])
#device.destroy
flash[:notice] = "Successfully destroyed device."
redirect_to devices_url
end
def custom_action
"Success"
end
I'd like to access the "custom_action" action via a url like this:
http://foo.bar/devices/custom_action
I've added this line to my routes.rb file:
match 'devices/custom_action' => 'devices#custom_action'
However, when I try the URL in the browser, I get this error:
ActiveRecord::RecordNotFound in DevicesController#show
Couldn't find Device with ID=custom_action
It seems to be going to #show action instead of #custom_action. If a user id is not supplied, and I go to http://foo.bar/devices/custom_action, I'd like it to go #custom_action.
I've read Rails Routing from the Outside, but still can't still seem to figure out the problem.
I think the problem may be because of the order in which you have defined your routes.
I suspect you have resources :devices in your routes.rb. In addition, I suspect you have defined your custom route after this. If you type rake routes into your console/terminal, you will see that there is already a route defined for the following pattern:
GET /devices/:id
This route is a product of resources :devices, which is taking precedence over your custom route. Referring back to the Edge Guides, specifically in 1.1. Connecting URLs to Code, it states that the request will be dispatched to the first matching route. So a simple fix would be to define your custom route before resources :devices.