差沙的密碼 -- SSHWSFC's code
          閱讀本Blog請(qǐng)自備塑料袋一只
          posts - 14,  comments - 59,  trackbacks - 0
          前些天去參加了Google的開發(fā)日活動(dòng),由于之后直接就去郊區(qū)所以一直沒有時(shí)間寫blog來(lái)談?wù)劯邢?。首先是google的OpenSocial,進(jìn)入大廳簽到之后轉(zhuǎn)角過(guò)去就是個(gè)大網(wǎng)站的展臺(tái),每個(gè)柱子的一面是一個(gè)網(wǎng)站,都是OpenSocial的合作網(wǎng)站,有聚友,天際,天涯等。有幸跟聚友的CTO譚曉生先生和天際網(wǎng)的CTO郭應(yīng)壽先生聊了聊OpenSocial使用中的益處和遇到的問(wèn)題,感覺OpenSocial目前還是不太成熟,對(duì)比FB來(lái)說(shuō)還有一定的差距,比如沒有照片處理等等問(wèn)題。而且我始終有一種感覺,OpenSocial是一個(gè)google的標(biāo)準(zhǔn),但是各大網(wǎng)站在使用OpenSocial的時(shí)候幾乎都會(huì)加上自己的擴(kuò)展,這樣下去,最終OpenSocial統(tǒng)一平臺(tái)的目標(biāo)很難實(shí)現(xiàn),因?yàn)閮蓚€(gè)網(wǎng)站的Gidget幾乎不能通用,這些問(wèn)題OpenSocial的合作網(wǎng)站跟Google也在討論中。另外得到的消息是,OpenSocial可能也會(huì)考慮出一套XXml,規(guī)范化OpenSocial的使用,并借此加強(qiáng)安全性。
          稍后的OpenSocial專題topic中了解到了更多有關(guān)OpenSocial的信息,主要是Shindig了, 前一天還在跟白衣提議用ss做一個(gè)類似Shindig的東西,主要是做一個(gè)OpenSocial的實(shí)現(xiàn),當(dāng)時(shí)就想這玩意估計(jì)有了,但是沒想到是host到apache了,在apache的孵化器中大家可以自己找找。會(huì)議的時(shí)候逮住了一個(gè)google的人問(wèn)了一堆問(wèn)題,過(guò)后才知道原來(lái)是google中國(guó)sns的負(fù)責(zé)人。
          最大的收獲實(shí)在是太意外了,在中午休息的時(shí)候,走過(guò)過(guò)道到樓下吃飯,突然發(fā)現(xiàn)一個(gè)熟悉的身影坐在角落里一個(gè)人在玩電腦,我暈是Andy Rubin,Android的老大。居然就坐在那里,而且旁邊的人沒有人在意他,要知道聽android topic的人可不少呀,居然每一個(gè)人認(rèn)出他來(lái)的。我叫了朋友確認(rèn)一下,準(zhǔn)備上前打招呼。剛上去打了個(gè)招呼,握了個(gè)手,又來(lái)了一個(gè)人,他一下認(rèn)出Andy,并且跟Andy簡(jiǎn)短的交談了一下。我提議先照個(gè)相,照相后簡(jiǎn)短聊下那個(gè)人就走了。過(guò)后Andy說(shuō)那個(gè)人就是Google中國(guó)負(fù)責(zé)android的老大邸爍博士,我狂暈呀兩位老大都讓我給碰上了。稍候跟Andy聊了一下Android的發(fā)展,隨后他掏出一個(gè)android的原型機(jī),就是google IO大會(huì)上的那種機(jī)器。這里要說(shuō)明的是,不管在模擬器上android的表現(xiàn)如何,在真機(jī)上你的體驗(yàn)絕對(duì)絕對(duì)是不一樣的,太COOL了。尤其是第二屏的widget效果,還有那個(gè)street view效果,真機(jī)拿在手上體驗(yàn)就是不一樣呀~~~~ 隨后又了解到了一些android目前的發(fā)展情況,這里可以告訴大家的是,android是絕對(duì)值得期待的~!??!

          posted @ 2008-06-15 13:03 差沙 閱讀(2809) | 評(píng)論 (4)編輯 收藏

          經(jīng)過(guò)兩天的努力,終于在Android上面跑起來(lái)MSN了。現(xiàn)在實(shí)現(xiàn)了基本的聊天功能,打算陸續(xù)的把其他功能完善,萬(wàn)事開頭難,相信以后的工作會(huì)很順利。


          Gtalk的功能由于有官方支持,早就弄了跟這個(gè)差不多的版本。


          另外,這個(gè)軟件目前是以插件的形式開發(fā),多一個(gè)協(xié)議就是多一個(gè)apk,實(shí)現(xiàn)一些intent即可。官方的IM包里面有很多支持,可惜文檔沒有提及。

           

          Android中文論壇原帖

          posted @ 2008-03-21 01:59 差沙 閱讀(4229) | 評(píng)論 (2)編輯 收藏

          今天看到Air1.0和Ext2.0.2的發(fā)布消息,很是興奮,要知道Ext的每個(gè)版本升級(jí)都是很實(shí)惠的。

          Ext2.0.2的這次升級(jí)主要是針對(duì)Air的支持,看來(lái)他們的關(guān)系是越來(lái)越近了,我也借機(jī)小試了一下Air。

          簡(jiǎn)單說(shuō)說(shuō)Air的開發(fā)過(guò)程:

          1.先要下載jre 和 airSDK

          2.jre就不說(shuō)了,airSDK也是簡(jiǎn)單的解壓一下便可。

          可以看看SDK下面的bin目錄,一共倆文件,一個(gè)adl一個(gè)adt,adl是用來(lái)測(cè)試的,adt使用編輯發(fā)布的(ADT怎么讓我想起來(lái)android了)

          3.創(chuàng)建一個(gè)普通的目錄作為項(xiàng)目目錄。OK,可以寫頁(yè)面了。就是寫html js flash什么的,都可。

          4.編寫一個(gè)xml文件,名字不限。內(nèi)容嘛~~~~

          看看這個(gè)文件,airSDK\templates\descriptor-template.xml 里面有詳細(xì)的解釋,拿過(guò)來(lái)改改即可,給一個(gè)例子:


          <?xml version="1.0" encoding="UTF-8"?>
          <application xmlns="http://ns.adobe.com/air/application/1.0.M6">
              <id>examples.html.HelloWorld</id>
              <version>0.1</version>
              <filename>HelloWorld</filename>
              <initialWindow>
                  <content>HelloWorld.html</content>
                  <visible>true</visible>
                  <width>400</width>
                  <height>200</height>
              </initialWindow>
          </application>


          5.運(yùn)行airSDK\bin\adl.exe (那個(gè)創(chuàng)建的xml文件名),運(yùn)行即可。

          PS:我一般用eclipse來(lái)編輯,用外部命令的工具來(lái)運(yùn)行adl,很方便。

          簡(jiǎn)單的說(shuō)了一下Air的開發(fā)方法后,我們來(lái)簡(jiǎn)單的看一下Ext都對(duì)Air提供了什么支持。

          1.Ext.air.FileProvider

          Ext提供狀態(tài)保存的功能,在對(duì)AIr的支持中Ext實(shí)現(xiàn)了一個(gè)Provider,這個(gè)Provider把狀態(tài)保存在本地目錄的一個(gè)文件里。使用方法如下:


          // Initialize the state provider
          Ext.state.Manager.setProvider(new Ext.air.FileProvider({
          	file: 'ext.state',
          	// if first time running
          	defaultState : {
          		mainWindow : {
          			width:400,
          			height:200,
          			x:10,
          			y:10
          		}
          	}
          }));


          制定Provider為Ext.air.FileProvider即可,這個(gè)操作一般在onReady里面執(zhí)行。當(dāng)然需要你先創(chuàng)建一個(gè)ext.state文本文件,在程序根目錄下即可。這樣ext的應(yīng)用運(yùn)行時(shí),窗口等大小的調(diào)整,位置之類的調(diào)整都能保存下來(lái)了。很方便。

          這里包裝的Air代碼主要是:

          air.File.applicationStorageDirectory.resolvePath

          air.FileStream

          2.Ext.air.NativeWindow

          Ext可以調(diào)用Air實(shí)現(xiàn)Native的窗口。使用方法如下:


          	var win = new Ext.air.NativeWindow({
          		id: 'mainWindow',
          		instance: window.nativeWindow,
          		minimizeToTray: true,
          		trayIcon: 'ext-air/resources/icons/extlogo16.png',
          		trayTip: 'Simple Tasks',
          		trayMenu : [{
          			text: 'Open Simple Tasks',
          			handler: function(){
          				win.activate();
          			}
          		}, '-', {
          			text: 'Exit',
          			handler: function(){
          				air.NativeApplication.nativeApplication.exit();
          			}
          		}]
          	});


          我們可以看到,其中最吸引人的是系統(tǒng)托盤的功能,可以方便的指定系統(tǒng)托盤的各種屬性。

          這里包裝的主要是:

          window.runtime.flash.html.HTMLLoader.createRootWindow

          air.Screen.mainScreen.visibleBounds

          3.Ext.sql.Connection

          這個(gè)是重頭戲,對(duì)db的支持,我們知道Air的DB是采用sqlite3來(lái)實(shí)現(xiàn)的。Ext封裝了Air的db操作,簡(jiǎn)化統(tǒng)一了一些,而且提供了Store的支持,非常強(qiáng)大:

          讓我們簡(jiǎn)單看一下用法:

          首先取得connection

          var conn = Ext.sql.Connection.getInstance();

          而后打開db

          conn.open('ext.db');//這里的文件如果不存在會(huì)自動(dòng)創(chuàng)建

          創(chuàng)建Table


                  conn.createTable({
                      name: 'user',
                      key: 'userId',
                      fields: [
          			    {name: 'userId', type:'string'},
          			    {name: 'name', type:'string'},
          			    {name: 'pwd', type:'string'},
          			    {name: 'email', type:'string'}
          			]
              	});

          取得一個(gè)Table

          var userDao = conn.getTable('user','userId');

          查詢

          var users = userDao.select();//這里可以寫條件式

          添加


          var newuser = {
              userId : 'sshw',
              name : 'sshwsfc',
              pwd : 'test',
              email : 'sshwsfc@gmail.com'
          } 
          
          userDao.insert(newuser);


          感覺使用上還是蠻不錯(cuò)的,大家可以一點(diǎn)點(diǎn)試試看。

          值得一提的是,在源碼中發(fā)現(xiàn)Connection這里設(shè)計(jì)成了工廠的模式,Connection是一個(gè)偽接口,實(shí)現(xiàn)除了Air的還有GoogleGear的,會(huì)根據(jù)所處環(huán)境選擇,灰常的好。

          功能還在研究中,有心得了一點(diǎn)點(diǎn)給大家分享,

          PS:打算搞一個(gè)iphone的信息管理軟件練練手。反正都是sqlite的

          posted @ 2008-02-26 13:49 差沙 閱讀(4819) | 評(píng)論 (4)編輯 收藏

          在朋友和同事的極力推薦下最近開始看上了python,其實(shí)主要是還是因?yàn)閜ython是2007年度語(yǔ)言,怎么的也要與時(shí)俱進(jìn)呀.最近一路看來(lái)有些心得,希望能與大家分享,小弟其實(shí)也只接觸不到一周的python,有說(shuō)錯(cuò)的地方還望大家指出改正.

          不打算從py的語(yǔ)法基礎(chǔ)說(shuō)起了,直接說(shuō)說(shuō)對(duì)django的心得:

          接觸django首先需要了解可能就是他那個(gè)model,建立一個(gè)model就什么都有了,這對(duì)于搞java得人員來(lái)說(shuō)還是挺有吸引力的(當(dāng)然貌似對(duì)于動(dòng)態(tài)語(yǔ)言這都是小兒科),那么讓我們先看一個(gè)model的例子:

          偷懶了,直接拿django-admin里面的User出來(lái)了


          class User(models.Model): 
              username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric])) 
              first_name = models.CharField(_('first name'), maxlength=30, blank=True) 
              last_name = models.CharField(_('last name'), maxlength=30, blank=True) 
              email = models.EmailField(_('e-mail address'), blank=True) 
              password = models.CharField(_('password'), maxlength=128)) 
              class Meta: 
                  ordering = ('username',)

          每個(gè)屬性就是一個(gè)庫(kù)表的字段,定義起來(lái)非常簡(jiǎn)單明了,models里面提供了很多種類的Field類似上面的EmailField。不同的Field有不同的設(shè)置,可以看相應(yīng)的原來(lái)來(lái)了解相關(guān)的設(shè)置.

          在model class內(nèi)部還有一個(gè)class Meta,這個(gè)Class的屬性制定了這個(gè)表的一些存取策略,例如這里的ordering。MetaClass里面的屬性可以用model的_meta屬性取得。OK,那么這樣一個(gè)model怎么就能實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)表的靈活操作了呢。讓我們來(lái)看看吧。

          首先先分析一下/django/django/db/models/base.py這個(gè)文件,其中包含了models.Model這類的定義:

          看看class定義的第一行吧,第一行就夠我琢磨一陣子的了:


          class Model(object):
              __metaclass__ = ModelBase

          Model采用了new style class定義,關(guān)于這個(gè)內(nèi)容大家可以放狗看一下,第一行是一個(gè)__metaclass__屬性的定義,該屬性的值是ModelBase,這是一個(gè)類。__metaclass__的意思是,指定一個(gè)class,這個(gè)class的實(shí)例就是本class,相信您已經(jīng)暈了。那么就拿這個(gè)Model的例子來(lái)說(shuō)明一下,如果沒有__metaclass__這個(gè)屬性,產(chǎn)生一個(gè)實(shí)例就是正常的流程,有了這個(gè)屬性流程會(huì)有改變:

          首先調(diào)用BaseModel.__new__(cls, name, bases, attrs)這個(gè)方法,回返回的值是一個(gè)class類型,然后用這個(gè)class來(lái)創(chuàng)建實(shí)例。其實(shí)BaseModel就是Model的元類,來(lái)制定Model這個(gè)類的最終樣子。關(guān)于元類的更多信息請(qǐng)看這里

          那么我們的目光一下轉(zhuǎn)移到BaseModel這個(gè)類上,我有種直覺,Meta這個(gè)class最后可以用_meta來(lái)取就是在這里做的手腳,看一下BaseModel的定義吧,有點(diǎn)長(zhǎng):


          class ModelBase(type):
              "Metaclass for all models"
              def __new__(cls, name, bases, attrs):
                  # If this isn't a subclass of Model, don't do anything special.
                  if name == 'Model' or not filter(lambda b: issubclass(b, Model), bases):    #1
                      return super(ModelBase, cls).__new__(cls, name, bases, attrs)
          
                  # Create the class.
                  new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')})    #2
                  new_class.add_to_class('_meta', Options(attrs.pop('Meta', None)))     #3
                  new_class.add_to_class('DoesNotExist', types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}))
          
                  # Build complete list of parents                                      #4
                  for base in bases:
                      # TODO: Checking for the presence of '_meta' is hackish.
                      if '_meta' in dir(base):
                          new_class._meta.parents.append(base)
                          new_class._meta.parents.extend(base._meta.parents)
          
                  model_module = sys.modules[new_class.__module__]
          
                  if getattr(new_class._meta, 'app_label', None) is None:
                      # Figure out the app_label by looking one level up.
                      # For 'django.contrib.sites.models', this would be 'sites'.
                      new_class._meta.app_label = model_module.__name__.split('.')[-2]  #5
          
                  # Bail out early if we have already created this class.
                  m = get_model(new_class._meta.app_label, name, False)                 #6
                  if m is not None:
                      return m
          
                  # Add all attributes to the class.
                  for obj_name, obj in attrs.items():
                      new_class.add_to_class(obj_name, obj)                             #7
          
                  # Add Fields inherited from parents
                  for parent in new_class._meta.parents:
                      for field in parent._meta.fields:
                          # Only add parent fields if they aren't defined for this class.
                          try:
                              new_class._meta.get_field(field.name)
                          except FieldDoesNotExist:
                              field.contribute_to_class(new_class, field.name)          #8
          
                  new_class._prepare()
          
                  register_models(new_class._meta.app_label, new_class)                 #9
                  # Because of the way imports happen (recursively), we may or may not be
                  # the first class for this model to register with the framework. There
                  # should only be one class for each model, so we must always return the
                  # registered version.
                  return get_model(new_class._meta.app_label, name, False)              #10


          簡(jiǎn)單分析一下這個(gè)代碼:

          1. 檢查class是否為Model的子類,不是的話,不做任何處理,直接傳給父類處理,也就相當(dāng)于正常的處理了class,注意super在多重繼承的時(shí)候應(yīng)該嚴(yán)格使用

          2. 用type來(lái)創(chuàng)建類,創(chuàng)建的就是正常的ModelClass

          3. 這句很重要,add_to_class是Model里面的class方法,這個(gè)方法其實(shí)就是傳入name和value,給Model添加class屬性.看到了,原來(lái)神奇的_meta就是這么來(lái)的. 提到add_to_class方法,簡(jiǎn)單看一下它的代碼:


              def add_to_class(cls, name, value):
                  if name == 'Admin':
                      assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value))
                      value = AdminOptions(**dict([(k, v) for k, v in value.__dict__.items() if not k.startswith('_')]))
                  if hasattr(value, 'contribute_to_class'):
                      value.contribute_to_class(cls, name)
                  else:
                      setattr(cls, name, value)
              add_to_class = classmethod(add_to_class)


          最后一句是制定這個(gè)方法是class方法,特點(diǎn)就是方法的第一個(gè)參數(shù)是本class,其實(shí)classmethod就是一個(gè)裝飾器,在2。4之后可以使用@來(lái)簡(jiǎn)寫。這里不得不提的是他對(duì)Admin的特殊處理,雖然AdminOption不是在admin模塊里面的,但是這么做還是跟一個(gè)Admin的東東綁定起來(lái)了,在java的世界解耦是一件大事,看到下面還有對(duì)'contribute_to_class'這個(gè)方法的特殊處理,django為啥不弄的解耦點(diǎn)呢。而且同樣是包裝成Option,一個(gè)是在BaseModel里面弄(那個(gè)Meta的包裝),一個(gè)在add_to_class方法里面弄,實(shí)在有點(diǎn)不優(yōu)雅,可能還沒了解太多,不知道他的深度用意吧。

          4. Meta的集成,Option的這個(gè)類提供繼承方法

          5. 取得applabel,就是把model的名字分割取到數(shù)第二個(gè),我很喜歡-2這樣的設(shè)定

          6. get_model方法取得緩存里面的東西。

          7. 把所有的class attr拿出來(lái)搞一遍,一般的屬性就setattr弄回去了,要是這個(gè)屬性有contribute_to_class這個(gè)callable屬性,那就執(zhí)行之(Admin的處理完全也可以這樣,其實(shí)我們常用的objects就是用這個(gè)方法弄的)

          8. 每個(gè)Field調(diào)用自己的contribute_to_class方法來(lái)進(jìn)行特殊的處理

          9. 進(jìn)入緩存,,暫且叫緩存吧,里面的東西大家看看很簡(jiǎn)單 文件在 /django/django/db/models/loading.py 里面還是有很多內(nèi)容的

          10.看注釋說(shuō)的很清楚了,我們一定要在緩存里面拿model。

           

          其中需要指出的是,new_class._prepare() 這個(gè)方法,簡(jiǎn)單列出片段:


              def _prepare(cls):
                  # Creates some methods once self._meta has been populated.
                  opts = cls._meta
                  opts._prepare(cls)
          
                  ....
          
                  dispatcher.send(signal=signals.class_prepared, sender=cls)

          中間省略了一些代碼,不是我沒看懂的就是沒意思的,關(guān)鍵要看這個(gè)dispatcher呀。這里是監(jiān)聽者模式,dispatcher.send(signal=signals.class_prepared, sender=cls)放松了一個(gè)包含特定信號(hào)的事件,讓監(jiān)聽的人可以做相應(yīng)的處理。這樣的信號(hào)還有很多種,我們可以很簡(jiǎn)單的截獲信號(hào),處理相應(yīng)的內(nèi)容。也許您還記得,在我們創(chuàng)建db的時(shí)候,會(huì)提示創(chuàng)建一個(gè)超級(jí)用戶,其實(shí)就是用這個(gè)方法來(lái)弄的。

          那我為什么要把這個(gè)單獨(dú)拿出來(lái)說(shuō)呢,因?yàn)楸O(jiān)聽這個(gè)事件的人不是別人,是"objects"?。?!在文件/django/django/db/models/manager.py的開頭就有這樣的代碼:


          def ensure_default_manager(sender):
              cls = sender
              if not hasattr(cls, '_default_manager'):
                  # Create the default manager, if needed.
                  try:
                      cls._meta.get_field('objects')
                      raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % cls.__name__
                  except FieldDoesNotExist:
                      pass
                  cls.add_to_class('objects', Manager())
          
          dispatcher.connect(ensure_default_manager, signal=signals.class_prepared)


          定義了一個(gè)callable,然后監(jiān)聽signals.class_prepared信號(hào),呵呵,連上了吧,只要Class準(zhǔn)備好了,就調(diào)用這個(gè)方法。簡(jiǎn)單判斷有沒有_default_manager'屬性和meta里面的objects后,開始插入objects。cls.add_to_class('objects', Manager()) 很熟悉吧,前面講過(guò)不多說(shuō)了。

          PS:寫到這里不由得感嘆,為啥同樣是往Class里面加入東東,要搞這么多的花樣呢,我以前也寫過(guò)一個(gè)Rails配置加載過(guò)程的分析文檔,雖然一個(gè)簡(jiǎn)單的加載配置就把所有動(dòng)態(tài)語(yǔ)言玩?zhèn)€遍,但是這也太不規(guī)范了吧,可能不這么玩就不算“動(dòng)態(tài)”語(yǔ)言了吧,哈哈。

           

          終于Model的Class造好了,相信大家以后造自己的Class也能玩出更多的花樣。那么可以開始下一步了。我到老家后再寫吧,打算講講神奇的objects,也就是Manager,其實(shí)就是玩QuerySet。。那里有很多的__xxx__方法,很好很強(qiáng)大

          posted @ 2008-02-02 17:32 差沙 閱讀(3247) | 評(píng)論 (1)編輯 收藏
          Android是google為手機(jī)開發(fā)的操作系統(tǒng), 基于Linux2.6內(nèi)核.


          2007年11月12日(北美時(shí)間), Android的APP SDK公布, 開始了google手機(jī)的開發(fā)大賽. 我們致力于Android的開發(fā)文檔翻譯, 開發(fā)技術(shù)交流等工作, 希望為Android平臺(tái)在中國(guó)的推廣貢獻(xiàn)自己的力量.


          Andorid的SDK是完全針對(duì)java設(shè)計(jì)的, 甚至提供eclipse的插件, 作為一個(gè)javaer不研究實(shí)在可惜.

          現(xiàn)在中文文檔已經(jīng)有了初步進(jìn)展,  大家翻譯的熱情都很高漲. 論壇里的討論也十分熱烈, 歡迎您的訪問(wèn).

          我們的網(wǎng)站, http://www.androidcn.net

          中文文檔計(jì)劃:

          http://www.androidcn.net/wiki

          PS: 管理員您好, 不知道這個(gè)符不符合首頁(yè)發(fā)布的規(guī)則, 要是不妥我會(huì)撤下, 我們都想為Android中文化貢獻(xiàn)力量
          posted @ 2007-11-15 13:41 差沙 閱讀(2347) | 評(píng)論 (0)編輯 收藏
               摘要: 相信大家看了Ext2.0后, 印象最深的應(yīng)該是Ext的組件模式,很好的規(guī)范了組件設(shè)計(jì),用Manager的統(tǒng)一管理,也是很好的方式.下面簡(jiǎn)單分析一下Ext的組件結(jié)構(gòu).  閱讀全文
          posted @ 2007-10-20 20:01 差沙 閱讀(7740) | 評(píng)論 (25)編輯 收藏

          ProcessInstance里面有一個(gè)findToken(String tokenPath)方法。這里面寫的是tokenPath。 tokenPath跟文件系統(tǒng)的規(guī)則差不多。類似 /fork1/fork2 這樣的。

          那么,怎么到fork2下的一個(gè)分支token ?

          token自己也有findToken這個(gè)方法,不同的是ProcessInstance的是以rootToken為起點(diǎn),token自己的是以自己為起點(diǎn)。那么取到token2下面的分支

          token2.findToken("token")
          如果有返回token,沒有返回null


          至于token的名字,我剛才查源碼才發(fā)現(xiàn),只有在Fork節(jié)點(diǎn)才會(huì)給token賦予名字。。。

          那么token2.findToken("token") 這里"token"那里來(lái)

          命名的規(guī)則,如下。。 

              String tokenName = null;
              
          if ( transitionName != null ) {
                
          if ( ! parent.hasChild( transitionName ) ) {
                  tokenName 
          = transitionName;
                }
           else {
                  
          int i = 2;
                  tokenName 
          = transitionName + Integer.toString( i );
                  
          while ( parent.hasChild( tokenName ) ) {
                    i
          ++;
                    tokenName 
          = transitionName + Integer.toString( i );
                  }

                }

              }
           else // no transition name
                int size = ( parent.getChildren()!=null ? parent.getChildren().size()+1 : 1 );
                tokenName 
          = Integer.toString(size);
              }

              
          return tokenName; 



          這里"token"那里來(lái)?這個(gè)token名字,你自己可以根據(jù)命名規(guī)則得到 ??吹竭@里應(yīng)該很明了了

          token的命名規(guī)則;首先根據(jù)transitionName的名字命名,這個(gè)transitionName的名字是你自己的寫的你不可能不知道。 如果transitionName的名字重名了,加自然數(shù)區(qū)分 當(dāng)然,如果transitionName沒有名字,用分支的個(gè)數(shù)+1作為名字。

          應(yīng)該比較清楚了。

          PS:這個(gè)是qq聊天記錄的整理版,所以說(shuō)話比較詭異。為的是記錄下來(lái)避免忘記,也感謝群里的朋友。發(fā)現(xiàn)互相解決問(wèn)題是提高水平的一個(gè)捷徑。。

          posted @ 2007-04-24 16:04 差沙 閱讀(2388) | 評(píng)論 (1)編輯 收藏

          說(shuō)ruby是怪異的語(yǔ)法有點(diǎn)不妥當(dāng),動(dòng)態(tài)語(yǔ)言里面不乏這樣的語(yǔ)法出現(xiàn)。但是看了一些源碼后發(fā)現(xiàn),使用ruby的用法真的各有不同,就像大家以前說(shuō)的,ruby每個(gè)人寫出來(lái)的可能都不同。

          現(xiàn)來(lái)說(shuō)Rails里面如何加載config的吧。

          在java里面config絕對(duì)是一個(gè)resource文件,然后通過(guò)讀取配置的工具加入進(jìn)來(lái),在分析處理。

          在ROR里面完全不是這么回事。

          1.首先大家要了解的是,在我們啟動(dòng) ruby script/server 的時(shí)候,rails做了一系列的處理,最后他執(zhí)行了environment.rb

          ruby 代碼
          Rails::Initializer.run?do? | config | ????
          ??
          # ?這里能插入我們自己的配置。????
          ?? # ?config.?之類????
          end???

          這里的config其實(shí)是Initializer內(nèi)部的一個(gè)變量,掌控全局的配置信息,我們可以使用這個(gè)config來(lái)配置我們想要的。Rails::Initializer.run的源碼是這樣的,yield再一次顯示了他的威力,讓我們?cè)谂渲梦募械靡耘渲胏onfig。然后實(shí)例化了一個(gè)initializer?之后,把config作為參數(shù)傳入了。

          ruby 代碼
          def ?self.run(command? = ?:process,?configuration? = ?Configuration.new)????
          ??
          yield ?configuration? if ?block_given?????
          ??initializer?
          = ?new?configuration????
          ??initializer.send(command)????
          ??initializer????
          end???

          我們接著往下走,可以看到initializer?做了一系列的初始化工作,包括load_path的設(shè)定,路由的初始化,和activerecord的初始化。我們關(guān)心的還是配置如何起作用,那么來(lái)看看environments目錄下面的配置文件是如何導(dǎo)入的吧。

          ruby 代碼

          def ?load_environment????
          ??silence_warnings?do???
          ????config?
          = ?configuration????
          ????constants?
          = ?self. class .constants????
          ????eval(IO.read(configuration.environment_path),?binding)????
          ????(self.
          class .constants? - ?constants).each?do? | const | ????
          ??????Object.const_set(const,?self.
          class .const_get(const))????
          ????end???
          ??end???
          end???

          IO.read(configuration.environment_path) ,,這里就不使用什么回調(diào)不回調(diào)了,而是干脆IO拿出來(lái)eval一把,這里也是吃了一驚,這樣也可以呀~~~~~~~然后,我們可以看看,他處理常量的方法,把自己配置文件中的常量全部放入Object里面,起到全局常量的目的。

          最絕的還是initialize_framework_settings,使用了有一個(gè)ruby的技巧。

          ruby 代碼

          def ?initialize_framework_settings????
          ??configuration.frameworks.each?do?
          | framework | ????
          ????base_class?
          = ?framework.to_s.camelize.constantize.const_get( " Base " )????
          ???
          ????configuration.send(framework).each?do?
          | setting,?value | ????
          ??????base_class.send(
          " #{setting}= " ,?value)????
          ????end???
          ??end???
          end???

          configuration.frameworks里面存放的是rails個(gè)個(gè)組件的名字,比方說(shuō)active_record之類。然后把這個(gè)名字大寫轉(zhuǎn)換,然后用constantize取得ActiveRecord這個(gè)Module(注意,這些東西都在activesupport里面呢,activesupport/lib/active_support/core_ext/string/inflections.rb )。然后用const_get取得這個(gè)模塊的Base類,也就是ActiveRecord::Base這個(gè)類了(下面都叫做Base類),所有的Rails的組件都是這個(gè)命名規(guī)則改天我們自己想要做一個(gè)Rails的組件加進(jìn)來(lái),也可以這樣(但是要稍微修改一個(gè)源碼)。

          然后,我們吧config里面的內(nèi)容給Base類。configuration.send(framework)是調(diào)用一個(gè)組件名稱的方法,比方說(shuō)active_record,就是去的config里面的active_record屬性(這是最基本的),通過(guò)后面的do我們可以看到config返回的是一個(gè)hash,然后把hash中每一個(gè)key作為變量,value為傳入值,傳入Base類。。。這里大家應(yīng)該沒什么問(wèn)題了,看看我們的config文件是怎么寫的吧。

          ruby 代碼
          # ?Settings?specified?here?will?take?precedence?over?those?in?config/environment.rb????
          ???
          # ?In?the?development?environment?your?application's?code?is?reloaded?on????
          #
          ?every?request.??This?slows?down?response?time?but?is?perfect?for?development????
          #
          ?since?you?don't?have?to?restart?the?webserver?when?you?make?code?changes.????
          config.cache_classes? = ?false???
          ???
          # ?Log?error?messages?when?you?accidentally?call?methods?on?nil.????
          config.whiny_nils? = ?true???
          ???
          # ?Enable?the?breakpoint?server?that?script/breakpointer?connects?to????
          config.breakpoint_server? = ?true???
          ???
          # ?Show?full?error?reports?and?disable?caching????
          config.action_controller.consider_all_requests_local? = ?true???
          config.action_controller.perform_caching?????????????
          = ?false???
          config.action_view.cache_template_extensions?????????
          = ?false???
          config.action_view.debug_rjs?????????????????????????
          = ?true???
          ???
          # ?Don't?care?if?the?mailer?can't?send????
          config.action_mailer.raise_delivery_errors? = ?false???

          哦,看著很暈吧,config就是我們的配置對(duì)象,按照我們上面的說(shuō)法,config.action_view之類framework的變量應(yīng)該是一個(gè)hash才對(duì)呀,如果是hash的話,不應(yīng)該用這樣的方式傳入,可能會(huì)用 config.action_view = {:debug_rjs => true}來(lái)傳入。

          OK.我們來(lái)看這個(gè)變量到底是什么樣的hash。

          ruby 代碼
          def ?initialize????
          ??.????
          ??.????
          ??
          for ?framework? in ?default_frameworks????
          ????self.send(
          " #{framework}= " ,?OrderedOptions.new)????
          ??end???
          end???

          在初始化這些變量的時(shí)候,Rails給他賦值為OrderedOptions.new。這個(gè)特殊的類型可能就是關(guān)鍵。

          ruby 代碼
          class ?OrderedOptions? < ?OrderedHash? # :nodoc:????
          ?? def ?[] = (key,?value)????
          ????super(key.to_sym,?value)????
          ??end???
          ??????
          ??
          def ?[](key)????
          ????super(key.to_sym)????
          ??end???
          ???
          ??
          def ?method_missing(name,? * args)????
          ????
          if ?name.to_s? =~ ? / (. * ) = $ / ????
          ??????self[$
          1 .to_sym]? = ?args.first????
          ????
          else ???
          ??????self[name]????
          ????end???
          ??end???
          end???

          看到其中的玄妙了么,method_missing~~~??! 如果調(diào)用一個(gè)**=的方法 ,就像當(dāng)用傳入一個(gè)HASH的值,key就是方法的名字。

          也就是:config.action_view.debug_rjs??=?true?相當(dāng)于config.action_view[:debug_rjs] = true

          OK ,大體上描述了一下,可以看到簡(jiǎn)單的一個(gè)Rails初始化已經(jīng)給我們展示了幾乎全部ruby的靚麗之處,這能說(shuō)明,這個(gè)亮點(diǎn)肯定是貫穿rails的基本,在以后的深入研究中我們就能看到了。

          posted @ 2006-11-21 12:10 差沙 閱讀(3758) | 評(píng)論 (2)編輯 收藏

          為了記錄自己看Rails源碼的過(guò)程,全程記錄無(wú)廢話。

          我們看看script/server都干了什么

          require?File.dirname(__FILE__)? + ? ' /../config/boot '
          require?
          ' commands/server '

          引用了boot.rb這個(gè)文件。看來(lái)這個(gè)文件是rails啟動(dòng)的入口,來(lái)看看怎么回事吧。
          unless?defined?(RAILS_ROOT)
          ??root_path?
          =?File.join(File.dirname(__FILE__),?'..')

          ??unless?RUBY_PLATFORM?
          =~?/mswin32/
          ????require?
          'pathname'
          ????root_path?
          =?Pathname.new(root_path).cleanpath(true).to_s
          ??end

          ??RAILS_ROOT?
          =?root_path
          end
          這一部分定義了RAILS_ROOT這個(gè)系統(tǒng)的全局變量,指定了項(xiàng)目的根目錄,大家可以在以后華麗的使用了。

          下一部分是找到rails,粗略看一下。
          ??if?File.directory?("#{RAILS_ROOT}/vendor/rails")
          ????require?
          "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
          ??
          else
          ????require?
          'rubygems'
          這里能看到,他先跑到vendor/rails去找rails了,這就是我們?yōu)槭裁茨茉诓寮镉胷ails是原因。如果沒有那么gems的干活。
          接下來(lái)是初始化一下load_path,沒什么看的了。boot.rb就這樣的吧。

          回到script/server的第二行,包含了'commands/server'這個(gè)文件,這個(gè)文件是什么?Rails的源碼里面找吧。我們?cè)赗ails的源碼里面找到這個(gè)文件。
          require?'active_support'
          require?
          'fileutils'

          begin
          ??require_library_or_gem?
          'fcgi'
          rescue?Exception
          ??
          #?FCGI?not?available
          end

          server?
          =?case?ARGV.first
          ??when?
          "lighttpd"
          ????ARGV.shift
          ??when?
          "webrick"
          ????ARGV.shift
          ??
          else
          ????
          if?RUBY_PLATFORM?!~?/mswin/?&&?!silence_stderr?{?`lighttpd?-version`?}.blank??&&?defined?(FCGI)
          ??????
          "lighttpd"
          ????
          else
          ??????
          "webrick"
          ????end
          end

          if?server?==?"webrick"
          ??puts?
          "=>?Booting?WEBrick"
          else
          ??puts?
          "=>?Booting?lighttpd?(use?'script/server?webrick'?to?force?WEBrick)"
          end

          FileUtils.mkdir_p(
          %w(?tmp/sessions?tmp/cache?tmp/sockets?))
          require?
          "commands/servers/#{server}"
          沒想到ActiveRecord居然是在這里引用的,這個(gè)ActiveRecord里面擴(kuò)展了很對(duì)Ruby的既有類型,所以我們看源碼的時(shí)候如果發(fā)現(xiàn)有不熟悉的方法,就來(lái)這里找找,當(dāng)然,看Rails的API是最好的選擇。

          從參數(shù)一目了然,我們可以傳入server的名字,lighttpd和webrick,根據(jù)不同的server選擇不同的server文件來(lái)讀取。我們還是看看webrick的吧。

          require?'webrick'
          require?
          'optparse'

          OPTIONS?
          =?{
          ??:port????????????
          =>?3000,
          ??:ip??????????????
          =>?"0.0.0.0",
          ??:environment?????
          =>?(ENV['RAILS_ENV']?||?"development").dup,
          ??:server_root?????
          =>?File.expand_path(RAILS_ROOT?+?"/public/"),
          ??:server_type?????
          =>?WEBrick::SimpleServer,
          ??:charset?????????
          =>?"UTF-8",
          ??:mime_types??????
          =>?WEBrick::HTTPUtils::DefaultMimeTypes
          }

          ARGV.options?do?
          |opts|
          ??script_name?
          =?File.basename($0)
          ??opts.banner?
          =?"Usage:?ruby?#{script_name}?[options]"

          ??opts.separator?
          ""

          ??opts.on(
          "-p",?"--port=port",?Integer,
          ??????????
          "Runs?Rails?on?the?specified?port.",
          ??????????
          "Default:?3000")?{?|v|?OPTIONS[:port]?=?v?}
          ??opts.on(
          "-b",?"--binding=ip",?String,
          ??????????
          "Binds?Rails?to?the?specified?ip.",
          ??????????
          "Default:?0.0.0.0")?{?|v|?OPTIONS[:ip]?=?v?}
          ??opts.on(
          "-e",?"--environment=name",?String,
          ??????????
          "Specifies?the?environment?to?run?this?server?under?(test/development/production).",
          ??????????
          "Default:?development")?{?|v|?OPTIONS[:environment]?=?v?}
          ??opts.on(
          "-m",?"--mime-types=filename",?String,
          ??????????????????
          "Specifies?an?Apache?style?mime.types?configuration?file?to?be?used?for?mime?types",
          ??????????????????
          "Default:?none")?{?|mime_types_file|?OPTIONS[:mime_types]?=?WEBrick::HTTPUtils::load_mime_types(mime_types_file)?}

          ??opts.on(
          "-d",?"--daemon",
          ??????????
          "Make?Rails?run?as?a?Daemon?(only?works?if?fork?is?available?--?meaning?on?*nix)."
          ??????????)?{?OPTIONS[:server_type]?
          =?WEBrick::Daemon?}

          ??opts.on(
          "-c",?"--charset=charset",?String,
          ??????????
          "Set?default?charset?for?output.",
          ??????????
          "Default:?UTF-8")?{?|v|?OPTIONS[:charset]?=?v?}

          ??opts.separator?
          ""

          ??opts.on(
          "-h",?"--help",
          ??????????
          "Show?this?help?message.")?{?puts?opts;?exit?}

          ??opts.parse!
          end

          ENV[
          "RAILS_ENV"]?=?OPTIONS[:environment]
          RAILS_ENV.replace(OPTIONS[:environment])?
          if?defined?(RAILS_ENV)

          require?RAILS_ROOT?
          +?"/config/environment"
          require?
          'webrick_server'

          OPTIONS[
          'working_directory']?=?File.expand_path(RAILS_ROOT)

          puts?
          "=>?Rails?application?started?on?http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
          puts?
          "=>?Ctrl-C?to?shutdown?server;?call?with?--help?for?options"?if?OPTIONS[:server_type]?==?WEBrick::SimpleServer
          DispatchServlet.dispatch(OPTIONS)
          本來(lái)不想把大段的代碼貼上來(lái),但是這里面的內(nèi)容可能大家都比較關(guān)心,涉及到server的啟動(dòng)參數(shù)。
          ??:port????????????=>?端口,
          ??:ip??????????????
          =>?server ip,
          ??:environment?????
          =>運(yùn)行環(huán)境,
          ??:server_root?????
          =>?web訪問(wèn)的目錄,(很多人問(wèn)這個(gè)怎么改)
          ??:server_type?????
          =>?WEBrick::SimpleServer,
          ??:charset?????????
          =>?"UTF-8", 編碼
          ??:mime_types??????
          =>?WEBrick::HTTPUtils::DefaultMimeTypes

          后面的require?引入了兩個(gè)文件,一個(gè)是'webrick_server',別看,就是他。另外一個(gè)是config/environment,這個(gè)文件是系統(tǒng)的全局配置文件,很重要,我們還是下次看看這個(gè)文件去吧。里面還真挺有意思。

          (不知道blogjava讓不讓寫ROR的文章,看到有人寫了所以放在首頁(yè)了,如果不妥,我會(huì)盡快刪除)
          posted @ 2006-11-20 23:43 差沙 閱讀(4584) | 評(píng)論 (0)編輯 收藏
          這家伙很懶,但起碼還是寫了一句話。

          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          常用鏈接

          留言簿(8)

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 连山| 虎林市| 杭锦后旗| 重庆市| 清水河县| 海安县| 昭通市| 呼伦贝尔市| 云梦县| 江津市| 高碑店市| 赤水市| 稻城县| 乐业县| 江源县| 富裕县| 古田县| 宁国市| 新兴县| 罗江县| 松溪县| 景宁| 连南| 桐柏县| 新巴尔虎左旗| 通州市| 米脂县| 琼海市| 蓝山县| 凉山| 开封市| 晋州市| 正安县| 呼和浩特市| 乌拉特前旗| 永川市| 微博| 乌海市| 福安市| 新余市| 上虞市|