Ruby on Rails "Couldnt find status id" - ruby-on-rails

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?

Related

Parsing Api with Httparty NoMethodError: undefined method `each' for nil:NilClass

Hi I am parsing JSON API from https://api.commissionfactory.com/V1/ via rake task
desc "run feed"
task :mr => :environment do
include HTTParty
url = 'https://api.commissionfactory.com/V1/Affiliate/Merchants?apiKey=fakekey&status=Joined'
response = HTTParty.get(url).parsed_response
response.each do |item|
Vendor.find_or_create_by(name: item['Name'])
end
end
I can get the json data but not parse it via response.each or response.map
When I try with the code above I get a
rake aborted!
NoMethodError: undefined method `each' for nil:NilClass
when I puts response I get the data below as expected:
{"Id"=>201, "DateCreated"=>"2014-04-10T10:47:35.747", "DateModified"=>"2017-06-11T00:00:32.11", "Name"=>"Tony's Furniture", "AvatarUrl"=>"https://c.url.com/io/39BD094A-24B5-4659-8A7A-FE6E023E9ED8.png"}
and I can manipulate the data via
response.map do |item|
puts item['Name']
puts item['Category']
puts item['TargetUrl']
puts item['Summary']
puts item['TrackingUrl']
puts item['AvatarUrl']
end
but as soon as i try to create or save records i get the same issue.
Vendors Controller
class VendorsController < ApplicationController
before_action :set_vendor, only: [:show, :edit, :update, :destroy]
# GET /vendors
# GET /vendors.json
def index
#vendors = Vendor.all
end
# GET /vendors/1
# GET /vendors/1.json
def show
#products = #vendor.products.find(params[:id])
end
# GET /vendors/new
def new
#vendor = Vendor.new
end
# GET /vendors/1/edit
def edit
end
# POST /vendors
# POST /vendors.json
def create
#vendor = Vendor.new(vendor_params)
respond_to do |format|
if #vendor.save
format.html { redirect_to #vendor, notice: 'Vendor was successfully created.' }
format.json { render :show, status: :created, location: #vendor }
else
format.html { render :new }
format.json { render json: #vendor.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /vendors/1
# PATCH/PUT /vendors/1.json
def update
respond_to do |format|
if #vendor.update(vendor_params)
format.html { redirect_to #vendor, notice: 'Vendor was successfully updated.' }
format.json { render :show, status: :ok, location: #vendor }
else
format.html { render :edit }
format.json { render json: #vendor.errors, status: :unprocessable_entity }
end
end
end
# DELETE /vendors/1
# DELETE /vendors/1.json
def destroy
#vendor.destroy
respond_to do |format|
format.html { redirect_to vendors_url, notice: 'Vendor was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_vendor
#vendor = Vendor.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def vendor_params
params.require(:vendor).permit(:name, :description, :Category, :TargetUrl, :Summary, :TrackingUrl, :AvatarUrl)
end
end
Vendor Model
class Vendor < ApplicationRecord
has_many :products
has_many :brands
end
While I have parsed xml data with nokogiri this is my first json parse with httparty. Can you please point out why I cannot seem to parse the data into the rails vendor db
With a little help from a mentor we were able to discover that the
include HTTParty
in my task
desc "run feed"
task :mr => :environment do
include HTTParty
url = 'https://api.commissionfactory.com/V1/Affiliate/Merchants?apiKey=fakekey&status=Joined'
response = HTTParty.get(url).parsed_response
response.each do |item|
Vendor.find_or_create_by(name: item['Name'])
end
end
was throwing the error. with its removal, the task passed.
As an older library, the include statement imports the entire library, which in this case threw the error and was not related to my needs.

Devise create user and login on test setup

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.

Ruby on Rails API how to soft delete an user

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.

Devise - How to display user that updated others post

I would like users to be able to create/update my "Person" resource, including overwriting each other. Currently I'm able to capture the user who created the initial "Person" but i can't figure out how to capture and display the user that updated the resource.
For example if user 1 creates an item, then user 2 updates this item, I would like to display that this item was most recently edited by user 2.
Here's my controller, any help would be much appreciated thanks!
class PeopleController < ApplicationController
before_action :set_person, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /people
# GET /people.json
def index
#people = Person.all
end
# GET /people/1
# GET /people/1.json
def show
end
# GET /people/new
def new
#person = current_user.person.build
end
# GET /people/1/edit
def edit
end
# POST /people
# POST /people.json
def create
#person = current_user.person.build(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render action: 'show', status: :created, location: #person }
else
format.html { render action: 'new' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /people/1
# PATCH/PUT /people/1.json
def update
respond_to do |format|
if #person.update(person_params)
format.html { redirect_to #person, notice: 'Person was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# DELETE /people/1
# DELETE /people/1.json
def destroy
#person.destroy
respond_to do |format|
format.html { redirect_to people_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_person
#person = Person.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def person_params
params.require(:person).permit(:name, :twitter, :facebook, :instagram, :vine)
end
end
Simple way for doing it is to maintain the a column called updated_by and store the current user when its updated as #Andrey mentioned in previous comment.
But if your looking for a more extensive for tracking you can use auditable gem
You can check this out :
https://github.com/harley/auditable
Create updated_by column in posts table, and each time user updates the post, update the column updated_by by the value of current_user.

Rails 4 testing controller failure

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

Resources