कलाकारों, ऑफ़लाइन कामों के लिए Google Base और Google गियर्स का इस्तेमाल

"Google API के साथ Ajax ऐप्लिकेशन बनाना" सीरीज़ का पहला लेख.

डायन अल्मायर और पामेला फ़ॉक्स, Google
जून 2007

संपादक का नोट: Google गियर API अब उपलब्ध नहीं है.

सुविधा के बारे में जानकारी

Google बेस को Google गियर के साथ जोड़कर, हम एक ऐसा ऐप्लिकेशन बनाने का तरीका दिखाते हैं जिसका ऑफ़लाइन इस्तेमाल किया जा सके. इस लेख को पढ़ने के बाद, आपको Google Base API के बारे में और जानकारी मिलेगी. साथ ही, यह भी समझ आएगा कि उपयोगकर्ता की पसंद और डेटा को सेव करने और उसे ऐक्सेस करने के लिए, Google गियर्स का इस्तेमाल कैसे किया जाए.

ऐप्लिकेशन को समझना

इस ऐप्लिकेशन को समझने के लिए, आपको सबसे पहले Google Base के बारे में जानकारी होनी चाहिए. यह बुनियादी तौर पर एक बड़ा डेटाबेस है, जिसमें प्रॉडक्ट, समीक्षाएं, रेसिपी, इवेंट वगैरह जैसी कई कैटगरी के आइटम शामिल हैं.

हर आइटम के बारे में शीर्षक, जानकारी, डेटा के मूल स्रोत के लिंक (अगर मौजूद हो) दिया जाता है. साथ ही, हर एट्रिब्यूट के हिसाब से अलग-अलग एट्रिब्यूट की जानकारी भी दी जाती है. Google Base इस तथ्य का लाभ उठाता है कि एक ही श्रेणी के आइटम विशेषता के समान सेट शेयर करते हैं-उदाहरण के लिए, सभी रेसिपी में सामग्री होती है. Google Base आइटम कभी-कभी Google वेब खोज या Google प्रॉडक्ट खोज के खोज परिणामों में भी दिखाई देते हैं.

हमारे डेमो ऐप्लिकेशन , गियर्स के साथ बेस की मदद से आप ऐसी आम खोजें संग्रहित कर सकते हैं और दिखा सकते हैं जो आप Google Base पर कर सकते हैं जैसे- "chocolate" (yum) के साथ रेसिपी ढूँढना या "वॉक्स ऑन द बीच" के साथ निजी विज्ञापन (रोमैंटिक!). यह "Google के बेस रीडर" की तरह है. इसका इस्तेमाल करके, जब आप किसी ऐप्लिकेशन को फिर से देखें, तो खोज के लिए सदस्यता लें और अपडेट किए गए नतीजे देखें. इसके अलावा, आपको ऐप्लिकेशन के हर 15 मिनट में अपडेट किए गए फ़ीड देखने का विकल्प भी मिलेगा.

ऐसे ऐप्लिकेशन जो ऐप्लिकेशन को बढ़ाना चाहते हैं, वे और सुविधाएं जोड़ सकते हैं. जैसे, खोज के नतीजों में नए नतीजे दिखने पर, उपयोगकर्ता को विज़ुअल तौर पर सूचना देना. इससे, उपयोगकर्ता को बुकमार्क (स्टार) के पसंदीदा आइटम (ऑफ़लाइन और ऑनलाइन) बुकमार्क करने की सुविधा मिलती है. साथ ही, उपयोगकर्ता को Google Base जैसी कैटगरी के हिसाब से एट्रिब्यूट खोजने की अनुमति भी मिलती है.

Google Base डेटा API फ़ीड का उपयोग

Google Base की क्वेरी के लिए, Google Base डेटा API (एपीआई) का इस्तेमाल किया जा सकता है, जो Google Data API फ़्रेमवर्क के मुताबिक है. Google डेटा API प्रोटोकॉल, वेब पर पढ़ने और लिखने के लिए एक सरल प्रोटोकॉल उपलब्ध कराता है, और इसका उपयोग कई Google उत्पादों द्वारा किया जाता है: Picasa, स्प्रेडशीट, ब्लॉगर, कैलेंडर, नोटबुक, और अन्य.

