ExtJS+mongoDB を使用してアプリを実装しています。node.js をサーバーとして使用し、express モジュールを使用して REST API を作成します。詳細には、ExtJS 4.1.3 + mongoose 1.2.17 + express 1.2.17 + mongodb 2.4 を Node.js v0.10.3 で実行しています。
コード ExtJS 部分 (MVC で編成):
モデル パーツには、PvdcPrice と PvdcPriceDetails の 2 つのモデルが含まれており、"hasMany" 関係があります。
PvdcPrice.js:
Ext.define('App.model.PvdcPrice', {
extend : 'Ext.data.Model',
fields : [{
name : '_id',
type : 'Number'
}, {
name : 'Type',
type : 'string'
}, {
name : 'MaxDiscount',
type : 'Number'
}],
hasMany : [{
name : 'prices',
model : 'App.model.PvdcPriceDetail',
associationKey : 'prices'
}],
proxy : {
type : 'rest',
url : '/pvdcprices',
reader : {
type : 'json',
root : 'data',
successProperty : 'success'
}
}
});
PvdcPriceDetail.js:
Ext.define('App.model.PvdcPriceDetail', {
extend : 'Ext.data.Model',
fields : [{
name : 'ID',
type : 'Number'
}, {
name : 'Location',
type : 'string'
}, {
name : 'Edition',
type : 'string'
}, {
name : 'MonthlyPrice',
type : 'Number'
}, {
name : 'OneTimePrice',
type : 'Number'
}
]
});
コントローラーの部分は長すぎるので、ストアを作成する部分だけをここに置きます。
var pvdcPrice = Ext.create('Ext.data.Store', {
model : "App.model.PvdcPrice",
data : [{
"_id" : 1,
"Type" : "pvdc",
"MaxDiscount" : "0"
}]
});
var priceInfo = pvdcPrice.first();
var pvdcPriceDetails = priceInfo.prices();
pvdcPriceDetails.add({
'ID' : 1,
'Location' : 'SNJ',
'Edition' : 'Basic',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPriceDetails.add({
'ID' : 2,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPriceDetails.add({
'ID' : 3,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPrice.sync();
var record = pvdcPrice.first();
console.log(record.get('Type'));
record.prices().each(function(r) {
console.log(r.get('Location'));
console.log(r.get('Edition'));
});
Node.js 部分、サーバー スクリプトは app.js です。
var express = require('express'),
app = module.exports = express();
// MongoDB
var mongoose = require('mongoose'),
db = mongoose.connect('mongodb://127.0.0.1/IaaSDB'),
//create sub schema of pvdc price schema
PriceDetailSchema = new mongoose.Schema({
ID: Number,
Location: String,
Edition: String,
MonthlyPrice: Number,
OneTimePrice: Number
}),
//create the Pvdc price info Model using the 'pvdcPrice' collection as a data-source
PvdcPrice = mongoose.model('pvdcPrice', new mongoose.Schema({
Type: String,
MaxDiscount: String,
prices: [PriceDetailSchema]
}));
// Configuration
app.configure(function () {
//app.set('views', __dirname + '/views');
//app.set('view engine', 'jade');
app.use(express.bodyParser());//parse JSON into objects
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/IaaSPriceTool'));
});
app.configure('development', function () {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
app.configure('production', function () {
app.use(express.errorHandler());
});
// Routes
app.get('/', function (req, res) {
res.redirect('/index.html');
});
/*
Pvdc Price Information CRUD web service
*/
app.get('/pvdcprices', function (req, res) {
PvdcPrice.find({}, function (err, pvdcprices) {
res.contentType('json');
res.json({
success: true,
data: pvdcprices
});
});
});
app.get('/pvdcprices/:id', function(req, res){
PvdcPrice.find({_id: req.params.id}, function (err, pvdcPrices) {
res.contentType('json');
res.json({
success: true,
data: pvdcPrices
});
});
});
app.post('/pvdcprices', function (req, res) {
console.log("[200] " + req.method + " to " + req.url);
console.log(req.body);
var newPriceInfo = new PvdcPrice();
var newPriceInfoData = req.body;
//remove the id which the client sends since it is a new pvdc price
delete newPriceInfo['_id'];
newPriceInfo.set(newPriceInfoData);
newPriceInfo.save(function (err, pvdcPrice) {
res.contentType('json');
res.json({
success: !err,
data: pvdcPrice
});
});
});
app.listen(3000);
console.log("Express server listening on port %d in %s mode", 3000, app.settings.env);
その後、firebug を使用してフロントエンドをデバッグします。ブラウザー コンソールから、pvdc 価格の競合が表示されていることがわかります。
POST http://localhost:3000/pvdcprices?_dc=1369740182183 200 OK 27ms
pvdc
Basic
ATL
Standard
ATL
Standard
これは、ExtJS のアソシエーション モデルが機能し、pvdcPrice の内容を確認できることを意味します。ExtJS の json 構造は次のようになります。
{
"data" :{
"_id" : 1,
"Type" : "pvdc",
"MaxDiscount" : "0",
"prices" : [{
'ID' : 1,
'Location' : 'SNJ',
'Edition' : 'Basic',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
},{
'ID' : 2,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
},{
'ID' : 3,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
}]
}
}
しかし、node.js からの応答は success: false です。
次に、node.js 部分のコンソールで、node.js の投稿のリクエスト本文を出力します。それは次のとおりです。
[200] POST to /pvdcprices?_dc=1369734975208
{ _id: 1, Type: 'pvdc', MaxDiscount: 0, id: null }
「価格」のサブコンテンツが欠落しており、pvdcPrice の主要部分のみがサーバーに投稿されます。
投稿プロセス中に欠落している原因を誰かが指摘できますか? 本当に助けてくれてありがとう:)