2016-10-27 73 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

相關問題