app/controllers/categories_controller.rb:
class CategoriesController < ApplicationController
before_action :set_category, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /categories
# GET /categories.json
def index
#categories = Category.all
end
# GET /categories/1
# GET /categories/1.json
def show
if session[:cart] then
#cart = session[:cart]
else
#cart = {}
end
end
# GET /categories/new
def new
if current_user.admin?
#category = Category.new
end
end
# GET /categories/1/edit
def edit
if current_user.admin?
end
end
# POST /categories
# POST /categories.json
def create
if current_user.admin?
#category = Category.new(category_params)
respond_to do |format|
if #category.save
format.html { redirect_to #category, notice: 'Category was successfully created.' }
format.json { render :show, status: :created, location: #category }
else
format.html { render :new }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
end
# PATCH/PUT /categories/1
# PATCH/PUT /categories/1.json
def update
if current_user.admin?
respond_to do |format|
if #category.update(category_params)
format.html { redirect_to #category, notice: 'Category was successfully updated.' }
format.json { render :show, status: :ok, location: #category }
else
format.html { render :edit }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
end
# DELETE /categories/1
# DELETE /categories/1.json
def destroy
if current_user.admin?
#category.destroy
respond_to do |format|
format.html { redirect_to categories_url, notice: 'Category was successfully destroyed.' }
format.json { head :no_content }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_category
#category = Category.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def category_params
params.require(:category).permit(:name, :desc)
end
end
In the controller above I'm preventing standard users to create, update or destroy categories by checking if current_user.admin?. But it's causing some problems in the tests.
test/controllers/categories_controller.rb:
require 'test_helper'
class CategoriesControllerTest < ActionController::TestCase
setup do
#category = categories(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:categories)
end
test "should get new" do
get :new
assert_response :success
end
test "should create category" do
assert_difference('Category.count') do
post :create, category: { desc: #category.desc, name: #category.name }
end
assert_redirected_to category_path(assigns(:category))
end
test "should show category" do
get :show, id: #category
assert_response :success
end
test "should get edit" do
get :edit, id: #category
assert_response :success
end
test "should update category" do
patch :update, id: #category, category: { desc: #category.desc, name: #category.name }
assert_redirected_to category_path(assigns(:category))
end
test "should destroy category" do
assert_difference('Category.count', -1) do
delete :destroy, id: #category
end
assert_redirected_to categories_path
end
end
Because of the restriction, tests related with create, update or destroy are failing. I think I need to create an admin user and login on test setup. But I don't know how to do this.
I'm using Devise gem for users part of the app.
I'm running my tests with rake test:functionals. How can I simulate user create and login in my tests?
If you want to look to the whole project: https://github.com/mertyildiran/SCOR
You can use fixtures to create an admin user in the test database (you probably already have a test/fixtures/users.yml file), and Devise's Test helpers to sign in:
sign_in :user, users(:admin)
If your users are confirmable, remember to set a confirmed_at date.
Check out the Devise wiki article on testing Rails controllers.
Related
I am trying to integrate Twilio and my rails application to send different text messages based on what option is chosen and saved to the database in the form. However after studying the docs and viewing the example applications they provide (Send ETA Notifications), saving the completed form, no text message is sent and I cannot figure out why. I would love some suggestions
job_status are the options to choose from which the text message body needs to change with:
JOB_STATUSES = ["Wildey Que", "In Service-Bay", "Awaiting Approval",
"Awaiting Parts", "Jackson Collection Que", "Wildey Collection Que",
"Completed"]
message_sender.rb
class MessageSender
require 'twilio-ruby'
def self.send_message(job_id, host, to, message)
new.send_message(job_id, host, to, message)
end
def initialize
# To find TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN visit
# https://www.twilio.com/console
account_sid = ENV['---'] (These are entered)
auth_token = ENV['---']
#client = Twilio::REST::Client.new(account_sid, auth_token)
end
def send_message(job_id, host, to, message)
#client.messages.create(
from: twilio_number,
to: to,
body: message,
status_callback: "http://#{host}/jobs/#{job_id}"
)
end
private
def twilio_number
# A Twilio number you control - choose one from:
# https://www.twilio.com/console/phone-numbers/incoming
# Specify in E.164 format, e.g. "+16519998877"
ENV['+17652957305']
end
end
jobs_controller.rb
class JobsController < ApplicationController
before_action :set_job, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /jobs
# GET /jobs.json
def index
if(params.has_key? (:job_status))
#jobs = Job.where(job_status: params[:job_status]).order("created_at desc")
else
#jobs = Job.all.order("created_at desc")
end
end
# GET /jobs/1
# GET /jobs/1.json
def show
end
# GET /jobs/new
def new
#job = current_user.jobs.build
end
# GET /jobs/1/edit
def edit
end
#TWILLIO INITILIZATION
def send_initial_notification
#job.job_status = :Wildey_Que
if #job.save
message = 'Equip4you: Thanks for dropping your machine off, we will keep you updated here every step of the way'
notify(message)
else
redirect_with_error
end
end
def send_delivery_notification
#job.job_status = :Completed
if #job.save
message = 'Equip4you: Thank you for allowing us to take care of your machine for you, if you have any further questions or concerns feel free to contact 425-9999'
notify(message)
else
redirect_with_error
end
end
#END TWILLIO INIT
# POST /jobs
# POST /jobs.json
def create
#job = current_user.jobs.build(job_params)
respond_to do |format|
if #job.save
format.html { redirect_to #job, notice: 'Job was successfully created.' }
format.json { render :show, status: :created, location: #job }
else
format.html { render :new }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /jobs/1
# PATCH/PUT /jobs/1.json
def update
respond_to do |format|
if #job.update(job_params)
format.html { redirect_to #job, notice: 'Job was successfully updated.' }
format.json { render :show, status: :ok, location: #job }
else
format.html { render :edit }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
# DELETE /jobs/1
# DELETE /jobs/1.json
def destroy
#job.destroy
respond_to do |format|
format.html { redirect_to jobs_url, notice: 'Job was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# TWILLIO INNIT
def notify(message)
MessageSender.send_message(
#job.id, request.host, #job.cell_number, message)
redirect_to jobs_url, notice: 'Message was delivered'
end
def redirect_with_error
message = "An error has occurred updating the ticket status"
redirect_to orders_url, flash: { error: message }
end
#TWILLIO INIT END
# Use callbacks to share common setup or constraints between actions.
def set_job
#job = Job.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def job_params
params.require(:job).permit(:job_status, :purchase_name, :contact_name, :cell_number, :home_number, :other_number, :other_number, :address, :machine_mod, :item_number, :serial_number, :concern, :accessories, :pickup_location, :paid, :invoice_number, :outcome, :avatar)
end
end
Routes.rb
require 'sidekiq/web'
Rails.application.routes.draw do
resources :jobs
devise_for :users
root to: 'jobs#index'
post '/jobs/new', to: 'jobs#new', as: 'initial_notifications'
post '/jobs/new', to: 'jobs#new', as: 'delivery_notifications'
routes.rb
require 'sidekiq/web'
Rails.application.routes.draw do
resources :jobs
devise_for :users
root to: 'jobs#index'
post '/jobs/new', to: 'jobs#new', as: 'initial_notifications'
post '/jobs/new', to: 'jobs#new', as: 'delivery_notifications'
Please check this def. It looks weird.
def twilio_number
# A Twilio number you control - choose one from:
# https://www.twilio.com/console/phone-numbers/incoming
# Specify in E.164 format, e.g. "+16519998877"
ENV['+17652957305']
end
My ruby application is throwing an error which has appeared all of a sudden. the error thrown is NoMethodError in JobsDevsController # listing=> undefined method `user_id' for nil:NilClass
The part of my code that throws this error in my controller is
def is_authorised
redirect_to root_path, alert: "You don't have permission..." unless current_user.id == #job.user_id
end
My Controller
class JobsDevsController < ApplicationController
before_action :set_jobs_dev , except: [:index, :new, :create, :show, :edit, :listing]
before_action :authenticate_user!, except: [:show, :listing]
before_action :is_authorised, only: [:listing, :budget, :description, :photo_upload, :location, :update, :show ]
# GET /jobs_devs
def index
#jobs_devs = JobsDev.all
end
# GET /jobs_devs/1
def show
end
# GET /jobs_devs/new
def new
#jobs_dev = current_user.jobs_devs.build
end
# def listing
# #jobs_dev = current_user.jobs_dev
# end
# GET /jobs_devs/1/edit
def edit
end
def budget
end
# POST /jobs_devs
def create
#jobs_dev = current_user.jobs_devs.build(jobs_dev_params)
if #jobs_dev.save!
redirect_to listing_jobs_dev_path(#jobs_dev), notice: 'Jobs dev was successfully created.'
else
render :new
end
end
# PATCH/PUT /jobs_devs/1
# def update
# if #jobs_dev.update(jobs_dev_params)
# redirect_to #jobs_dev, notice: 'Jobs dev was successfully updated.'
# else
# render :edit
# end
# end
def update
respond_to do |format|
if #jobs_dev.update(jobs_dev_params)
format.html { redirect_to #jobs_dev, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #jobs_dev }
else
format.html { render :edit }
format.json { render json: #jobs_dev.errors, status: :unprocessable_entity }
end
end
end
# DELETE /jobs_devs/1
def destroy
#jobs_dev.destroy
redirect_to jobs_devs_url, notice: 'Jobs dev was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_jobs_dev
#jobs_dev = JobsDev.find(params[:id])
end
def is_authorised
redirect_to root_path, alert: "You don't have permission..." unless current_user.id == #jobs_dev.user_id
end
# Only allow a trusted parameter "white list" through.
def jobs_dev_params
params.require(:jobs_dev).permit(:job_category, :job_type, :job_title, :job_description, :recurrence,
:budget, images: []
)
end
end
Please can you help with this senario
Make sure you set_job for listing actiton
You may need to add to the listing action directly
#job = current_user.job
or the better way to add it to before action of listing action and take order into consideration
Looks like your is_authorised method is looking for #job, which isn't set in your controller; rather, you assign #jobs_dev.
Update the method to the following:
def is_authorised
redirect_to root_path, alert: "You don't have permission..." unless current_user.id == #jobs_dev.user_id
end
I'm not sure that's sufficient, as you're skipping setting this in your before_action:
before_action :set_jobs_dev , except: [:index, :new, :create, :show, :edit, :listing]
It looks as if you'll need to remove :listing from the except clause there.
Try both of these things and it should work again. Let me know if you've any questions or have any issues with this :)
I am able to soft delete an user from the main application.
Here are the details.
The user URL is:
http://0.0.0.0:3000/users/4c7fa12c-3d58-480b-a823-6c67d6e7f0fe.json
Which is presenting a JSON result like this:
{"id":"4c7fa12c-3d58-480b-a823-6c67d6e7f0fe","name":"John","status":"Active","created_at":"2015-11-10T18:31:27.000+00:00","updated_at":"2015-11-10T18:38:20.000+00:00"}
I can do a soft delete by using an inactivation this way:
http://0.0.0.0:3000/users/4c7fa12c-3d58-480b-a823-6c67d6e7f0fe/inactivate
Here is my inactivate method in the users controller:
def inactivate
#user.update status: 'Inactive'
redirect_to users_url
end
The result is shown when reload the user URL:
{"id":"4c7fa12c-3d58-480b-a823-6c67d6e7f0fe","name":"John","status":"Inactive","created_at":"2015-11-10T18:31:27.000+00:00","updated_at":"2015-11-10T19:29:58.000+00:00"}
Now my user is "Inactive".
Here is my routes file:
Rails.application.routes.draw do
resources :wit_dims
resources :wokas
resources :posts
resources :languages
resources :users
root :to => "home#index"
resources :users do
get 'inactivate', on: :member
end
match 'inactivate', to: 'users#inactivate', via: 'delete'
#api
namespace :api do
namespace :v1 do
resources :users, only: [:index, :create, :show, :update, :destroy]
resources :posts, only: [:index, :create, :show, :update, :destroy]
end
end
end
How I can change this routes file and the API users controller to make the same king of inactivation through the API? I want more than a trivial solution using a PUT to change status of the user from Active to Inactive.
Here is my main application users controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy, :inactivate]
# 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 :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 inactivated.' }
format.json { head :no_content }
end
end
def inactivate
#user.update status: 'Inactive'
redirect_to users_url
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[:user]
end
end
Here is my API users controller:
class Api::V1::UsersController < Api::V1::BaseController
before_action :set_user, only: [:show, :update, :destroy]
def show
render(json: Api::V1::UserSerializer.new(#user).to_json)
end
def update
if #user.update_attributes(user_params)
render(
json: Api::V1::UserSerializer.new(#user).to_json,
status: 200,
location: api_v1_user_path(#user.id)
)
else
return api_error(status: 422, errors: #tbm.errors)
end
end
def index
users = User.all
render(
json: ActiveModel::ArraySerializer.new(
users,
each_serializer: Api::V1::UserSerializer,
root: 'users'
)
)
end
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 :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
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
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :status).delete_if{ |k,v| v.nil? }
end
end
Basically I would like to be able to call an inactivate method through the API which is going to change the status from Active to Inactive, instead of physically deleting / destroying the user.
I used PUT and executed an updated on the status attribute to mark the user as Inactive.
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
I'm doing this treehouse project, some kind of social network built with ruby on rails (http://teamtreehouse.com/library/building-social-features-in-ruby-on-rails-2).
I was trying to make a user unable to update an existing status from another user and got stuck. This is my statuses_controller.rb:
class StatusesController < ApplicationController
before_filter :authenticate_user!, only: [:new, :create, :edit, :update]
before_action :set_status, only: [:show, :edit, :update, :destroy]
# GET /statuses
# GET /statuses.json
def index
#statuses = Status.order("created_at DESC").to_a
end
# GET /statuses/1
# GET /statuses/1.json
def show
end
# GET /statuses/new
def new
#status = Status.new
end
# GET /statuses/1/edit
def edit
end
# POST /statuses
# POST /statuses.json
def create
#status = current_user.statuses.new(status_params)
respond_to do |format|
if #status.save
format.html { redirect_to #status, notice: 'Status was successfully created.' }
format.json { render action: 'show', status: :created, location: #status }
else
format.html { render action: 'new' }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /statuses/1
# PATCH/PUT /statuses/1.json
def update
#status = current_user.statuses.find(params[:id])
params[:status].delete(:user_id) if params[:status].has_key?(:user_id)
respond_to do |format|
if #status.update(status_params)
format.html { redirect_to #status, notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# DELETE /statuses/1
# DELETE /statuses/1.json
def destroy
#status.destroy
respond_to do |format|
format.html { redirect_to statuses_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_status
#status = Status.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def status_params
params.require(:status).permit(:content, :user_id)
end
end
While testing this (if a user 'should update status for the current user when logged in'), I got the following error:
1) Error:
StatusesControllerTest#test_should_update_status_for_the_current_user_when_logged_in:
ActiveRecord::RecordNotFound: Couldn't find Status with id=980190962 [WHERE "statuses"."user_id" = ?]
app/controllers/statuses_controller.rb:45:in `update'
test/controllers/statuses_controller_test.rb:76:in `block in <class:StatusesControllerTest>'
2) Error:
StatusesControllerTest#test_should_update_status_when_logged_in:
ActiveRecord::RecordNotFound: Couldn't find Status with id=980190962 [WHERE "statuses"."user_id" = ?]
app/controllers/statuses_controller.rb:45:in `update'
test/controllers/statuses_controller_test.rb:70:in `block in <class:StatusesControllerTest>'
12 tests, 24 assertions, 0 failures, 2 errors, 0 skips
This is my statuses_controller_test.rb:
test "should update status when logged in" do
sign_in users(:gustavo)
put :update, id: #status, status: { content: #status.content }
assert_redirected_to status_path(assigns(:status))
end
test "should update status for the current user when logged in" do
sign_in users(:gustavo)
put :update, id: #status, status: { content: #status.content, user_id: users(:paul).id }
assert_redirected_to status_path(assigns(:status))
assert_equal assigns(:status).user_id, users(:gustavo).id
end
And that's my fixture users.yml:
gustavo:
first_name: "Gustavo"
last_name: "Paiva"
email: "gustavorpaiva#gmail.com"
profile_name: "grpaiva"
paul:
first_name: "Paul"
last_name: "McCartney"
email: "paulmccartney#gmail.com"
profile_name: "paulpaul"
I'm using Rails 4.0.4, and I've already made some fixtures on treebook's code so it could work perfectly (i think it was made with Rails 2.x). Should that be the case or am I missing something here?
Ps.: This is my project link, before making this changes http://sheltered-everglades-2797.herokuapp.com/
Thanks!
Try #status.id in the put method instead of just #status
test "should update status when logged in" do
sign_in users(:gustavo)
put :update, id: #status.id, status: { content: #status.content }
assert_redirected_to status_path(assigns(:status))
end
If that doesn't work, can you post the code for how is the #status object is built in the controller test?