Google डेटा एपीआई का फ़ॉर्मैट, एक्सएमएल और ऐटम पब्लिशिंग प्रोटोकॉल पर आधारित होता है. इसलिए, पढ़ने/लिखने के ज़्यादातर इंटरैक्शन एक्सएमएल में होते हैं.

Google Data API पर आधारित Google Base फ़ीड का उदाहरण है:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera

snippets फ़ीड टाइप से हमें सामान का सार्वजनिक तौर पर उपलब्ध फ़ीड मिलता है. -/products हमें फ़ीड को प्रॉडक्ट कैटगरी तक सीमित करने की सुविधा देता है. इसके अलावा, bq= पैरामीटर की मदद से फ़ीड सिर्फ़ उन नतीजों तक सीमित रहता है जिनमें "डिजिटल कैमरा" कीवर्ड शामिल होता है. अगर आप ब्राउज़र में यह फ़ीड देखते हैं, तो आपको मेल खाने वाले नतीजों के साथ <entry> नोड वाला एक्सएमएल दिखेगा. हर एंट्री में सामान्य लेखक, शीर्षक, कॉन्टेंट, और लिंक एलिमेंट शामिल होते हैं. हालांकि, इनमें खास कैटगरी के अन्य एट्रिब्यूट भी शामिल होते हैं. जैसे, प्रॉडक्ट कैटगरी में सामान के लिए "कीमत".

ब्राउज़र में XMLHttpRequest के क्रॉस-डोमेन प्रतिबंध के कारण, हमें अपने JavaScript कोड में www.google.com से सीधे किसी XML फ़ीड में पढ़ने की अनुमति नहीं है. हम एक्सएमएल में पढ़ने के लिए सर्वर-साइड प्रॉक्सी सेट अप कर सकते हैं और इसे अपने ऐप्लिकेशन के डोमेन पर ही ऐसी जगह पर ला सकते हैं जहां हम सर्वर-साइड प्रोग्रामिंग से पूरी तरह बचना चाहते हैं. अच्छी बात यह है कि यह सुविधा उपलब्ध नहीं है.

अन्य Google Data API की तरह, Google Base डेटा API में, स्टैंडर्ड एक्सएमएल के साथ JSON आउटपुट का विकल्प भी होता है. JSON फ़ॉर्मैट में पहले देखे गए फ़ीड का आउटपुट इस यूआरएल पर होगा:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera&alt=json

JSON, एक आसान इंटरचेंज फ़ॉर्मैट है. इसकी मदद से, हैरारकी नेस्टिंग और कई तरह के डेटा को ऐक्सेस किया जा सकता है. हालांकि, सबसे ज़रूरी बात यह है कि JSON के आउटपुट नेटिव JavaScript कोड होते हैं. इसलिए, क्रॉस-डोमेन पाबंदी को बायपास करते हुए, इसे आपके वेब पेज में सिर्फ़ एक स्क्रिप्ट टैग का रेफ़रंस देकर लोड किया जा सकता है.

Google डेटा एपीआई की मदद से, JSON लोड होने के बाद, कॉलबैक फ़ंक्शन के साथ "json-in-script" आउटपुट दिया जाता है. इससे, JSON आउटपुट के साथ काम करना आसान हो जाता है, क्योंकि हम पेज पर स्क्रिप्ट टैग को डाइनैमिक तौर पर जोड़ सकते हैं और हर एक के लिए अलग-अलग कॉलबैक फ़ंक्शन तय कर सकते हैं.

इसलिए, डाइनैमिक तरीके से पेज में बेस एपीआई JSON फ़ीड लोड करने के लिए, हम नीचे दिए गए उस फ़ंक्शन का इस्तेमाल कर सकते हैं जो फ़ीड के यूआरएल के साथ स्क्रिप्ट टैग बनाता है. इसे altcallback वैल्यू के साथ जोड़ा जाता है.

function getJSON() {
  var script = document.createElement('script');

  var url = "http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera";
  script.setAttribute('src', url + "&alt=json-in-script&callback=listResults");
  script.setAttribute('type', 'text/JavaScript');
  document.documentElement.firstChild.appendChild(script);
}

