Good afternoon,
I've done a scaffold of a class, here the example: User - At the moment I was executing the test I saw this bug:
Minitest::Assertion: "User.count" didn't change by 1.
Expected: 3
Actual: 2
test/controllers/users_controller_test.rb:20:in `block in <class:UsersControllerTest>'
the refering code of the bug is this one:
test "should create user" do
assert_difference('User.count') do
post :create, user: { name: 'test', password: 'secret', password_confirmation: 'secret' }
end
assert_redirected_to user_path(assigns(:user))
end
So the code above was created by the scaffold, I just change the name reference.
UserController:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy, :reset_password]
# GET /users
# GET /users.json
def index
#users = super
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: get_action_message }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
#user.update(user_params)
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: get_action_message }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: get_action_message }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :password, :password_confirmation)
end
def search_params
super - ['password_digest']
end
def show_attributes
#show_attributes = super - ['password_digest']
end
end
UserModel
class User < ActiveRecord::Base
nilify_blanks
validates :name, presence: true, uniqueness: true;
has_secure_password
end
For what I was able to understand, the "create" it's not being executed. I've put the breakpoint on the Controller create but its not stoping there..
What am I doing wrong, besides my poor english skills?
Tks for the helping!!
Thks guys,
I found this bug.
I had forgotten to put in the user Session
Related
I've been around for this problem for 1 hour and not figuring out why it doesn't work.
I don't use gem devise.
I have user model, post model, UsersController.rb, PostsController.rb and 1 helper like below
PostsController.rb :
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = current_user.posts.build(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:caption, :user_id)
end
end
ApplicationHelper.rb
module ApplicationHelper
def current_user
session[:user_id] && User.find(session[:user_id])
end
end
The current_user helper method works fine for all the views.
As I understand, PostsController inherits from ApplicationController, so it takes all the helpers from ApplicationHelper. I still dont figure out why this doesn't work.
Thanks for any help.
Try with adding this into ApplicationController.rb
helper_method :current_user
call helper methods in Rails 5 :
# sample :
module UsersHelper
def full_name(user)
user.first_name + user.last_name
end
end
class UsersController < ApplicationController
def update
#user = User.find params[:id]
if #user.update_attributes(user_params)
notice = "#{helpers.full_name(#user) is successfully updated}"
redirect_to user_path(#user), notice: notice
else
render :edit
end
end
end
Before Rails 5 :
# sample :
module UsersHelper
def full_name(user)
user.first_name + user.last_name
end
end
class UsersController < ApplicationController
include UsersHelper
def update
#user = User.find params[:id]
if #user.update_attributes(user_params)
redirect_to user_path(#user), notice: "#{full_name(#user) is successfully updated}"
else
render :edit
end
end
end
am using devise for authentication in a rails app everything is working fine, but i have a post model and after signing up when i try to create a new post it shows up an error:
1 error prohibited this post from being saved:
User must exist
I looked into the terminal and got this:
Unpermitted parameter: user_id
(0.0ms) begin transaction
(0.0ms) rollback transaction
i tried adding a user controller
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
before_action :set_user
before_action :check_ownership, only: [:edit, :update]
respond_to :html, :js
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User 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
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :email)
end
end
my posts_controler.rb
class PostsController < ApplicationController
before_action :authenticate_user!, :except => [:show, :index]
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:tittle, :body)
end
end
My user model
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts
end
My post model
class Post < ApplicationRecord
belongs_to :user
end
i have also added user_id to user through this migration:
class AddUseridToPost < ActiveRecord::Migration[5.0]
def change
add_column :posts, :user_id, :integer
end
end
as the error says, permit the user_id as follows
def post_params
params.require(:post).permit(:tittle, :body, :user_id)
end
Or, better approach is you generate a new post for the logged_in user as in post create:
def create
#post = current_user.posts.new(post_params)
# ...other logic
end
This way, you don't need to allow user_id also, it will ensure that the params are not tampered with..
If you add column in your model, you should add it to your permitted params. So add :user_id in your permitted params in posts_controller:
def post_params
params.require(:post).permit(:tittle, :body, :user_id)
end
I'm trying to make a very simple web app using Rails and I'm using the Sorcery gem to authenticate users. I followed the tutorial here on their GitHub page, and I'm getting no where with it.
I have 2 issues which I believe are probably linked.
The first being, when I use this before_filter skip_before_filter :require_login, only: [:index, :new, :create], users can still access the page without logging in.
The other issue is, when a user tries to log in, they aren't redirected, and when I use the built in helper logged_in?, it always returns false. Even though there was no error message when logging in.
I've added the appropriate controllers, let me know if you need to look at anything else.
Thanks.
user_sessions_controller.rb
class UserSessionsController < ApplicationController
skip_before_filter :require_login, :except => [:destroy]
def new
#user = User.new
end
def create
if #user = login(params[:email], params[:password])
redirect_back_or_to(:users, :notice => 'Login successfull.')
else
flash.now[:alert] = 'Login failed'
render action: 'new'
end
end
def destroy
logout
redirect_to(:users, :notice => 'Logged out!')
end
end
users_controller.rb
class UsersController < ApplicationController
skip_before_filter :require_login, only: [:index, :new, :create]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to :users, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
#def user_params
# params.require(:user).permit(:email, :crypted_password, :salt)
#end
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
# protect_from_forgery with: :exception
protect_from_forgery
before_filter :require_login
private
def not_authenticated
redirect_to(login_path, :alert => "Please login first")
end
end
Everyone has access to Users pages due to this line skip_before_filter :require_login, only: [:index, :new, :create]. This literally means "don't check authorization". Just remove this line.
Generally you should skip require_login filter only on public pages and login pages (i.e. UserSessionsController#create etc).
And the second issue: do you have authenticates_with_sorcery! in your User model?
I've got an app where:
1. user is on a page viewing their profile information
2. user presses button to email someone from this page
3. after the email is sent, user is sent back to view their profile information again and a notice flashes to tell them if the email worked or not.
I'm having with no. 3. I'm not sure how to set up a redirect (or something else appropriate) that will send a user to view their profile info again
Controller:
class ProfilesController < ApplicationController
before_action :set_profile, only: [:show, :edit, :update, :destroy, :email]
# GET /profiles
# GET /profiles.json
def index
#profiles = Profile.all
end
# GET /profiles/1
# GET /profiles/1.json
def show
end
# GET /profiles/new
def new
#profile = Profile.new
end
# GET /profiles/1/edit
def edit
#profile = Profile.find_by user_id: current_user.id
end
# POST /profiles
# POST /profiles.json
def create
#profile = Profile.new(profile_params)
respond_to do |format|
if #profile.save
format.html { redirect_to #profile, notice: 'Profile was successfully created.' }
format.json { render :show, status: :created, location: #profile }
else
format.html { render :new }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /profiles/1
# PATCH/PUT /profiles/1.json
def update
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to #profile, notice: 'Profile was successfully updated.' }
format.json { render :show, status: :ok, location: #profile }
else
format.html { render :edit }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# DELETE /profiles/1
# DELETE /profiles/1.json
def destroy
#profile.destroy
respond_to do |format|
format.html { redirect_to profiles_url, notice: 'Profile was successfully destroyed.' }
format.json { head :no_content }
end
end
def email_profile
destination = params[:to]
share = Share.profile(#profile, destination)
if destination =~ /#/ && share.deliver
redirect_to #profile, notice: 'email sent'
else
redirect_to #profile, notice: 'email failed'
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_profile
#profile = Profile.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def profile_params
params.require(:profile).permit(:user_id, :first_name, :last_name, :dob, :email, :mobile, :address, :suburb, :postcode, :city, :state, :country)
end
end
Share Mailer:
class Share < ActionMailer::Base
default_url_options[:host] = "localhost:3000"
default from: "from#example.com"
def profile(profile, destination)
#profile = profile
mail(to: destination, subject: "sent you stuff")
end
end
Current error:
ActionController::ActionControllerError in ProfilesController#email_profile
Cannot redirect to nil!
I think it has something to do with the :id parameter not being passed through after the email is sent.. but I'm a newbie so I don't really know what I'm talking about.. appreciate any guidance so I can fix this and also better understand ROR :)
You probably need to find a #profile first. I guess something like Profile.find(params[:profile_id]) is missing.
Hi there I am getting a NoMethodError in Users#show error in my Rails 3.2 app using devise.
Error on line 2 of my show below:
<strong>Firstname:</strong>
<%= #user.firstname %>
</p>
<p>
<strong>dateofbirth:</strong>
(If I remove the first name box it does the error for dateofbirth, etc.)
I'm using devise for my users, but generated a user controller in which to place my views.
I'm not sure what the problem is because I ran my migration and firstname exists in the schema
Here's the user controller:
class UsersController < ApplicationController
# before_action :set_user, only: [:show, :edit, :update, :destroy]
def find
#user = User.new
end
def show
#user = User.find(params[:id])
end
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User 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
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:username, :firstname, :dateofbirth, :lastname, :gender, :location, :email, :password)
end
end
Your controller has two show methods defined. Try removing the second one. I believe the empty show method is overwriting your filled-in show method. In your view, #user doesn't exist so it evaluates to nil. Nil has neither a firstname method, nor dateofbirth method. Hence the NoMethodError.