Lesson17
バリデーションを追加する
models/subscribers.jsのスキーマ定義を修正
- 型はString, Date, Array, Mixed, ObjectIdなど。
lowercase: true
とすると、値が小文字に変換される。
const subscriberSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
lowercase: true,
unique: true
},
zipCode: {
type: Number,
min: [10000, "Zip code too short"],
max: 99999
},
});
静的メソッドとインスタンスメソッド
- スキーマには静的メソッド・インスタンスメソッドを定義することができる。
- 静的メソッド:
subscriberSchema.xxx = function() {};
- インスタンスメソッド:
subscriberSchema.methods..xxx = function() {};
※ アロー関数にするとメソッド内でthisが使えなくなるのでfunctionで定義
// インスタンスメソッドの定義
subscriberSchema.methods.getInfo = function() {
return `name=${this.name}, email=${this.email}`;
};
// インスタンスメソッドの呼び出し
Subscriber.findOne({}).exec().then(subscriber => {
console.log(subscriber.getInfo());
});
アソシエーションを作る
SubscriberモデルにCourseモデルを紐づける場合、models/subscriber.jsのスキーマ定義に追加する。
※ 関連付けは相互に参照する必要はない。片方のモデルがもう片方のモデルを参照するだけで十分。
- 1対1の場合
course: { type: mongoose.Schema.Types.ObjectId, ref: "Course" }
- 1対多の場合
courses: [{ type: mongoose.Schema.Types.ObjectId, ref: "Course" }]
- 利用方法
subscriber1.course = course1;
配列の場合はsubscriber1.course.push(course1);
"use strict";
const mongoose = require("mongoose");
const courseSchema = new mongoose.Schema({
title: {
type: String,
required: true,
unique: true
},
description: {
type: String,
required: true
},
});
module.exports = mongoose.model("Course", courseSchema);
関連モデルからデータを記入する
Mongooseのpopulateメソッドを使うと、関連付けられたモデルのデータを取得(クエリ結果に記入)することができる。
Subscriber.findOne().populate('course').then(subscriber => {
console.log(subscriber.course);
});
// インスタンスを指定する場合
Subscriber.populate(subscriber, 'course').then(subscriber2 => {
console.log(subscriber2.course);
});
Lesson18
ユーザーモデルを作る
1. models/user.jsの作成
- nameのfirstとlastのように、オブジェクトを入れ子にすることが可能。
- スキーマのvirtualメソッドを使って、仮想属性(データベースには保存されない属性)を定義することができる。
例) firstとlastからフルネームを取得する。 timestamps: true
でcreatedAtとupdatedAtが追加される。
"use strict";
const mongoose = require("mongoose");
const {Schema} = mongoose;
const userSchema = new Schema(
{
name: {
first: {
type: String,
trim: true
},
last: {
type: String,
trim: true
}
},
email: {
type: String,
required: true,
lowercase: true,
unique: true
},
zipCode: {
type: Number,
min: [1000, "Zip code too short"],
max: 99999
},
password: {
type: String,
required: true
},
courses: [{type: Schema.Types.ObjectId, ref: "Course"}],
subscribedAccount: {
type: Schema.Types.ObjectId,
ref: "Subscriber"
}
},
{
timestamps: true
}
);
userSchema.virtual("fullName").get(function() {
return `${this.name.first} ${this.name.last}`;
});
module.exports = mongoose.model("User", userSchema);
2. controllers/usersController.jsの作成
- module.exportsにアクションをオブジェクトとして代入すると、管理しやすくなる。
- indexアクションとindexViewアクションに分け、データはres.localsを使って引き渡す。
"use strict";
const User = require("../models/user");
const Subscriber = require("../models/subscriber");
module.exports = {
index: (req, res, next) => {
User.find({})
.then(users => {
console.log(users);
res.locals.users = users;
next();
});
},
indexView: (req, res) => {
res.render("users");
},
addUser: (req, res) => {
let createdUser;
const newUser = new User({
name: {
first: req.body.first,
last: req.body.last
},
email: req.body.email,
password: req.body.password,
});
newUser.save().then(user => {
createdUser = user;
return Subscriber.findOne({email: req.body.email});
}).then(subscriber => {
createdUser.subscribedAccount = subscriber;
createdUser.save();
}).then(() => {
res.render("thanks");
});
}
}
3. index.jsに追加
app.get("/users", usersController.index, usersController.indexView);