2016-10-27 31 views
0

在rails上的教程之后,当尝试执行method: :delete操作时出现此错误。Rails没有移植到Heroku的SQLITE本地主机PGSQL

ActiveRecord::StatementInvalid (PG::DatatypeMismatch: ERROR: argument of WHERE must be type boolean, not type integer

这是我破坏方法。

def destroy 
@user_stock = current_user.user_stocks.where(stock_id: params[:id]).first 
@user_stock.destroy 
respond_to do |format| 
    format.html { redirect_to my_portfolio_path, notice: "#{@user_stock.stock.ticker} was removed from portfolio." } 
    format.json { head :no_content } 
end 
end 

我看了一个问题上herefindfind_by需要被正确的使用,但它只是让我感到困惑。

UserStocksController

class UserStocksController < ApplicationController 
 
    before_action :set_user_stock, only: [:show, :edit, :update, :destroy] 
 

 
    # GET /user_stocks 
 
    # GET /user_stocks.json 
 
    def index 
 
    @user_stocks = UserStock.all 
 
    end 
 

 
    # GET /user_stocks/1 
 
    # GET /user_stocks/1.json 
 
    def show 
 
    end 
 

 
    # GET /user_stocks/new 
 
    def new 
 
    @user_stock = UserStock.new 
 
    end 
 

 
    # GET /user_stocks/1/edit 
 
    def edit 
 
    end 
 

 
    # POST /user_stocks 
 
    # POST /user_stocks.json 
 
    def create 
 
    if params[:stock_id].present? 
 
     @user_stock = UserStock.new(stock_id: params[:stock_id], user: current_user) 
 
    else 
 
     stock = Stock.find_by_ticker(params[:stock_ticker]) 
 
     if stock 
 
     @user_stock = UserStock.new(user: current_user, stock: stock) 
 
     else 
 
     stock = Stock.new_from_lookup(params[:stock_ticker]) 
 
     if stock.save 
 
      @user_stock = UserStock.new(user:current_user, stock: stock) 
 
     else 
 
      @user_stock = nil 
 
      flash[:error] = "Stock is not available" 
 
     end 
 
     end 
 
    end 
 
    
 
    respond_to do |format| 
 
     if @user_stock.save 
 
     format.html { redirect_to my_portfolio_path, notice: "Stock #{@user_stock.stock.ticker} was saved" } 
 
     format.json { render :show, status: :created, location: @user_stock } 
 
     else 
 
     format.html { render :new } 
 
     format.json { render json: @user_stock.errors, status: :unprocessable_entity } 
 
     end 
 
    end 
 
    end 
 

 
    # PATCH/PUT /user_stocks/1 
 
    # PATCH/PUT /user_stocks/1.json 
 
    def update 
 
    respond_to do |format| 
 
     if @user_stock.update(user_stock_params) 
 
     format.html { redirect_to @user_stock, notice: 'User stock was successfully updated.' } 
 
     format.json { render :show, status: :ok, location: @user_stock } 
 
     else 
 
     format.html { render :edit } 
 
     format.json { render json: @user_stock.errors, status: :unprocessable_entity } 
 
     end 
 
    end 
 
    end 
 

 
    # DELETE /user_stocks/1 
 
    # DELETE /user_stocks/1.json 
 
    def destroy 
 
    @user_stock = current_user.user_stocks.where(stock_id: params[:id]).first 
 
    @user_stock.destroy 
 
    respond_to do |format| 
 
     format.html { redirect_to my_portfolio_path, notice: "#{@user_stock.stock.ticker} was removed from portfolio." } 
 
     format.json { head :no_content } 
 
    end 
 
    end 
 

 
    private 
 
    # Use callbacks to share common setup or constraints between actions. 
 
    def set_user_stock 
 
    @user_stock = UserStock.find_by(params[:id]) 
 
    end 
 

 
    # Never trust parameters from the scary internet, only allow the white list through. 
 
    def user_stock_params 
 
     params.require(:user_stock).permit(:user_id, :stock_id) 
 
    end 
 
end

my_portfolio视图呈现的局部_list

<table class="table table-striped"> 
 
\t <thead> 
 
\t \t <tr> 
 
\t \t \t <th>Name</th> 
 
\t \t \t <th>Symbol</th> 
 
\t \t \t <th>Current Price</th> 
 
\t \t \t <% if @user.id == current_user.id%> 
 
\t \t \t <th>Actions</th> 
 
\t \t \t <%end%> 
 
\t \t </tr> 
 
\t </thead> 
 
\t <tbody> 
 
\t \t <%@user_stocks.each do |us|%> 
 
\t \t <tr> 
 
\t \t \t <td><%=us.name%></td> 
 
\t \t \t <td><%=us.ticker%></td> 
 
\t \t \t <td><%=us.price%></td> 
 
\t \t \t <% if @user.id == current_user.id%> 
 
\t \t \t <td> 
 
\t \t \t \t <%= link_to 'Delete', user_stock_path(us), :method => :delete, 
 
\t \t \t \t \t \t \t \t \t \t \t \t \t \t :data => {:confirm => "You sure you want to delete #{us.name} from your portfolio?"}, 
 
\t \t \t \t \t \t \t \t \t \t \t \t \t \t :class => "btn btn-xs btn-danger"%> 
 
      </td> 
 
\t \t \t <%end%> 
 
\t \t </tr> 
 
\t \t <%end%> 
 
\t </tbody> 
 
</table>

回答

0

你的问题可能是你set_user_stock方法:

def set_user_stock 
    @user_stock = UserStock.find_by(params[:id]) 
end 

UserStock.find_by(params[:id])只是一种说法更短的方式:

UserStock.where(params[:id]).first 

所以,如果params[:id]是,比方说,6,你最终会发送此SQL到数据库:

select * 
from user_stocks 
where 6 

,并有你的错误:6不是SQL boolean值,where 6没有意义。 SQLite对SQL的解释很松散,所以它会接受像where 6这样的废话,但PostgreSQL正确地抱怨。

有两个教训在这里:

  1. set_user_stock方法应该是这样的:

    def set_user_stock 
        @user_stock = UserStock.find(params[:id]) 
    end 
    

    def set_user_stock 
        @user_stock = UserStock.find_by(:id => params[:id]) 
    end 
    

    使用find版本,如果你希望永远请致电set_user_stock并附上有效的params[:id]find_by如果你想自己处理@user_stock.nil?

  2. 永远不要在一个数据库之上开发并在另一个数据库上部署。所以如果你想在SQLite上开发并部署其他任何东西,那么双打。你应该总是发展,测试和部署使用相同的数据库(一路下跌到数据库版本),ActiveRecord的不会保护你从任何数据库可移植性的困难的部分。

+0

你真正的mvp – Jack

1

好吧,从我有这个我的猜测。同样,你只发布了部分,所以我不知道这一切是如何涉及,但我的猜测是,你加入ID是这样的:

<%= link_to 'Delete', user_stock_path(id: us.id), :method => :delete, 
                 :data => {:confirm => "You sure you want to delete #{us.name} from your portfolio?"}, 
                 :class => "btn btn-xs btn-danger"%> 
+0

undefined method stock_id – Jack

+0

你可以发布你的整个控制器吗? – codigomonstruo

+0

只是做了,在我的问题 – Jack

相关问题