इसलिए, अब हमारा कॉलबैक फ़ंक्शन listResults, पैरामीटर के तौर पर पास किए गए JSON के ज़रिए ही दोहरा सकता है. साथ ही, बुलेट वाली सूची में मिली हर एंट्री के बारे में जानकारी दिखा सकता है.

  function listTasks(root) {
    var feed = root.feed;
    var html = [''];
    html.push('<ul>');
    for (var i = 0; i < feed.entry.length; ++i) {
      var entry = feed.entry[i];
      var title = entry.title.$t;
      var content = entry.content.$t;
      html.push('<li>', title, ' (', content, ')</li>');
    }
    html.push('</ul>');

    document.getElementById("agenda").innerHTML = html.join("");
  }

Google गियर्स जोड़ना

अब हमारे पास एक ऐसा ऐप्लिकेशन है जो Google Data API के ज़रिए Google Base से बात कर सकता है, इसलिए हम इस ऐप्लिकेशन को ऑफ़लाइन चलने के लिए सक्षम करना चाहते हैं. Google गियर्स यहाँ आता है.

जब कोई ऐसा ऐप्लिकेशन लिखने की बात आती है जो ऑफ़लाइन हो सकता है, तो वास्तुकला के कई विकल्प होते हैं. यह ज़रूरी है कि आप इस बारे में खुद से पूछें कि ऐप्लिकेशन को ऑनलाइन और ऑफ़लाइन, दोनों तरीकों से कैसे काम करना चाहिए (उदाहरण के लिए, क्या यह ठीक वैसा ही काम करता है? क्या खोज जैसी कुछ सुविधाएं अक्षम हैं? आपके हिसाब से, सिंक करने की प्रोसेस कैसे मैनेज की जाएगी?)

हमारे मामले में, हम यह पक्का करना चाहते थे कि प्लग-इन के बिना ब्राउज़र का इस्तेमाल करने वाले उपयोगकर्ता अब भी ऐप्लिकेशन का इस्तेमाल कर सकें. साथ ही, हम ऐसे उपयोगकर्ताओं को ऑफ़लाइन इस्तेमाल के फ़ायदे देते हैं जो प्लग-इन का इस्तेमाल करते हैं और वे बेहतर रिस्पॉन्सिव यूज़र इंटरफ़ेस (यूआई) का इस्तेमाल करते हैं.

हमारा आर्किटेक्चर कुछ ऐसा दिखता है:

  • हमारे पास एक JavaScript ऑब्जेक्ट है, जो आपकी खोज क्वेरी को स्टोर करने और इन क्वेरी के नतीजों को वापस करने के लिए ज़िम्मेदार है.
  • अगर आपने Google गियर्स इंस्टॉल किया हुआ है, तो आपको गियर्स वर्शन मिलता है जो स्थानीय डेटाबेस की हर चीज़ सेव कर लेता है.
  • अगर आपके पास Google गियर्स इंस्टॉल नहीं है, तो आपको एक ऐसा वर्शन मिलता है जो क्वेरी को क्वेरी में स्टोर करता है और बिलकुल पूरा परिणाम संग्रहित नहीं करता (अत्यधिक धीमा प्रतिक्रियाशीलता), क्योंकि परिणाम कुकी में बहुत बड़े होते हैं.
इस आर्किटेक्चर के बारे में सबसे अच्छी बात यह है कि आपको पूरी दुकान के लिए if (online) {} की जांच नहीं करनी होगी. इसकी जगह, ऐप्लिकेशन में एक गियर्स चेक की जांच की जाती है, और उसके बाद सही अडैप्टर का इस्तेमाल किया जाता है.


गियर्स के स्थानीय डेटाबेस का इस्तेमाल करना

गियर्स के घटकों में से एक लोकल SQLite डेटाबेस है, जिसे एम्बेड किया गया है और वह आपके इस्तेमाल के लिए तैयार है. अगर आप MySQL या Oracle जैसे सर्वर-साइड डेटाबेस के लिए पहले API का उपयोग कर चुके हैं, तो यह एक आसान डेटाबेस API है जिससे आपको जानकारी मिलेगी.

