Authenticate model issue - ruby-on-rails

I have a rails 4 app where I want to have certain books require a secret password to see.
I have a model called Book.rb:
class Book < ActiveRecord::Base
has_secure_password :validations => false
end
and a sign_in.html.haml that has the form:
= form_for login_book_path do |f|
= f.password_field :password
= f.submit "View Book"
and the login book path routes to the following controller method:
def book_login
#book = Book.find_by(slug: params[:slug])
respond_to do |format|
if #book.authenticate(params[:password])
format.html { redirect_to root_path }
else
format.html { render :sign_in }
end
end
end
If I hardcode the password (like #book.authenticate("thesecretpassword"), it correctly redirects me to the root_url. But for some reason, without hardcoding it doesn't work (just sends me back to sign_in.html.haml?
Here's the output in the terminal when I hit the "VIEW BOOK" button:
Started POST "/the-wizard-book/sign_in" for 127.0.0.1 at 2015-02-24 14:04:48 -0700
Processing by BooksController#book_login as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Nx2OkI/FjJwq6zmcT5KLSkQpr9hYa83RL7CFmLQW0/g=", "/the-wizard-book/sign_in"=>{"password"=>"[FILTERED]"}, "commit"=>"View Book", "slug"=>"the-wizard-book"}
Load (0.2ms) SELECT "books".* FROM "books" WHERE "books"."slug" = 'the-wizard-book' LIMIT 1

Related

Calling `format.js` results in "No template found" Warning

I'm trying to offer my users a link to click which will: (1) trigger an AJAX call, (2) activate a controller/action which will destroy a Comment object, (3) have that same controller/action respond back with both HTML and JavaScript.
Everything works fine, except the JavaScript response. For some reason, Rails cannot find the .js.erb template that corresponds to my controller/action, so it doesn't fire any client-side JavaScript, and instead throws a "No template found" warning.
View that contains the clickable link:
<%= link_to blog_post_comment_path(#blog_post,c), method: :delete, :remote => true do %>
<%= fa_icon "trash" %>
<% end %>
Controller:
class CommentsController < ApplicationController
def destroy
#blog_post = BlogPost.find(params[:blog_post_id])
#comment = Comment.find(params[:id])
#comment.delete
respond_to do |format|
format.html { redirect_to edit_blog_post_path(#blog_post), notice: "Comment deleted!" }
format.js
end
end
end
I have a view that lives at: /app/views/comments/destroy.js.erb. No matter what JavaScript I add to this file, it won't execute.
When I click the link_to link in a browser, the Rails logs shows:
Comment Destroy (1.5ms) DELETE FROM "comments" WHERE "comments"."id" = ? [["id", 44]]
↳ app/controllers/comments_controller.rb:7
No template found for CommentsController#destroy, rendering head :no_content

issue with nested route in Rails 5.1 application

I'm building an application for students to register an absence during a exam.
my routes look like this:
resources :users do
resources :absences
end
the form to create an absence looks like this:
<%= form_for [#user, #absence] do |f| %>
<%= f.label :course_id, "Vak" %>
<%= f.select :course_id, options_for_courses, label: "Vak" %>
<%= f.label :date, "Datum" %>
<%= f.text_field :date %>
<%= f.submit "Afwezigheid aanvragen" %>
<% end %>
the Absence model looks like this:
class Absence < ApplicationRecord
...
belongs_to :user
end
the User model looks like this:
class User < ApplicationRecord
...
has_many :absences
end
The AbsencesController looks like this:
class AbsencesController < ApplicationController
...
def new
#user = current_user
#absence = current_user.absences.build
end
def create
#absence = Absence.create(absence_params)
if #absence.save
redirect_to root_path, notice: "Afwezigheid succesvol aangevraagd"
else
flash[:alert] = "Er was een probleem met het registreren van de afwezigheid"
render :new
end
end
But when I try to register an absence, I get an error in the form:
The error log looks like this:
Started POST "/users/2/absences" for 127.0.0.1 at 2017-09-21 09:51:55 +0200
Processing by AbsencesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"esW1HeKf+VG8+RC4Zm2F7d8BFewddk6aIssj0Y90s+UC4oTUxpO1iw9hR9M94Jfov5bjeB0aQPRHG0qvENO3Tg==", "absence"=>{"course_id"=>"2", "date"=>"27/09/2017"}, "commit"=>"Afwezigheid aanvragen", "user_id
"=>"2"}
(0.1ms) BEGIN
Course Load (0.3ms) SELECT "courses".* FROM "courses" WHERE "courses"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
(0.1ms) ROLLBACK
(0.1ms) BEGIN
(0.1ms) ROLLBACK
Rendering absences/new.html.erb within layouts/application
Rendered absences/new.html.erb within layouts/application (145.6ms)
Completed 500 Internal Server Error in 616ms (ActiveRecord: 0.9ms)
ActionView::Template::Error - undefined method `absences_path' for #<#<Class:0x007fb911af0420>:0x007fb90baab5d8>
Did you mean? asset_path:
actionpack (5.1.3) lib/action_dispatch/routing/polymorphic_routes.rb:230:in `polymorphic_method'
actionpack (5.1.3) lib/action_dispatch/routing/polymorphic_routes.rb:138:in `polymorphic_path'
actionview (5.1.3) lib/action_view/helpers/form_helper.rb:472:in `apply_form_for_options!'
actionview (5.1.3) lib/action_view/helpers/form_helper.rb:440:in `form_for'
I'm not sure what's going on, have I missed something?
thanks for your help,
Anthony
There is an error while creating your object and you are doing render :new which is rendering the form again but with #user as nil. So what happens that <%= form_for [nil, #absence] do |f| %> makes the path as absences_path which is not present. So either fetch #user in create action too or just use current_user everywhere. Like this:
def new
#user = current_user # You may remove this
#absence = current_user.absences.build
end
def create
#absence = Absence.create(absence_params)
if #absence.save
redirect_to root_path, notice: "Afwezigheid succesvol aangevraagd"
else
#user = current_user # If you don't want to remove this line from new action then add it here too
flash[:alert] = "Er was een probleem met het registreren van de afwezigheid"
render :new
end
end
And in the form if you remove the #user from controller then do it like this:
<%= form_for [current_user, #absence] do |f| %>
Update:
To save the object in create action change this line:
#absence = Absence.create(absence_params)
to
#absence = current_user.absences.build(absence_params)
Your user_id was nil because there was no input box or any hidden field for that and that is correct. You just need to build the object again against the current_user. And I have changed the create to build because create directly saves the object to database instead you want to build it first and then you are trying to save it.
Hope this helps.
You are getting problem in your create method when you are rendering the new because form doesn't getting the #user
add following in your create method & check again
#user = current_user
Okay, you just add return after this line:
redirect_to root_path, notice: "Afwezigheid succesvol aangevraagd"
return
As your log says, you are trying to render :new template at the end of the method, you need to add return to stop it after redirect_to
or delete that line at the end of your create method
render :new
Also change this:
#absence = current_user.absences.build(absence_params)

Rails 3: when no current_user(no user logged in) friendly_id sends username as :id but controller method does not work

I'm using friendly_id gem and it's working properly when I go to a user's profile page as a logged in user:
localhost/users/facebookname
When I log out and go to the profile page it displays the url same way, no problem. However, when I attempt to display the user's 'liked' posts I run into a problem. Nothing happens.
Started GET "/users/facebookname/likes" for 127.0.0.1 at 2015-01-08 14:47:23 +0700
Processing by UsersController#likes as JS
Parameters: {"id"=>"facebookname"}
Completed in 152ms
UsersController#likes
def likes
#title = "Likes"
#user = User.find(params[:id])
respond_to do |format|
format.html { render "posts/posts", :locals => { :posts => #likes } }
format.js { respond_with #likes}
end
end
UsersModel
has_friendly_id :username, :use_slug => true, :approximate_ascii => true
When I am logged in as a user, and try the same thing, the Parameters: {"id"=>"facebookname"} are used the same way, but the controller action uses this with the proper :id and renders #likes. Why is this not happening without a logged in user?
Thank you very much for any insight
You should find user by username in your controller:
#user = User.find_by_username!(params[:id])

Authlogic ignoring password parameter

Authlogic seems to be ignoring the password parameter when creating a new user. Here's my users_controller class:
class Api::V1::UsersController < ApplicationController
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.json { render :json => #user, :status => :created}
else
format.json { render :json => #user.errors, :status => :unprocessable_entity }
end
end
end
private
def user_params
params.require(:user).permit(:username, :email, :password)
end
end
And my user model:
class User < ActiveRecord::Base
acts_as_authentic do |c|
c.require_password_confirmation = false
end
end
When I send a POST request to /api/v1/users/ with a username, email and password parameter, authlogic says that the password cannot be blank even though it isn't. Here's whats printed out by rails:
Started POST "/api/v1/users/" for 127.0.0.1 at 2013-06-22 00:03:30 -0400
Processing by Api::V1::UsersController#create as */*
Parameters: {"email"=>"someemail#website.com", "password"=>"[FILTERED]", "username"=>"myUser", "user"=>{"username"=>"myUser", "email"=>"someemail#website.com"}}
(0.2ms) BEGIN
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('someemail#website.com') LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."username") = LOWER('myUser') LIMIT 1
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."persistence_token" = '7b72bab3627914d33e83e4efe1c5a9dab190750efb227698c8b5b6be7a7ccf118160d8e12623078543e0f4e5f31eb30828799cb0d97fb2af195daee894c79902' LIMIT 1
(0.2ms) ROLLBACK
Completed 422 Unprocessable Entity in 33ms (Views: 0.2ms | ActiveRecord: 3.2ms)
I'm using the latest authlogic and Ruby 2/Rails 4.
Take a look at an excerpt from Rails log:
{"email"=>"someemail#website.com", "password"=>"[FILTERED]", "username"=>"myUser", "user"=>{"username"=>"myUser", "email"=>"someemail#website.com"}}
It looks like you send slightly wrong parameters. To be recognized by Authlogic, password parameter should go under user key in parameters hash. I.e. that line from Rails log should look like this (pay attention to the end of string):
{"email"=>"someemail#website.com", "password"=>"[FILTERED]", "username"=>"myUser", "user"=>{"username"=>"myUser", "email"=>"someemail#website.com", "password" => "[FILTERED]"}}
To fix it, you can do a hack like this:
private
def user_params
params.require(:user).permit(:username, :email).merge(:password => :password)
end
Alternatively, you can adjust the parameters sent from the client side (for example, using user[password] parameter's name instead of just password when sending HTTP POST request).
try this out:-
acts_as_authentic do |config|
config.check_passwords_against_database = false
config.validate_password_field = false
config.crypted_password_field = false
end

How to allow devise users to edit their profil?

I have a namespace called "backend" which is protected by Devise.
I would like now to allow users to edit their profil.
So I created a users_controller in Backend.
Here's the users_controllercode :
class Backend::UsersController < ApplicationController
layout 'admin'
before_filter :authenticate_user!
def index
#users = Backend::User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #users }
end
end
def show
#user = Backend::User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
def edit
#user = Backend::User.find(params[:id])
end
def update
#user = Backend::User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'Article was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
When I go on backend_users_path there is a list of all the users. I would like to permit to edit only his own profil.
So I go on the Edit page : <%= link_to "Edit", edit_backend_user_path(backend_user.id) %> .
Here's the Edit page code :
<%= simple_form_for #user do |f| %>
<div><%= f.label :email %><br />
<%= f.input :email, :autofocus => true %></div>
<div><%= f.submit "Update" %></div>
<% end %>
And there is my problem : when I try to modify the email address, nothing happen. The update fails.
How can I do this ?
I'm quite lost.
Thanks by advance.
Here's the log file :
Started PUT "/backend/users/1" for 127.0.0.1 at 2012-11-13 12:13:51 +0100
Processing by Backend::UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wWrUDh7LVWhP+P7OWO6laDWaCKInxk37AA2BPuQWAI4=", "backend_user"=>{"email"=>"grellazzi#laposte.net"}, "commit"=>"Update", "id"=>"1"}
[1m[35mBackend::User Load (0.0ms)[0m SELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = 1 LIMIT 1
[1m[36mBackend::User Load (0.0ms)[0m [1mSELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = ? LIMIT 1[0m [["id", "1"]]
[1m[35mSQL (1.0ms)[0m BEGIN
[1m[36m (0.0ms)[0m [1mCOMMIT[0m
Redirected to http://localhost:3000/backend/users/1
Completed 302 Found in 23ms (ActiveRecord: 1.0ms)
Started GET "/backend/users/1" for 127.0.0.1 at 2012-11-13 12:13:51 +0100
Processing by Backend::UsersController#show as HTML
Parameters: {"id"=>"1"}
[1m[35mBackend::User Load (0.0ms)[0m SELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = 1 LIMIT 1
[1m[36mBackend::User Load (0.0ms)[0m [1mSELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = ? LIMIT 1[0m [["id", "1"]]
Rendered backend/users/show.html.erb within layouts/admin (0.0ms)
Completed 200 OK in 7ms (Views: 5.0ms | ActiveRecord: 0.0ms)
Thanks for your links, I tried to modify my user_controller with
if params[:user][:password].blank?
params[:user].delete("password")
params[:user].delete("password_confirmation")
end
#user = User.find(current_user.id)
if #user.update_attributes(params[:user])
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
But it fails...
If nothing happens, that usually indicates a validation error, in your case probably a missing password or other data that is not part of your form but is still being validated. To debug this, output #user.errors.inspect to your logfile or look at error_messages_on #user in your view.
In general, take a look at these guides on how to allow users to edit their (partial) profile:
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-account-without-providing-a-password
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-password

Resources