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