लोकल डेटाबेस को इस्तेमाल करने का तरीका बहुत आसान है:

  • Google गियर्स ऑब्जेक्ट शुरू करें
  • डेटाबेस फ़ैक्ट्री ऑब्जेक्ट पाएं और डेटाबेस खोलें
  • SQL अनुरोध चलाना शुरू करें

चलिए, इन पर जल्दी से गौर करते हैं.


Google गियर ऑब्जेक्ट शुरू करें

आपके ऐप्लिकेशन को /gears/samples/gears_init.js के कॉन्टेंट में या तो सीधे या फिर अपनी JavaScript फ़ाइल में कोड पेस्ट करके पढ़ना चाहिए. <script src="..../gears_init.js" type="text/JavaScript"></script> को ट्रांसफ़र करने पर, आपके पास google.गियर नेमस्पेस का ऐक्सेस होगा.


कोई डेटाबेस फ़ैक्ट्री ऑब्जेक्ट पाएं और कोई डेटाबेस खोलें
var db = google.gears.factory.create('beta.database', '1.0');
db.open('testdb');

यह कॉल आपको एक डेटाबेस ऑब्जेक्ट देगा, जिसकी मदद से आप कोई डेटाबेस स्कीमा खोल सकते हैं. डेटाबेस खोलने पर, इन पर ऑरिजिन की नीति के वही नियम लागू होते हैं. इसलिए, आपके "testdb" और "testdb" का टकराव नहीं होता.


SQL से जुड़े अनुरोधों को लागू करना शुरू करें

अब हम डेटाबेस पर SQL अनुरोध भेजने के लिए तैयार हैं. जब हम "चुनने" के अनुरोध भेजते हैं, तो हम एक ऐसा नतीजा सेट वापस लाते हैं जिसे हम मनपसंद डेटा के लिए फिर से इस्तेमाल कर सकते हैं:

var rs = db.execute('select * from foo where name = ?', [ name ]);

'लौटाया गया नतीजा' सेट पर, ये तरीके अपनाए जा सकते हैं:

booleanisValidRow()
voidnext()
voidclose()
intfieldCount()
stringfieldName(int fieldIndex)
variantfield(int fieldIndex)
variantfieldByName(string fieldname)

ज़्यादा जानकारी के लिए, कृपया डेटाबेस मॉड्यूल एपीआई से जुड़ा दस्तावेज़ देखें. (नोटर का नोट: Google गियर एपीआई अब उपलब्ध नहीं है).


दो लेवल वाले एपीआई को इनकैप्सुलेट करने के लिए, गियर्सडीबी का इस्तेमाल करना

हम डेटाबेस को सीमित करना और कुछ सामान्य डेटाबेस टास्क को ज़्यादा सुविधाजनक बनाना चाहते थे. उदाहरण के लिए,

  • हम इस ऐप्लिकेशन को डीबग करते समय जनरेट किए गए SQL को लॉग करने का एक अच्छा तरीका चाहते थे.
  • हम सभी जगहों पर try{}catch(){} करने के बजाय, एक ही जगह पर अपवादों को मैनेज करना चाहते थे.
  • डेटा पढ़ते या लिखते समय हम परिणाम सेट के बजाय JavaScript ऑब्जेक्ट से निपटना चाहते थे.

एक सामान्य तरीके से इन समस्याओं को हल करने के लिए, हमने फ़ॉर्मेसबी नाम की एक ओपन सोर्स लाइब्रेरी बनाई है, जो डेटाबेस ऑब्जेक्ट को रैप करती है. अब हम आपको दिखाएंगे कि GAMSDB का इस्तेमाल कैसे किया जाता है.

शुरुआती सेट अप

हमारे window.onload कोड में, हमें यह पक्का करना होगा कि जिन डेटाबेस टेबल पर हम भरोसा करते हैं वे सही जगह पर हैं. अगर नीचे दिया गया कोड चलता है और अगर उपयोगकर्ता के पास गियर इंस्टॉल है, तो वे GearsBaseContent ऑब्जेक्ट बनाएंगे:

