Jonathan Wexler/吉川 邦夫 翔泳社 2019年09月25日頃
Lesson18
ユーザーモデルを作る
- 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);
- 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");
});
}
}
app.get("/users", usersController.index, usersController.indexView);
Lesson19
Routerモジュールを使う
- 経路が多くなる場合は、Routerオブジェクトを使って管理を分けるとよい。
- Routerオブジェクトは、appとは別に独自のミドルウェアとルーティングを提供する。
- appで経路を追加していたものをrouteに書き換え、最後にapp.use(“/”, router);を追加する。
// 以下を追加
const router = express.Router();
router.use(express.static("public"));
router.use(layouts);
router.use(
express.urlencoded({
extended: false
})
);
router.use(express.json());
router.get("/", homeController.index);
app.use("/", router);
pre(‘save’)フックを使う
- Mongooseのpre(‘save’)フックを使うと、データ保存前に処理を実行させることができる。
- フックはパラメータとしてnextミドルウェア関数を受け取るので、処理が完了したら次のミドルウェア関数を呼び出す。
"use strict";
const mongoose = require("mongoose");
const {Schema} = mongoose;
const Subscriber = require("./subscriber"); // 追加
const userSchema = new Schema(
{
name: {
first: {
type: String,
trim: true
},
last: {
type: String,
trim: true
}
},
email: {
type: String,
required: true,
lowercase: true,
unique: true,
trim: true
},
zipCode: {
type: Number,
min: [1000, "Zip code too short"],
max: 99999,
trim: true
},
password: {
type: String,
required: true,
trim: 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}`;
});
// 追加
userSchema.pre("save", function(next) {
let user = this;
if (user.subscribedAccount === undefined) {
Subscriber.findOne({
email: user.email
})
.then(subscriber => {
user.subscribedAccount = subscriber;
next();
})
.catch(error => {
console.log(`Error in connecting subscriber:${error.message}`);
next(error);
});
} else {
next();
}
});
module.exports = mongoose.model("User", userSchema);
Lesson20
HTTPのPUT, DELETEメソッドを使う
- method-overrideパッケージを使う。
npm install method-override
- リクエストパラメータで_method=PUTのように指定する。
// 以下を追加
const methodOverride = require('method-override');
router.use(
methodOverride("_method", {
methods: ["POST", "GET"]
})
);