2

すべてのエンドポイントがルート上にあるRestifyの例を見てきました:/ users、/dataなど。次のようにネストを実装できることはわかっています。

server.get('/users/:user/data/:id', returnData);

req.params変数には、すべてのリクエストパラメータが含まれます。例:

{ user: '45', id: '80' }

アプリケーションにエンドポイントがほとんどない場合、これは正常に機能するようですが、REST APIを介して公開したい深く分岐したデータ構造がある場合はどうなりますか?何かのようなもの:

{
  stuff: {
    points: {
      colors: {
        shinyThings: {},
        dullThings: {}
      }
    },
    ships: {
      enterprises: {},
      starDestroyers: {}
    }
  },
  things: {},
}

これらすべてのエンドポイントへのパスを手動で作成する必要があるのは、正しくないようです。私はたくさんのパス定義とこのようなもので終わります:

server.put('/stuff/:stuff/points/:points/colors/:colors/shinyThings/:shinyThings', returnShinyThing);

Restifyでこれを行う簡単な方法はありますか?

4

1 に答える 1

2

私はそれを行う方法を考え出しましたが、より良い選択肢があると確信しています:

1)エンドポイントで特定のアクションを処理するモジュールを作成します。これらのモジュールは、中央ルーターモジュールに必要になります。例stuff.js

exports.list = function(req, res, next) {
  // Code to handle a GET request to /stuff
};

exports.create = function(req, res, next) {
  // Code to handle a POST request to /stuff
};

exports.show = function(req, res, next) {
  // Code to handle a GET request to /stuff/:id
};

exports.update = function(req, res, next) {
  // Code to handle a PUT request to /stuff/:id
};

exports.destroy = function(req, res, next) {
  // Code to handle a DELETE request to /stuff/:id
};

2)ルーターモジュールで、アクションのマッピングを定義します->http動詞:

var actions = {
  list: 'get',
  create: 'post',
  show: 'get',
  update: 'put',
  destroy: 'del'
}

3)次のようなデータ構造を表すオブジェクトを作成します。

var schema = {
  stuff: {
    _actions: require('./stuff'),
    points: {
      _actions: require('./points'),
      colors: {
        _actions: require('./colors'),
        shinyThings: {_actions: require('./shinyThings')},
        dullThings: {_actions: require('./dullThings')}
      }
    },
    ships: {
      _actions: require('./ships'),
      enterprises: {_actions: require('./enterprises')},
      starDestroyers: {_actions: require('./starDestroyers')}
    }
  },
  things: {_actions: require('./things')},
}

4)ルーターの初期化中に、アプリケーションはルートを接続するRestifyサーバーオブジェクトをルーターに渡します。初期化中、再帰関数はスキーマオブジェクトをウォークし、_actionsキーが見つかると、指定されたパスにあるルートハンドラーを指定されたサーバーオブジェクトにアタッチする2番目の関数を呼び出します。

(function addPathHandlers(object, path) {
  for (var key in object) {
    if (key === '_actions') addActions(object, path);
    else if (typeof object[key] === 'object') {
      var single = en.singularize(path.split('/').pop());

      if (path.charAt(path.length - 1) !== '/') {
        path += ['/:', single, '_id/'].join('');
      }

      addPathHandlers(object[key], path + key);
    }
  }
})(schema, '/');

function addActions(object, path) {
  // Actions that require a specific resource id
  var individualActions = ['show', 'update', 'destroy']; 

  for (var action in object._actions) {
    var verb = actions[action];

    if (verb) {
      var reqPath = path;
      if (individualActions.indexOf(action) !== -1) reqPath += '/:id';

      server[verb](reqPath, object._actions[action]);
    }
  }
}

注:これは、lingoモジュール(つまり、en.singularize()関数)を利用します。また、関数の重要でない部分を削除したため、少し単純化されていますが、そのままで完全に機能するはずです。

これのインスピレーションは、express-resourceがそれを行う方法を調べた後にもたらされましたが、それはそれほど洗練されておらず、使いやすいものではありません。

于 2012-12-06T16:17:49.003 に答える