content = hasGears() ? new GearsBaseContent() : new CookieBaseContent();

इसके बाद, अगर डेटाबेस पहले से मौजूद नहीं है, तो हम उसे खोलेंगे और टेबल बनाएंगे:

db = new GearsDB('gears-base'); // db is defined as a global for reuse later!

if (db) {
  db.run('create table if not exists BaseQueries' +
         ' (Phrase varchar(255), Itemtype varchar(100))');
  db.run('create table if not exists BaseFeeds' + 
         ' (id varchar(255), JSON text)');
}

इस समय, हम पक्का हैं कि हमारे पास क्वेरी और फ़ीड को स्टोर करने के लिए एक टेबल है. कोड new GearsDB(name), दिए गए नाम वाले डेटाबेस की शुरुआत के लिए एक कैप्सूल तैयार करेगा. run वाला तरीका, निचले लेवल के execute तरीके को रैप करता है. हालांकि, यह डीबग करने के आउटपुट को कंसोल और ट्रैपिंग अपवादों में भी हैंडल करता है.


खोज के लिए इस्तेमाल हुए शब्द को जोड़ना

पहली बार ऐप्लिकेशन चलाने पर, आपको कुछ नहीं खोजा जाएगा. अगर आप प्रॉडक्ट में Nintendo Wii को खोजने की कोशिश करते हैं, तो हम इस खोज शब्द को BaseQuery टेबल में सेव कर लेंगे.

addQuery तरीके का गियर्स वर्शन इनपुट लेकर और insertRow के ज़रिए इसे सेव करके यह काम करता है:

var searchterm = { Phrase: phrase, Itemtype: itemtype };
db.insertRow('BaseQueries', searchterm); 

insertRow एक JavaScript ऑब्जेक्ट (searchterm) लेता है और उसे आपके लिए टेबल में INSERTS को हैंडल करता है. इसकी मदद से, कंस्ट्रेंट के बारे में जानकारी भी दी जा सकती है. उदाहरण के लिए, "बॉब" के एक खास यूआरएल को शामिल करने की सेटिंग. हालांकि, ज़्यादातर समय आप डेटाबेस में इन सीमाओं का प्रबंधन करेंगे.


खोज के लिए इस्तेमाल किए गए सभी शब्द पाना

आपकी पिछली खोजों की सूची भरने के लिए, हम selectAll नाम वाले एक अच्छे रैपर का इस्तेमाल करते हैं:

GearsBaseContent.prototype.getQueries = function() {
  return this.db.selectAll('select * from BaseQueries');
}

इससे JavaScript की उन श्रेणियों का कलेक्शन मिलेगा जो डेटाबेस की पंक्तियों से मेल खाती हैं (उदाहरण के लिए, [ { Phrase: 'Nintendo Wii', Itemtype: 'product' }, { ... }, ...]).

ऐसी स्थिति में, पूरी सूची लौटाना ठीक है. हालांकि, अगर आपके पास ज़्यादा डेटा है, तो हो सकता है कि आप चुनिंदा कॉल में कॉलबैक का इस्तेमाल करना चाहें, ताकि आप रिटर्न होने वाली हर लाइन पर काम कर सकें:

 db.selectAll('select * from BaseQueries where Itemtype = ?', ['product'], function(row) {
  ... do something with this row ...
});

यहां GAMSDB चुनने के कुछ और तरीके बताए गए हैं:

selectOne(sql, args)JavaScript ऑब्जेक्ट से मेल खाने वाला पहला/एक मिलान दिखाएं
selectRow(table, where, args, select)आम तौर पर, सामान्य मामलों में SQL को अनदेखा करने के लिए इस्तेमाल किया जाता है
selectRows(table, where, args, callback, select)SelectRow की तरह है, लेकिन कई नतीजों के लिए.

फ़ीड लोड करना

जब हमें Google Base से परिणाम फ़ीड मिलती है, तब हमें उसे डेटाबेस में सहेजने की आवश्यकता होती है:

content.setFeed({ id: id, JSON: json.toJSONString() });

... which calls ...

