Ruby Rails,更改的数据库现在有错误未找到 TypeError
Ruby on Rails, changed database now have error not found TypeError
我不太确定发生了什么,但基本上在我的评论中 table 在我的数据库中我做了以下迁移:
def change
remove_column :reviews, :name, :string
add_column :reviews, :user_id, :integer
end
因此删除名称列并添加 user_id 列。然后我 运行 rake db:migrate 和 rake db:setup,通过 rails 打开了 rails 服务器,现在有这个错误:
ProductsController 中的类型错误#index
无法将 nil 转换为 String
def record_not_found
flash[:alert] = "Cannot find record number " + params[:id] + ".
Displaying all records."
redirect_to root_path
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
# make these methods available / visible in views
helper_method :the_date, :active_menu, :admin? , :logged_in?, :logged_in_as, :acting_role
# from an error generated when a request is
# made for a record with an 'id' that does not exist
rescue_from ActiveRecord::RecordNotFound,
:with => :record_not_found
private # these methods below can only be called by the object itself
def record_not_found
flash[:alert] = "Cannot find record number " + params[:id] + ".
Displaying all records."
redirect_to root_path
end
Products_controller.rb :
class ProductsController < ApplicationController
# When this controller is called, this method is always run first.
# The method 'set_product' found below, will be called for 'only' those
# actions indicated. Used to retrieve object data from the database.
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_filter :check_authorization, except: [:index, :show, :search ]
# GET /products
# This action uses the class method 'all' sent to the classs Product to get all products
# similar to "SELECT * FROM PRODUCTS" , "@products" represents a collection of different
# product objects. Notice it is plural. Ordered by product title.
def index
# @products = Product.all.order :title
@products = Product.order(:title).page(params[:page]).per(6)
end
# GET /products/1
# The 'before_action' method above causes the private set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id. The retrieved database record is used to create an instance variable @product .
# The associated view 'show.html.erb' is called - using the instance variable @product .
def show
end
# GET /products/new
# A new empty Product object '@product' is created, all attributes are blank.
# This empty instance variable is sent to the view 'new.html.erb', @product is
# used in the blank form when entering new values.
def new
@product = Product.new
end
# GET /products/1/edit
# The 'before_action' method above causes the private set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id. The retrieved database record is used to create an instance variable @product .
# The associated view 'edit.html.erb' is called - using the instance variable @product,
# @product is used in the blank form when editing existing values.
def edit
end
# POST /products
# product_params is a hash object with all attribute values populated from a form used
# in 'new' above. The attributes in product_params are used in a new method to create
# a new product object. If the object's values are saved to the database then a flash
# notice is displayed, else the 'new' action is called again so a user can alter any errors.
def create
@product = Product.new(product_params)
if @product.save
redirect_to @product, notice: 'Product was successfully created.'
else
render action: 'new'
end
end
# PATCH/PUT /products/1
# this update action is run after a form is used to edit a record.
# The 'before_action' method above causes the private 'set_product' method to be called
# which instantiates a @product object from the database. This object is then updated with
# a call to product_params. The private method 'product_params'checks that the attributes
# used from the form are permitted.
# If successful this action redirects the user to show.html.erb or it will again
# render / display the edit form to correct any invalid data
# When editing, the file_field img_url textbox holds the value of a product's newly
# browsed filename, while the textbox img_url displays any existing filename.
# If a new filename has not been selected the file_field will remain empty but will
# be used to update the product's record.
def update
# temp_url_string is used to temporarily save from the database, an existing product's
# img_url filename.
temp_url_string = Product.find(params[:id]).img_url
if @product.update(product_params)
# if product's img_url attribute from the form is blank
if @product.img_url.empty?
# then a copy of the filename string is assigned to the img_url attribute
@product.update_attribute(:img_url, temp_url_string)
end
# redirect_to @product, notice: 'Product was successfully updated.'
# redirect_to @product, notice: "'" + @product.title + "'" + " was successfully updated."
redirect_to @product, notice: "'#{@product.title}' was successfully updated."
else
render action: 'edit'
end
end
# DELETE /products/1
# The 'before_action' method above causes the private set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id. The retrieved database record is used to create an instance variable @product .
# This object is then sent the message 'destroy' to delete the record from the database.
# A redirection method, redirects to the products_path (products_url) which means ... products#index
def destroy
@product.destroy
redirect_to products_url
end
# 'fuzzy_search' assigns to an instance variable collection '@products' all objects which include some
# of the search_string in their title, the collection is ordered by title.
# If there are some products to display, this action redirects the user to the 'index' action.
def search
# @products = Product.simple_search(params[:search_string])
products = Product.fuzzy_search2(params[:search_string])
@products = Kaminari.paginate_array(products.order :title).page(params[:page]).per(6)
if products.empty?
flash.now[:alert] = "No records found - displaying all records ..."
#@products = Product.all.order :title
@products = Product.order(:title).page(params[:page]).per(6)
end
render :action => "index"
end
def multi_find
# call a Product class method, using two parameters; a category unique identifier and a search string (author or title)
products = Product.multi_find(params[:cat_id], params[:search_string])
#
@products = Kaminari.paginate_array(products.order :title).page(params[:page]).per(6)
# if no products have been found
if products.empty?
# display a notice
flash.now[:alert] = "No records found - displaying all records ..."
# then display all products
@products = Product.order(:title).page(params[:page]).per(6)
end
# use the index view
render :action => "index"
end
private
# The 'before_action' method above causes the private 'set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id, the retrieved database record is used to create an instance variable @product .
# This class method 'find' is similar to "SELECT * FROM PRODUCTS WHERE PRODUCT.ID = params[:id]"
def set_product
@product = Product.find(params[:id])
end
# This private method is called by the actions; create and update.
# 'product_params' checks that only permitted attributes are allowed.
# A hash 'params' of these parameter attributes and associated values is returned.
def product_params
params.require(:product).permit(:title, :description, :img_url, :price, :date_published, :author_name, :stock_level,:genre)
# returns 'params' a hash collection of keys and associated values.
end
end
ProductsController#index 中似乎有 ActiveRecord::RecordNotFound 错误,
所以方法 record_not_found 使用参数 [:id] = nil 调用,
这反过来会导致这一行的 TypeError:
flash[:alert] = "Cannot find record number " + nil + ".
Displaying all records."
无论如何,更准确的答案需要查看 ProductsController
我不太确定发生了什么,但基本上在我的评论中 table 在我的数据库中我做了以下迁移:
def change
remove_column :reviews, :name, :string
add_column :reviews, :user_id, :integer
end
因此删除名称列并添加 user_id 列。然后我 运行 rake db:migrate 和 rake db:setup,通过 rails 打开了 rails 服务器,现在有这个错误:
ProductsController 中的类型错误#index 无法将 nil 转换为 String
def record_not_found
flash[:alert] = "Cannot find record number " + params[:id] + ".
Displaying all records."
redirect_to root_path
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
# make these methods available / visible in views
helper_method :the_date, :active_menu, :admin? , :logged_in?, :logged_in_as, :acting_role
# from an error generated when a request is
# made for a record with an 'id' that does not exist
rescue_from ActiveRecord::RecordNotFound,
:with => :record_not_found
private # these methods below can only be called by the object itself
def record_not_found
flash[:alert] = "Cannot find record number " + params[:id] + ".
Displaying all records."
redirect_to root_path
end
Products_controller.rb :
class ProductsController < ApplicationController
# When this controller is called, this method is always run first.
# The method 'set_product' found below, will be called for 'only' those
# actions indicated. Used to retrieve object data from the database.
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_filter :check_authorization, except: [:index, :show, :search ]
# GET /products
# This action uses the class method 'all' sent to the classs Product to get all products
# similar to "SELECT * FROM PRODUCTS" , "@products" represents a collection of different
# product objects. Notice it is plural. Ordered by product title.
def index
# @products = Product.all.order :title
@products = Product.order(:title).page(params[:page]).per(6)
end
# GET /products/1
# The 'before_action' method above causes the private set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id. The retrieved database record is used to create an instance variable @product .
# The associated view 'show.html.erb' is called - using the instance variable @product .
def show
end
# GET /products/new
# A new empty Product object '@product' is created, all attributes are blank.
# This empty instance variable is sent to the view 'new.html.erb', @product is
# used in the blank form when entering new values.
def new
@product = Product.new
end
# GET /products/1/edit
# The 'before_action' method above causes the private set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id. The retrieved database record is used to create an instance variable @product .
# The associated view 'edit.html.erb' is called - using the instance variable @product,
# @product is used in the blank form when editing existing values.
def edit
end
# POST /products
# product_params is a hash object with all attribute values populated from a form used
# in 'new' above. The attributes in product_params are used in a new method to create
# a new product object. If the object's values are saved to the database then a flash
# notice is displayed, else the 'new' action is called again so a user can alter any errors.
def create
@product = Product.new(product_params)
if @product.save
redirect_to @product, notice: 'Product was successfully created.'
else
render action: 'new'
end
end
# PATCH/PUT /products/1
# this update action is run after a form is used to edit a record.
# The 'before_action' method above causes the private 'set_product' method to be called
# which instantiates a @product object from the database. This object is then updated with
# a call to product_params. The private method 'product_params'checks that the attributes
# used from the form are permitted.
# If successful this action redirects the user to show.html.erb or it will again
# render / display the edit form to correct any invalid data
# When editing, the file_field img_url textbox holds the value of a product's newly
# browsed filename, while the textbox img_url displays any existing filename.
# If a new filename has not been selected the file_field will remain empty but will
# be used to update the product's record.
def update
# temp_url_string is used to temporarily save from the database, an existing product's
# img_url filename.
temp_url_string = Product.find(params[:id]).img_url
if @product.update(product_params)
# if product's img_url attribute from the form is blank
if @product.img_url.empty?
# then a copy of the filename string is assigned to the img_url attribute
@product.update_attribute(:img_url, temp_url_string)
end
# redirect_to @product, notice: 'Product was successfully updated.'
# redirect_to @product, notice: "'" + @product.title + "'" + " was successfully updated."
redirect_to @product, notice: "'#{@product.title}' was successfully updated."
else
render action: 'edit'
end
end
# DELETE /products/1
# The 'before_action' method above causes the private set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id. The retrieved database record is used to create an instance variable @product .
# This object is then sent the message 'destroy' to delete the record from the database.
# A redirection method, redirects to the products_path (products_url) which means ... products#index
def destroy
@product.destroy
redirect_to products_url
end
# 'fuzzy_search' assigns to an instance variable collection '@products' all objects which include some
# of the search_string in their title, the collection is ordered by title.
# If there are some products to display, this action redirects the user to the 'index' action.
def search
# @products = Product.simple_search(params[:search_string])
products = Product.fuzzy_search2(params[:search_string])
@products = Kaminari.paginate_array(products.order :title).page(params[:page]).per(6)
if products.empty?
flash.now[:alert] = "No records found - displaying all records ..."
#@products = Product.all.order :title
@products = Product.order(:title).page(params[:page]).per(6)
end
render :action => "index"
end
def multi_find
# call a Product class method, using two parameters; a category unique identifier and a search string (author or title)
products = Product.multi_find(params[:cat_id], params[:search_string])
#
@products = Kaminari.paginate_array(products.order :title).page(params[:page]).per(6)
# if no products have been found
if products.empty?
# display a notice
flash.now[:alert] = "No records found - displaying all records ..."
# then display all products
@products = Product.order(:title).page(params[:page]).per(6)
end
# use the index view
render :action => "index"
end
private
# The 'before_action' method above causes the private 'set_product' method to be called.
# The class method 'find' is sent to the Product class to find an existing product by
# its id, the retrieved database record is used to create an instance variable @product .
# This class method 'find' is similar to "SELECT * FROM PRODUCTS WHERE PRODUCT.ID = params[:id]"
def set_product
@product = Product.find(params[:id])
end
# This private method is called by the actions; create and update.
# 'product_params' checks that only permitted attributes are allowed.
# A hash 'params' of these parameter attributes and associated values is returned.
def product_params
params.require(:product).permit(:title, :description, :img_url, :price, :date_published, :author_name, :stock_level,:genre)
# returns 'params' a hash collection of keys and associated values.
end
end
ProductsController#index 中似乎有 ActiveRecord::RecordNotFound 错误, 所以方法 record_not_found 使用参数 [:id] = nil 调用, 这反过来会导致这一行的 TypeError:
flash[:alert] = "Cannot find record number " + nil + ".
Displaying all records."
无论如何,更准确的答案需要查看 ProductsController