0

Rails アプリ データベースの資格情報を使用して、Titanium アプリにログインできるようにしたいと考えています。

Titanium で、次のモデルを作成しました。

exports.definition = {
    config: {
        'adapter': {
            'type': 'myAdapter',
            'base_url': 'http://server:3000/api/users/'
        }
    },

    extendModel: function(Model) {      
        _.extend(Model.prototype, {
          // custom functions
          login: function() {
            this.sync("login", this);
          }
        });
        return Model;
    },

    extendCollection: function(Collection) {        
        _.extend(Collection.prototype, {});
        return Collection;
    }
}

Appcelerator の公式ドキュメントにある Twitter の例から、私が作成した同期アダプター:

// Global URL variable
var BASE_URL = 'http://server:3000/api/';

// Override the Backbone.sync method with the following
module.exports.sync = function(method, model, options) {

  var payload = model.toJSON();
  var error;

  switch(method) {
    // custom cases
    case 'login':
      http_request('POST', BASE_URL + 'login', payload, callback);
      break;

    // This case is called by the Model.fetch and Collection.fetch methods to retrieve data.
    case 'read':
      // Use the idAttribute property in case the model ID is set to something else besides 'id'
      if (payload[model.idAttribute]) {
        // If we have an ID, fetch only one tweet
        http_request('GET', BASE_URL + '', {
          id : payload[model.idAttribute]
        }, callback);
      } else {
        // if not, fetch as many as twitter will allow us
        http_request('GET', BASE_URL + '', null, callback);
      }
      break;

    // This case is called by the Model.save and Collection.create methods
    // to a initialize model if the IDs are not set.
    // For example, Model.save({text: 'Hola, Mundo'})
    // or Collection.create({text: 'Hola, Mundo'}) executes this code.
    case 'create':
      if (payload.text) {
        http_request('POST', BASE_URL + 'update.json', {
          status : payload.text
        }, callback);
      } else {
        error = 'ERROR: Cannot create tweet without a status!';
      }
      break;

    // This case is called by the Model.destroy method to delete the model from storage.
    case 'delete':
      if (payload[model.idAttribute]) {
        // Twitter uses a POST method to remove a tweet rather than the DELETE method.
        http_request('POST', BASE_URL + 'destroy/' + payload[model.idAttribute] + '.json', null, callback);
      } else {
        error = 'ERROR: Model does not have an ID!';
      }
      break;

    // This case is called by the Model.save and Collection.create methods
    // to update a model if they have IDs set.
    case 'update':
      // Twitter does not have a call to change a tweet.
      error = 'ERROR: Update method is not implemented!';
      break;
    default :
      error = 'ERROR: Sync method not recognized!';
  };

  if (error) {
    options.error(model, error, options);
    Ti.API.error(error);
    model.trigger('error');
  }

  // Simple default callback function for HTTP request operations.
  function callback(success, response, error) {
    res = JSON.parse(response);
    console.log("response |" + response);
    console.log("res |" + res);
    console.log("res str |" + JSON.stringify(res))
    console.log("options |" + options);
    if (success) {
      // Calls the default Backbone success callback
      // and invokes a custom callback if options.success was defined.
      options.success(res, JSON.stringify(res), options);
    } 
    else {
      // res.errors is an object returned by the Twitter server
      var err = res.errors[0].message || error;
      Ti.API.error('ERROR: ' + err);
      // Calls the default Backbone error callback
      // and invokes a custom callback if options.error was defined.
      options.error(model, err, options);
      model.trigger('error');
    }
  };

};

// Helper function for creating an HTTP request
function http_request(method, url, payload, callback) {

  // Generates the OAuth header - code not included
  var header;
  //= generate_header(method, url, payload);

  var client = Ti.Network.createHTTPClient({
    onload : function(e) {
      if (callback)
        callback(true, this.responseText, null);
    },
    onerror : function(e) {
      if (callback)
        callback(false, this.responseText, e.error);
    },
    timeout : 5000
  });

  // Payload data needs to be included for the OAuth header generation,
  // but for GET methods, the payload data is sent as a query string
  // and needs to be appended to the base URL
  if (method == 'GET' && payload) {
    var values = [];
    for (var key in payload) {
      values.push(key + '=' + payload[key]);
    }
    url = url + '?' + values.join('&');
    payload = null;
  }

  client.open(method, url);
  //client.setRequestHeader('Authorization', header);
  client.send(payload);
};

// Perform some actions before creating the Model class
module.exports.beforeModelCreate = function(config, name) {
  config = config || {};
  // If there is a base_url defined in the model file, use it
  if (config.adapter.base_url) {
    BASE_URL = config.adapter.base_url;
  }
  return config;
};

// Perform some actions after creating the Model class
module.exports.afterModelCreate = function(Model, name) {
  // Nothing to do
}; 

Rails アプリは JSON で応答し、動作しますが、問題はコールバック関数にあります。

[INFO] :   response |{"email":"huhu@gmail.com","password":null}
[ERROR] :  Script Error {
[INFO] :   res |[object Object]
[INFO] :   res str |{"email":"huhu@gmail.com","password":null}
[INFO] :   options |[object Object]
[ERROR] :      backtrace = "#0 () at file://localhost/.../xxx.app/alloy/sync/myAdapter.js:4";
[ERROR] :      line = 30;
[ERROR] :      message = "'undefined' is not a function (evaluating 'options.success(res, JSON.stringify(res), options)')";
[ERROR] :      name = TypeError;
[ERROR] :      sourceId = 216868480;
[ERROR] :      sourceURL = "file://localhost/.../xxx.app/alloy/sync/myAdapter.js";
[ERROR] :  }

それで、誰かがオプションが未定義である理由を知っていますか...? read メソッドを使用してユーザーを取得するために fetch メソッドを呼び出すと、機能することに注意してください。ところで、誰かを認証する良い方法はありますか?

4

1 に答える 1

0

モデルでパラメーターを渡していない場合は、options以下のように変更してみてください

this.sync("login", this, {
   success: function() {},
   error: function(){}
});
于 2013-06-11T17:42:22.987 に答える