GearsBaseContent.prototype.setFeed = function(feed) {
  this.db.forceRow('BaseFeeds', feed);
}

हम पहले JSON फ़ीड लेते हैं और toJSONString तरीके का इस्तेमाल करके उसे एक स्ट्रिंग के रूप में दिखाते हैं. इसके बाद, हम feed ऑब्जेक्ट बनाएं और उसे forceRow तरीके से पास करें. forceRow किसी मौजूदा एंट्री का मौजूद न होने पर, INSERT एंट्री करेगा या मौजूदा एंट्री को अपडेट करेगा.


खोज के नतीजे दिखाना

हमारा ऐप्लिकेशन, किसी भी खोज के नतीजे, पेज के दाएं पैनल में दिखाता है. यहां बताया गया है कि हम खोज के लिए शब्द से जुड़े फ़ीड को कैसे वापस लाते हैं:

GearsBaseContent.prototype.getFeed = function(url) {
  var row = this.db.selectRow('BaseFeeds', 'id = ?', [ url ]);
  return row.JSON;
}

अब हमारे पास पंक्ति के लिए JSON है. इसलिए, eval() ऑब्जेक्ट को वापस पा सकता है:

eval("var json = " + jsonString + ";");

हम दौड़ों से दूर हैं और JSON से अपने पेज में interHTML सामग्री शुरू कर सकते हैं.


ऑफ़लाइन ऐक्सेस के लिए, संसाधन स्टोर का इस्तेमाल करना

हमें स्थानीय डेटाबेस से कॉन्टेंट मिल रहा है, इसलिए इस ऐप्लिकेशन को ऑफ़लाइन भी काम करना चाहिए?

नहीं, समस्या यह है कि इस ऐप्लिकेशन को शुरू करने के लिए, आपको इसके वेब संसाधन लोड करने होंगे, जैसे कि JavaScript, सीएसएस, एचटीएमएल, और इमेज. अभी यह दिख रहा है, अगर आपके उपयोगकर्ता ने नीचे दिए गए तरीके आज़माए हैं, तो भी ऐप्लिकेशन काम कर सकता है: ऑनलाइन शुरू करें, कुछ खोजें करें, ब्राउज़र करें, ऑफ़लाइन जाएं. यह काम कर सकता है, क्योंकि आइटम अब भी ब्राउज़र की कैश मेमोरी में रहेंगे. अगर ऐसा नहीं है, तो क्या होगा? हम चाहते हैं कि हमारे उपयोगकर्ता ऐप्लिकेशन को ऐक्सेस कर पाएं. ऐसा, रीबूट करने के बाद और उसके बाद भी हो सकता है.

ऐसा करने के लिए, हम LocalServer कॉम्पोनेंट का इस्तेमाल करते हैं और अपने रिसॉर्स कैप्चर करते हैं. जब आप कोई संसाधन कैप्चर करते हैं (जैसे कि ऐप्लिकेशन को चलाने के लिए आवश्यक HTML और JavaScript), तो गियर्स इन आइटम को सहेज लेगा और उन्हें वापस करने के लिए ब्राउज़र के अनुरोधों को फंसाएगा. स्थानीय सर्वर ट्रैफ़िक पुलिस की तरह काम करेगा और सेव की गई सामग्री को स्टोर से वापस कर देगा.

हम ResourceStore कॉम्पोनेंट का इस्तेमाल भी करते हैं. इसके लिए, आपको मैन्युअल तौर पर सिस्टम को बताना होता है कि आपको कौनसी फ़ाइलें कैप्चर करनी हैं. कई स्थितियों में, हो सकता है कि आप अपने ऐप्लिकेशन का वर्शन तैयार करना चाहें और लेन-देन के हिसाब से अपग्रेड की अनुमति दें. संसाधनों का एक सेट वर्शन को परिभाषित करता है. साथ ही, जब आप संसाधनों का कोई नया सेट रिलीज़ करते हैं, तब आप चाहते हैं कि आपके उपयोगकर्ता फ़ाइलों को आसानी से अपग्रेड करें. अगर यह आपका मॉडल है, तो आपके पास मैनेज किया जा रहा रिसॉर्स स्टोर एपीआई इस्तेमाल करने की सुविधा होगी.

