Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

隠された宝石:ActiveRecordストア

Railsは、特定の状況に対応する多くの便利な組み込みツールを備えた大規模なフレームワークです。このシリーズでは、Railsの大規模なコードベースに隠されているあまり知られていないツールのいくつかを見ていきます。

この記事では、ActiveRecordのstoreに焦点を当てます およびstore_accessor メソッド。これらの方法はどちらも、JSONやYAMLなどのデータベース列に構造化データを格納するユースケースを対象としています。 store_accessor ゲッターメソッドstoreでモデルを詰まらせることなく、これらのデータから値を取得する便利な方法を提供します さらに一歩進んで、選択した形式にデータを透過的にシリアル化/逆シリアル化します。これがどこで役立つかを理解するために、JSONをリレーショナルデータベースに保存するためのオプションと、そうすることをお勧めするいくつかの理由についても見ていきます。

データベース内のJSON

この記事で「データベース」と言うときは、Railsコミュニティで最も広く使用されているリレーショナルデータベース、特にPostgreSQLとMySQLを指していることを明確にする必要があります。

JSONをリレーショナルデータベースに保存する理由を尋ねられるかもしれません。実際、リレーショナルデータベースの利点を活用する方法は、データを分割して関係にすることです。 それらの間はデータベース(外部キーなど)によって適用でき、データにインデックスを付けてクエリのパフォーマンスを向上させることができます。

リレーショナルデータベースモデルの欠点の1つは、データ構造を事前に知っておく必要があることです。 テーブルの各行で同じです。アプリケーションがこれらの要件を満たさないデータを中心に構築されている場合は、NoSQLデータベースを調査することをお勧めします。ただし、ほとんどのWebアプリでは、ほとんどのデータについて知っている~~ devil ~~リレーショナルデータベースに固執し、これらの動的データ構造に慎重に「振りかける」必要があります。このような場合、JSON列のようなものが非常に理にかなっています。

JSONとJSONB

PostgreSQLには2種類のJSON列があります:json およびjsonb 。主な違いは、jsonb は書き込み時に解析されます。つまり、データはデータベースがより高速にクエリできる形式で保存されます。注意点は、JSONはすでに解析されているため、テキストとして出力すると、ユーザーが入力した内容と正確に一致しなくなる可能性があることです。たとえば、重複するキーが削除されたり、キーの順序が元のキーと一致しなかったりする可能性があります。

PostgreSQLのドキュメントには、ほとんどの場合、jsonbと記載されています 特に理由がない限り、これが必要です。

MySQLのjson 列はjsonbと同様に動作します PostgreSQLで。 「ユーザーが入力した内容だけ」の出力をサポートするには、おそらくvarcharを使用する必要があります。 列または類似のもの。

JSON vs. Text

データを事前に解析できるようにすることに加えて、テキストフィールドに同じデータを格納する代わりにJSON列を使用すると、データ自体を使用するクエリが可能になります。たとえば、特定のキーと値のペアが列に存在するすべてのレコードをクエリできます。 Rails自体は、データベース固有であるため、多くの(存在する場合)JSON固有のクエリをサポートしていないことに注意してください。したがって、これらの機能を活用する場合は、SQLクエリを使用する必要があります。

RailsのJSON列

Railsはjsonの作成をサポートしています (およびjsonb PostgreSQLの場合)移行の列:

class CreateItems < ActiveRecord::Migration[7.0]
  def change
    create_table :items do |t|
      t.jsonb :user_attributes

    ...
    end
  end
end

この列を読むと、返される結果はハッシュです:

> Item.first.user_attributes
  Item Load (0.6ms)  SELECT "items".* FROM "items" ORDER BY "items"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> {"color"=>"text-red-400"}
> Item.first.update!(user_attributes: {color: "text-blue-400"})
> Item.first.user_attributes.dig(:color)
=> "text-blue-400"

ハッシュ属性ができたので、値を読み書きするためにいくつかのヘルパーメソッドをモデルに追加したくなるかもしれません:

class Item < ApplicationRecord
  def color=(value)
    self.user_attributes["color"] = value
  end

  def color
    user_attributes.dig("color")
  end
end

このようなメソッドは完全に機能しますが、処理するJSONキーがたくさんあると、すぐに扱いにくくなる可能性があります。幸い、Railsは私たちをカバーしてくれました。

ActiveRecordのストアとstore_accessor

JSONをデータベースに保存するには、シリアル化とアクセスの2つの側面があります。 jsonを使用している場合 -データベースに列を入力すると、シリアル化の側面について心配する必要はありません。 Railsとデータベースアダプタがそれを処理します(store_accessorに直接スキップできます )。データをテキスト列に保存する場合は、ActiveRecordのstore メソッドはあなたにぴったりです。これにより、列に書き込むデータが選択した形式にシリアル化されます。

ActiveRecordのストア

ActiveRecordにはstoreがあります 読み取りまたは列に書き込むデータを自動的にシリアル化する方法:

class Item < ApplicationRecord
  store :user_attributes, accessors: [:color], coder: JSON
end

