モデルの属性は、モデルに関する基本的な情報です。たとえば、Person
というモデルには、firstName
、lastName
、phoneNumber
、age
、birthDate
、emailAddress
などの属性があるかもしれません。
モデルのattributes
設定では、属性のセットを定義できます。各属性は辞書(プレーンなJavaScriptオブジェクト)として定義されます。
// api/models/User.js
{
attributes: {
emailAddress: { type: 'string', required: true, },
karma: { type: 'number', },
isSubscribedToNewsletter: { type: 'boolean', defaultsTo: true, },
},
}
各属性内には、SailsとWaterlineに追加の指示を与えるために使用される1つ以上のキー(またはオプション)があります。これらの属性キーは、モデルに対して、型安全性の確保、高度な検証ルールの適用、および(自動マイグレーションが有効になっている場合は)データベース内のテーブルまたはコレクションの設定方法を指示します。
attributes
をデフォルトのモデル設定(例:config/models.js
)として定義することで、すべてのモデルに表示されるデフォルト属性を定義することもできます。たとえば、新しいSailsアプリには、最初からid
、createdAt
、updatedAt
の3つのデフォルト属性が付属しています。
これらの属性は、上書きまたは無効化されない限り、すべてのモデルで使用できます。デフォルト属性を上書きするには、モデル定義で同じ名前の属性を定義します。デフォルト属性を無効化するには、false
として定義します。たとえば、特定のモデルのデフォルトのupdatedAt
属性を無効にするには、次のようにします。
// api/models/ProductCategory.js
module.exports = {
attributes: {
updatedAt: false,
label: { type: 'string', required: true },
}
}
アソシエーションを除き、すべての属性はtype
を宣言する必要があります。
これは、この属性に格納されるデータの型であり、クエリと結果の論理的な型安全性のチェックに使用されます。以下は、SailsとWaterlineでサポートされているデータ型のリストです。
属性がrequired: true
の場合、.create()
を呼び出す際に、常に値を指定する必要があります。これにより、属性の値がnull
または空文字列("")として作成または更新されるのを防ぎます。
5つのデータ型に加えて、属性に対して定義できる基本的な保証がいくつかあります。その1つがデフォルト値を割り当てる機能です。
属性のデフォルト値(defaultsTo
)は、.create()
でのみ適用され、キーが完全に省略されている場合にのみ適用されます。
attributes: {
phoneNumber: {
type: 'string',
defaultsTo: '111-222-3333'
}
}
string
、number
、およびboolean
データ型は、レコードの作成または更新時にnull
を値として受け入れません。null
値を設定できるようにするには、属性のallowNull
フラグを切り替えることができます。allowNull
フラグは、上記のデータ型でのみ有効であることに注意してください。型がjson
またはref
の属性、アソシエーション、または主キー属性では有効ではありません。
attributes: {
phoneNumber: {
type: 'string',
allowNull: true
}
}
基本的な型安全性チェックに加えて、Sailsはいくつかの異なる高度な検証ルールを提供しています。たとえば、isIn
ルールは、この属性に格納される新しい値が、いくつかの異なるハードコードされた定数のいずれかと正確に一致する必要があることを検証します。
unsubscribeReason: {
type: 'string',
isIn: ['boring', 'too many emails', 'recipes too difficult', 'other'],
required: true
}
高度な検証ルールの完全なリストについては、検証を参照してください。
属性定義内で、columnName
を指定して、Sails/Waterlineに、その属性のデータを構成されたデータストア(つまり、データベース)の特定の列に強制的に格納させることができます。これは必ずしもSQL固有のものではないことに注意してください。MongoDBフィールドなどにも同様に機能します。
columnName
プロパティは、主に既存のデータベースやレガシーデータベースを操作するために設計されていますが、データベースが他のアプリケーションで共有されている場合や、スキーマを変更するアクセス許可がない場合にも役立ちます。
モデルのnumberOfWheels
属性をnumber_of_round_rotating_things
列に格納/取得するには、次のようにします。
// An attribute in one of your models:
// ...
numberOfWheels: {
type: 'number',
columnName: 'number_of_round_rotating_things'
}
// ...
では、より包括的な例を見てみましょう。
Sailsアプリに、次のようなUser
モデルがあるとします。
// api/models/User.js
module.exports = {
datastore: 'shinyNewMySQLDatabase',
attributes: {
name: {
type: 'string'
},
password: {
type: 'string'
},
email: {
type: 'string',
unique: true
}
}
};
すべてが正常に機能しますが、アプリの対象ユーザーを格納する既存のMySQLデータベースをサーバー上のどこかで使用する代わりに...
// config/datastores.js
module.exports = {
// ...
// Existing users are in here!
rustyOldMySQLDatabase: {
adapter: 'sails-mysql',
url: 'mysql://ofh:[email protected]/jonas'
},
// ...
};
...古いMySQLデータベースに、次のようなour_users
というテーブルがあるとします。
the_primary_key | email_address | full_name | seriously_hashed_password |
---|---|---|---|
7 | [email protected] | Mike McNeil | ranchdressing |
14 | [email protected] | Nick Crumrine | thousandisland |
これをSailsから使用するには、User
モデルを次のように変更します。
// api/models/User.js
module.exports = {
datastore: 'rustyOldMySQLDatabase',
tableName: 'our_users',
attributes: {
id: {
type: 'number',
unique: true,
columnName: 'the_primary_key'
},
name: {
type: 'string',
columnName: 'full_name'
},
password: {
type: 'string',
columnName: 'seriously_hashed_password'
},
email: {
type: 'string',
unique: true,
columnName: 'email_address'
}
}
};
この例では、
tableName
プロパティも使用したことに気付いたかもしれません。これにより、データの格納に使用されるテーブルの名前を制御できます。
encrypt
を設定すると、この属性を自動的に暗号化するかどうかを決定できます。true
に設定した場合、レコードを取得すると、.decrypt()
を使用しない限り、この属性の暗号化された値が引き続き含まれます。
attributes: {
ssn: {
type: 'string',
encrypt: true
}
}
属性に
encrypt: true
を使用している場合、暗号化されていない値でレコードを検索することはできません。
これらの設定は、アプリが起動されたときに、Sailsが属性の物理レベル(例:PostgreSQL、MySQL、またはMongoDB)のデータベースフィールドをどのように作成するかを示すために使用されます。
モデルの
migrate
プロパティがsafe
に設定されている場合、これらの設定は無視され、データベースの列は変更されません。
Sailsがデータベーステーブルを作成するときに、属性に使用する物理レベルの列データ型を示します。これにより、基盤となるデータベースがどのように作成するかに直接関連付けられた型を指定できます。たとえば、type
プロパティをnumber
に設定し、それをデータベースに格納するために列型float
を使用する属性があるとします。属性の定義は次のようになります。
attributes: {
placeInLine: {
type: 'number',
columnType: 'float'
}
}
- 列の型は完全にデータベースに依存します。選択した
columnType
が、データベースで有効なデータ型に対応していることを確認してください。columnType
を指定しない場合、アダプターは属性のtype
に基づいて選択します。columnType
の値は、データベース列を作成するステートメントでそのまま使用されるため、varchar(255) CHARACTER SET utf8mb4
などの追加オプションを指定できます。- Sailsモデルにバイナリデータを格納する場合は、属性の
type
をref
に設定してから、選択したデータベースの適切なcolumnType
を使用する必要があります(例:MySQLの場合はmediumblob
、PostgreSQLの場合はbytea
)。Sailsには、バイナリデータをデータストアアダプターにストリーミングするメカニズムが現在ないため、格納しようとするものはすべてデータベースに転送される前にメモリに収まる必要があることに注意してください。データベースにBLOBを格納する代わりに、.upload()
メソッドを使用して、ディスクまたはS3のようなリモートファイルシステムにストリーミングすることを検討できます。- MySQLの
CHARACTER SET utf8mb4
などのカスタム列オプションは、列のストレージサイズに影響を与える可能性があることに注意してください。これは、エラーを回避するために列サイズを小さく指定する必要がある場合がある、unique
プロパティと組み合わせて使用する場合に特に重要です。詳細については、以下のunique
プロパティのドキュメントを参照してください。
属性を自動インクリメントキーとして設定します。新しいレコードがモデルに追加されるときに、この属性の値が指定されていない場合、最新のレコードの値に1を加算して生成されます。注:autoIncrement
を指定する属性は、常にtype: 'number'
である必要があります。また、サポートのレベルはデータストアによって異なることに注意してください。たとえば、MySQLでは、テーブルあたり複数の自動インクリメント列は許可されません。
attributes: {
placeInLine: {
type: 'number',
autoIncrement: true
}
}
対象の属性に対して同じ値を持つ2つのレコードが許可されないようにします。これはアダプターレベルの制約であるため、ほとんどの場合、これにより、基盤となるデータストアに属性の一意のインデックスが作成されます。
attributes: {
username: {
type: 'string',
unique: true
}
}
データベースによっては、unique: true
を使用する場合、required: true
を設定する必要がある場合もあります。
MySQLデータベースで
utf8mb4
文字セットを使用して属性にunique: true
を使用する場合、'index too long'エラーを回避するために、columnType
プロパティを介して列サイズを手動で設定する必要があります。例:columnType: varchar(100) CHARACTER SET utf8mb4
。