हमारे संसाधनों को कैप्चर करने के लिए, GAMSBaseContent ऑब्जेक्ट:

  1. उन फ़ाइलों की कैटगरी सेट अप करें जिन्हें कैप्चर करना है
  2. स्थानीय सर्वर बनाएं
  3. नया ResourceStore खोलें या बनाएं
  4. स्टोर में पेजों को कैप्चर करने के लिए कॉल करें
// Step 1
this.storeName = 'gears-base';
this.pageFiles = [
  location.pathname,
  'gears_base.js',
  '../scripts/gears_db.js',
  '../scripts/firebug/firebug.js',
  '../scripts/firebug/firebug.html',
  '../scripts/firebug/firebug.css',
  '../scripts/json_util.js',    'style.css',
  'capture.gif' ];

// Step 2
try {
  this.localServer = google.gears.factory.create('beta.localserver', '1.0');
} catch (e) {
  alert('Could not create local server: ' + e.message);
  return;
}

// Step 3
this.store = this.localServer.openStore(this.storeName) || this.localServer.createStore(this.storeName);

// Step 4
this.capturePageFiles();

... which calls ...

GearsBaseContent.prototype.capturePageFiles = function() {
  this.store.capture(this.pageFiles, function(url, success, captureId) {
    console.log(url + ' capture ' + (success ? 'succeeded' : 'failed'));
  });
}

यहां ध्यान देने वाली बात यह है कि आपके पास सिर्फ़ अपने डोमेन पर मौजूद संसाधनों को कैप्चर करने का विकल्प होता है. हम इस सीमा तक पहुंच गए, जब हमने सीधे मूल "गियरs_db.js" फ़ाइल से उसके SVN ट्रंक में गियर्सडीबी JavaScript फ़ाइल तक पहुंचने का प्रयास किया. समाधान सरल है, बेशक, आपको कोई भी बाहरी संसाधन डाउनलोड करना है और उन्हें अपने डोमेन के अंतर्गत रखना है. ध्यान दें कि 302 या 301 रीडायरेक्ट काम नहीं करेंगे, क्योंकि लोकल सर्वर सिर्फ़ 200 (सफल) या 304 (बदलाव नहीं किए गए) सर्वर कोड स्वीकार करता है.

इसका असर पड़ता है. अगर आप images.yourdomain.com पर अपने चित्र रखते हैं, तो आप उन्हें कैप्चर नहीं कर पाएंगे. www1 और www2 एक दूसरे को नहीं देख सकते. सर्वर साइड प्रॉक्सी सेट अप किए जा सकते हैं. हालांकि, इससे आपका ऐप्लिकेशन एक से ज़्यादा डोमेन में बंट जाएगा.

ऑफ़लाइन ऐप्लिकेशन को डीबग करना

ऑफ़लाइन ऐप्लिकेशन को डीबग करना थोड़ा मुश्किल है. अब और भी स्थितियां देखी जा सकती हैं:

  • मैं ऐप्लिकेशन में पूरी तरह से ऑनलाइन हूं और कैश मेमोरी में सेव है
  • मैं ऑनलाइन हूं, लेकिन मैंने ऐप्लिकेशन ऐक्सेस नहीं किया. मुझे कैश मेमोरी में कुछ भी नहीं मिला
  • मैं ऑफ़लाइन हूं, लेकिन मैंने ऐप्लिकेशन ऐक्सेस किया है
  • मैं ऑफ़लाइन हूं और मैंने कभी ऐप्लिकेशन ऐक्सेस नहीं किया (यह जगह ठीक नहीं है!)