ここでは、:user_attributes は使用する列ですが、accessors アクセスしたいキーのリストです(colorのみ) ここでは)、最後に、データのエンコード方法を指定します。 JSONを使用していますが、YAMLやカスタムエンコーディングなど、ここでは好きなものを使用できます。このメソッドは、(選択したコーダーを使用して)シリアル化を処理し、store_accessorを呼び出します。 ボンネットの下。

ActiveRecordのstore_accessor

store_accessorを使用して、モデルにget/setメソッドを作成します。 :

class Item < ApplicationRecord
  store_accessor :user_attributes, :color
  store_accessor :user_attributes, :name, prefix: true
  store_accessor :user_attributes, :location, prefix: 'primary'
end

ここでも、user_attributes は使用するデータベース列であり、その後にJSONデータで使用するキーが続きます。最後に、プレフィックス(またはサフィックス)を使用するオプションがあります。 store_accessorに注意してください ネストされたデータはサポートせず、最上位のキーと値のペアのみをサポートします。 prefix およびsuffix オプションは、ブール値、文字列、または記号のいずれかを取ります。ブール値のtrueの場合 が渡されると、列の名前がプレフィックス/サフィックスとして使用されます。

=>item = Item.create!(color: 'red', user_attributes_name: 'Jonathan', primary_location: 'New Zealand')
>#<Item:0x000055d63f4f0360
 id: 4,
 user_attributes: {"color"=>"red", "name"=>"Jonathan", "location"=>"New Zealand"}>
=>item.color
>"red"
=> item.user_attributes_name
>"Jonathan"
=> item.name
>NoMethodError: undefined method `name'...
=> item.primary_location
>"New Zealand"
実際の使用法

私はたまにしか、典型的な事前に知られているリレーショナルデータベーススキーマから逸脱する必要がありました。数回、データベース構造がこれらのオプションがない場合よりもクリーンでシンプルになりました。

私が遭遇した1つの例は、ユーザーが自分のアカウントを接続する複数のAPIをサポートすることです。 APIが同じ認証スキームを使用しない場合、これは注意が必要です。ユーザー名とパスワードを使用するものもあれば、APIキーを使用するものもあります。また、APIキー、シークレット、マーチャントIDを使用するものもあります。 1つのアプローチは、テーブルに列を追加し続けることです。列の多くはnullになります。 ほとんどのプロバイダーにとって。 jsonを使用する ただし、保存できるのは特定のAPIに必要な値のみです。

私が取り組んでいるサイドプロジェクトもJSONストレージを使用して、ユーザーがユーザー定義の属性を含むアイテムに任意の属性を設定できるようにします。このデータの流動的で予測不可能な性質を考えると、JSONストレージ(store_accessorを使用)のようなもの 既知の属性の場合)は自然に適合します。

概要

JSONデータ(およびその周りのActiveRecordのヘルパー)は、データとデータ構造が変更可能または不明な場合に非常に役立ちます。もちろん、この種のデータストレージは、ほとんどの場合と同様に、トレードオフです。特定のレコードのデータ構造には多くの柔軟性がありますが、データベースの制約によって得られるデータの整合性の一部を放棄することになります。また、一般的なActiveRecordクエリ、結合などを使用して、レコード間でクエリを実行する能力が低下します。

次のような経験則があります:

  1. JSONキーがすべての行で同じになることを知っているか
  2. 他のデータベーステーブルのID(主キー)を保存しているか、
  3. テーブルからレコードを検索するために使用される値をJSONに保存しています

次に、データベースを活用してデータの整合性を強化できる新しいテーブルを作成する方がよい場合があります。ただし、他のテーブルに直接関連しない行固有のデータを保存している場合は、JSONがデータベース構造の簡素化に役立つ可能性があります。


  1. JSONをExcelに変換する方法は?

    JSONまたはJavascriptObjectNotationファイルは、さまざまな種類のデータを格納するために頻繁に使用されます。ストレージに加えて、2つのサーバー間でデータを転送するためにも使用されます。これは、APIなどを介してWebサーバーと通信するときによく見られます。 JSONファイルはかなり基本的な構造を持っています。つまり、配列とオブジェクトがあります。典型的なJSONファイルには、配列に格納されているさまざまなオブジェクト内にデータを格納するキーと値のペアがあります。値のキーとともにインデックスを提供することにより、データにアクセスできます。 結局のところ、JSONファイ

  2. Google Play ストアの 2022 年ベスト ヒドゥン ジェムズ

    Google Play ストアには、ゲーム、ソーシャル アプリ、最適化、バッテリー セーバー アプリなど、各カテゴリに数百万のアプリがあります。他のアプリほど人気が​​ないアプリは他にもたくさんありますが、それらは仕事を成し遂げるのに本当に役立ち、頻繁に使用するのが大好きです.隔年と同様に、Google Play ストアは 2022 年に隠れた宝石カテゴリでチャートを突破したアプリをリストしました。 そこで今日は、2022 年の最高の隠れた宝石カテゴリで、受賞歴のある Android アプリのトップ 5 を共有します。 ソクラティック – 数学の答えと宿題のヘルプ Socratic は