1

RailsでPostgresを使用しています。ブール値を返す副選択を含むクエリがありますが、Postgresは常に't'またはのような文字列を返します'f'。しかし、生成されたJSONには、実際のブール値が必要です。

これは私の質問です:

SELECT
  *,
  EXISTS (
    SELECT TRUE
    FROM measurement
    JOIN experiment ON measurement.experiment_id = experiment.id
    JOIN location ON experiment.location_id = location.id
    WHERE location.map_id = map.id
    LIMIT 1
  ) AS measurements_exist
FROM "map"

THEN true使用するかどうTHEN 1かは関係ありませんTHEN 'true'。常に文字列を取得します。したがって、私のJSON応答は常に次のようになります。

[
  {"id":8, ..., "measurements_exist":"f"},
  {"id":9, ..., "measurements_exist":"t"}
]

しかし、それは次のようになります(!):

[
  {"id":8, ..., "measurements_exist":false},
  {"id":9, ..., "measurements_exist":true}
]

これを正しく機能させる方法はありますか?

ありがとうございました!


ソリューション:

対応するモデル(ここでは:)に、値の変換にMap使用する属性アクセサーを指定するだけです。value_as_booleanそのため、コントローラーが値にアクセスしようとするたびに、属性アクセサーメソッドが自動的に使用されます。

コントローラコード:

class MapsController < ApplicationController
  def index
    select = ["*"]
    select.push(measurements_exist) # This will just insert the string returned by the 'measurements_exist' method
    maps = Map.select(select) # Results in 'SELECT *, EXISTS (...) AS measurements_exist FROM "map"'
    render json: maps
  end

  private

  def measurements_exist
    "EXISTS (
      SELECT TRUE
      FROM measurement
      JOIN experiment ON measurement.experiment_id = experiment.id
      JOIN location ON experiment.location_id = location.id
      WHERE location.map_id = map.id
      LIMIT 1
    ) AS measurements_exist"
  end
end

モデルコード:

class Map < ActiveRecord::Base
  def measurements_exist
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(self[:measurements_exist])
  end
end

結果のJSON:

[
  {"id":7, ..., "measurements_exist":false},
  {"id":6, ..., "measurements_exist":true}
]
4

4 に答える 4

4

ActiveRecordには、ActiveRecord::ConnectionAdapters::Column.value_to_booleantrueのような値をRuby値に変換するために内部的に使用するというメソッドがありtrueます。

コードで使用できます。

于 2013-02-17T12:43:19.510 に答える
0

Railsからモデルをクエリすると、DBアダプターがスキーマからフィールドのタイプを判別できるため、ブールフィールドが自動的にtrue/falseに変換されます。dbからカスタムブールフィールドを選択した場合-アダプタはそれについて何も認識しないため、文字列「t」または「f」が返され、手動で変換する必要があります。

期待されるブール値を取得する方法の1つ:

  1. DBMS側で提供されたSQLクエリを使用してビューを作成します(たとえば、PostgreSQLのCREATE VIEW ...ステートメントを参照してください)。ビューフィールドにはタイプがあるため、ブールフィールドはアプリで自動的に変換されます。と呼ばれると仮定しmap_with_measurementsます。

  2. モデルMapWithMeasurementを作成し、に配置しmodels/map_with_measurement.rbます。 class MapWithMeasurement < ActiveRecord::Base; end

  3. を使用しMapWithMeasurement.find_allます。

于 2013-02-17T12:23:23.577 に答える
0

wannabe_boolgemを使用できます。 https://github.com/prodis/wannabe_bool

このgemは、#to_bString、Integer、Symbol、およびNilClassクラスのメソッドを実装します。

class Map < ActiveRecord::Base
  def measurements_exist
    self[:measurements_exist].to_b
  end
end
于 2014-10-30T01:21:00.587 に答える
0

別の解決策は次のとおりです。

boolean = (value_from_postgres =~ /^t$/i) == 0

't'のvalue_from_postgresをブール値trueに変換するか、'f'をブール値falseに変換します

$irb
2.2.1 :001 > value_from_postgres = 't'
 => "t" 
2.2.1 :002 > (value_from_postgres =~ /^t$/i) == 0
 => true 
2.2.1 :003 > value_from_postgres = 'f'
 => "f" 
2.2.1 :004 > (value_from_postgres =~ /^t$/i) == 0
 => false 

文字列「true」または「false」を期待している場合は、この行の通常の式を/ ^ true $/iに一致するように変更できます。これは、任意の正規表現への一致をブール値のtrueに変換するように記述できるため、ターナリやジェムを使用するよりも柔軟性があります。

三元を使用すると、次のようになります。

boolean = value_from_postgres.eql?('t') ? true : false
于 2016-03-25T21:47:30.717 に答える