जीवन को आसान बनाने के लिए, हमने निम्न पैटर्न का उपयोग किया:

  • जब हम यह पक्का करना चाहते हैं कि ब्राउज़र सिर्फ़ कैश मेमोरी से कुछ न चुन रहा हो, तो हम Firefox (या आपकी पसंद के ब्राउज़र) में कैश मेमोरी बंद कर देते हैं
  • हम फ़ायरबग (और अन्य ब्राउज़र पर फ़ायरबग लाइट का परीक्षण करने के लिए) का उपयोग करके डीबग करते हैं; हम संपूर्ण स्थान पर console.log() का उपयोग करते हैं, और कहीं भी कंसोल का पता लगाते हैं
  • हम हेल्पर JavaScript कोड इसमें जोड़ते हैं:
    • हमें डेटाबेस साफ़ करने और हमें एक अच्छी तरह से करने की अनुमति देता है
    • कैप्चर की गई फ़ाइलों को हटा देता है. इसलिए, जब फिर से लोड किया जाता है, तो उन्हें फिर से इंटरनेट पर ले जाया जाता है (काम के दोहराए जाने पर उपयोगी ;)

पेज के बाईं ओर डीबग विजेट सिर्फ़ तब दिखता है, जब आपके डिवाइस पर गियर्स इंस्टॉल हो. इसमें क्लीनअप कोड के लिए कॉलआउट हैं:

GearsBaseContent.prototype.clearServer = function() {
  if (this.localServer.openStore(this.storeName)) {
    this.localServer.removeStore(this.storeName);
    this.store = null;
  }
}

GearsBaseContent.prototype.clearTables = function() {
  if (this.db) {
    this.db.run('delete from BaseQueries');
    this.db.run('delete from BaseFeeds');
  }
  displayQueries();
}

नतीजा

आप देख सकते हैं कि Google गियर के साथ काम करना काफ़ी सरल है. हमने डेटाबेस कॉम्पोनेंट को और भी आसान बनाने के लिए गियर्सडीबी का इस्तेमाल किया, और मैन्युअल संसाधनस्टोर का इस्तेमाल किया, जो हमारे उदाहरण के लिए बिलकुल सही था.

ऑनलाइन कॉन्टेंट किस जगह पर सेव किया जाए, यह तय करने के लिए आप ज़्यादातर इस जगह पर मौजूद होते हैं. डेटाबेस स्कीमा तय करने में समय लगाना ज़रूरी है. अगर आपको आने वाले समय में स्कीमा को बदलना पड़ता है, तो आपको उस बदलाव को मैनेज करना होगा, क्योंकि आपके मौजूदा उपयोगकर्ताओं के पास डेटाबेस का वर्शन पहले से मौजूद होगा. इसका मतलब है कि आपको किसी भी db अपग्रेड के साथ स्क्रिप्ट कोड भेजना होगा. बेशक, इससे इस समस्या को कम करने में मदद मिलेगी. हो सकता है कि आप GearShift का इस्तेमाल करना चाहें, जो छोटी लाइब्रेरी होती है. इसकी मदद से आप किए गए बदलावों को मैनेज कर सकते हैं.

हम यहां दिए गए नतीजों के साथ, मैनेज किए गए रिसॉर्सस्टोर का इस्तेमाल भी कर सकते थे, ताकि अपनी फ़ाइलों पर नज़र रखी जा सके:

  • हम अच्छे नागरिक होंगे और साफ़ भविष्य के अपग्रेड को सक्षम करने के लिए हमारी फ़ाइलों का वर्शन करेंगे
  • में प्रबंधित संसाधनस्टोर की एक सुविधा है जिससे आप किसी URL को सामग्री के किसी अन्य भाग के लिए उपनाम दे सकते हैं. एक मान्य वास्तुशिल्प विकल्प होगा गियर्स_base.js गैर-गीयर वर्शन होगा, और दूसरे नाम के साथ ऐसा होगा कि गियर्स ही गियर्स_बेस_विथ गियर्स.जेशन डाउनलोड करेंगे जिसमें सभी ऑफ़लाइन सहायता होगी.
हमने महसूस किया कि हमारे ऐप्लिकेशन के लिए सिर्फ़ एक इंटरफ़ेस सेट करना और दो तरीकों से उसे इस्तेमाल करना आसान था.

हम आशा करते हैं कि आपको आवेदनों को तैयार करना मज़ेदार और आसान लगा! अगर आपके पास कोई सवाल है या आप कोई ऐप्लिकेशन शेयर करना चाहते हैं, तो कृपया हमसे Google गियर्स फ़ोरम में जुड़ें.