Rails没有将SQLITE localhost移植到Heroku PGSQL

时间:2016-10-27 23:30:57

标签: ruby-on-rails postgresql sqlite heroku rails-activerecord

关于rails的教程,我在尝试method: :delete操作时遇到此错误。

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

我在here上阅读了关于findfind_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
&#13;
&#13;
&#13;

my_portfolio视图呈现部分_list

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

2 个答案:

答案 0 :(得分: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"%>

答案 1 :(得分: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中的布尔值,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
    

    如果您希望始终使用有效findset_user_stock致电params[:id],如果您想自己处理find_by,请使用@user_stock.nil?版本

  2. 永远不要在一个数据库上开发并在另一个数据库上部署。如果您正在尝试在SQLite上开发并在其他任何方面进行部署,那么这一点也是如此。您应该始终使用相同的数据库(一直到数据库版本)进行开发,测试和部署,ActiveRecord不会保护您免受数据库可移植性的任何困难部分的影响。