5

モデルの残りの部分を配置せずに、Rails で非常に迅速かつ汚い方法でクエリを実行しようとしています。これが悪い習慣であることはわかっていますが、ソリューション全体が整うまで、厳しい時間枠で迅速な結果が必要です.

重量に基づいて配送料が設定されている商品があります。重量はアイテムに格納され、価格はテーブル shipping_zone_prices に格納されます。現在私が行っているのは、重量が販売アイテムよりも重い最初の行に関連する価格を探すことだけです。

class Item < ActiveRecord::Base
  def shipping_price
    item_id = self.id
    shipping_price = ShippingZonePrice.find_by_sql(
      "SELECT z.price as price
       FROM shipping_zone_prices z, items i
       WHERE i.id = '#{item_id}'
       AND z.weight_g > d.weight
       ORDER BY z.weight_g asc limit 1")    
  end
end

この種の作品。SQL は仕事をしますが、アプリにプラグインすると次のようになります。

 <%= @item.shipping_price %> Shipping

次のように表示されます。

[#<ShippingZonePrice price: 12>] Shipping

この例では、'12' はデータベースから引き出された価格であり、正しいです。@item.shipping_price.class は「配列」を返します。[0] (またはその他の整数) を使用して配列にアクセスしようとすると、空白が返されます。

これにアクセスする別の方法はありますか、それとも基本的なものが欠けていますか?

4

5 に答える 5

7

priceインスタンスメソッドを定義しているので、存在するかどうかを返す必要があると思いますnil

次のようなことを試してください:

def shipping_price
  ShippingZonePrice.find_by_sql(
    "SELECT z.price as price
     FROM shipping_zone_prices z, items i
     WHERE i.id = '#{self.id}'
     AND z.weight_g > d.weight
     ORDER BY z.weight_g asc limit 1").first.try(:price)
end

次に、これはあなたのために働くはずです:

@item.shipping_price

空の配列を返す可能性があるため、このfirst.try(:price)部分が必要です。find_by_sql空の配列に対して次のようなことをしようとするとfirst.price、次の行に沿って例外が発生しますNoMethodError: undefined method 'price' for nil:NilClass

于 2012-09-19T14:46:27.823 に答える
5

これはfind_by_sql、データではなくモデルを返すためです。問題のデータを直接取得する場合は、次のようにします。

ShippingZonePrice.connection.select_value(query)

connection単一の値、単一の配列、配列の行、またはハッシュの行をフェッチできる直接アクセス ユーティリティ メソッドが多数あります。のドキュメントを 参照してくださいActiveRecord::ConnectionAdapters::DatabaseStatements

SQL を直接記述する場合と同様に、SQL インジェクションのバグを作成しないように細心の注意を払う必要があります。これが、通常、このメソッドを安全な場所にカプセル化することが最善である理由です。例:

class ShippingZonePrice < ActiveRecord::Base
  def self.price_for_item(item)
    self.connection.select_value(
      self.sanitize_sql(
        %Q[
          SELECT z.price as price
            FROM shipping_zone_prices z, items i
            WHERE i.id=?
              AND z.weight_g > d.weight
            ORDER BY z.weight_g asc limit 1
        ],
        item.id
      )
    )
  end
end
于 2012-09-19T15:03:39.810 に答える
3
@item.shipping_price.first.price

また

@item.shipping_price[0].price

それを指摘してくれたAtastorに感謝します!

で使用するAS priceと、結果のプロパティになりますfind_by_sqlprice

于 2012-09-19T14:40:13.440 に答える
1

あなたがアクセスしようとして失敗したと言っていないなら、私は[0]あなたが置きたいと言うでしょう

@item.shipping_price.first.price # I guess BSeven just forgot the .first. in his solution

ビューに...奇妙な

于 2012-09-19T14:45:48.400 に答える