database.yml & capistrano2

10月 4, 2008 · Posted in Promgramming · 4 Comments 

实验室的服务器配置好了apache2+passenger2的环境,就很开心试了capistrano2远程部署。

要使用capistrano2来作远程的deploy当然要把服务器配置好ssh,web server等,我的做法是创建一个deploy的user专门来干这档事,并把deploy加入到www-data组以便在服务器的空间有权限写入。不过在试用过程中发现如果是使用scm的话capistrano2是不管你database.yml(因为不可能把production server的db账户信息纳入版本控制),想想可能放在share目录下应该就可以解决(share目录专门放些不变的东西,如log,如一些如用户资源等静态数据),但具体怎样还是看看别人怎么做的,搜索一下看到这个POST。这位老兄加了个两个钩子,在setup和update_code时把事先准备的模板放到share目录中。但其实还有些问题,数据库的user并不一定就是server的user,最好还是在config/deploy.rb加上两个字段如db_user和db_passwd来设数据库。

看了下Capistrano2的文档,发现真是个好东东,简单又方便。

Ruby也要解放IO

08月 26, 2008 · Posted in Promgramming · Comment 

Ruby1.9的库,NerverBlock,非阻塞IO。

http://www.espace.com.eg/neverblock

看看它的官网上的benchmarks就知道真的是解放。

FxRuby初体验Part4

07月 2, 2008 · Posted in something · 1 Comment 

之前的:FxRuby初体验Part1Part2Part3

到了PictureBook的V0.4了。这个版本算是基本的功能都做足了,包括了加上了相册选择,相册持久化等等。

#album_list_view.rb
require 'fox16'
 
include Fox
 
class AlbumListView < FXList
  attr_reader :album_list
  def initialize(p, opts)
    super(p, :opts => opts)
  end
  def switcher=(sw)
    @switcher = sw
  end
 
  def add_album(album)
    appendItem(album.title)
    AlbumView.new(@switcher, album)
  end
   
  def album_list=(albums)
    @album_list = albums
    @album_list.each_album do |album|
      add_album(album)
    end
  end
end
   
#picture_book.rb
$KCODE = "U"
require 'fox16'
require 'yaml'
   
include Fox
   
require 'album'
require 'album_list'
require 'photo'
require 'photo_view'
require 'album_view'
require 'album_list_view'
   
class PictureBook < FXMainWindow
  def initialize(app)
    super(app, "Picture Book" , :width => 600, :height => 400)
    add_menu_bar
    begin
      @album_list = YAML.load_file("picturebook.yml" )
    rescue
      @album_list = AlbumList.new
      @album_list.add_album(Album.new("My Photos" ))
    end
    splitter = FXSplitter.new(self,
      :opts => SPLITTER_HORIZONTAL|LAYOUT_FILL)
    @album_list_view = AlbumListView.new(splitter, LAYOUT_FILL)
    @switcher = FXSwitcher.new(splitter, :opts => LAYOUT_FILL)
    @switcher.connect(SEL_UPDATE) do
      @switcher.current = @album_list_view.currentItem
    end
    @album_list_view.switcher = @switcher
    @album_list_view.album_list = @album_list
  end
   
   
  def create
    super
    show(PLACEMENT_SCREEN)
  end
   
    def add_menu_bar
      # 创建一个菜单栏的实例
      menu_bar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
      # 创建一个菜单栏项
      file_menu = FXMenuPane.new(self)
      FXMenuTitle.new(menu_bar, "文件" , :popupMenu => file_menu)
      # 下面是一个创建菜单栏项和所关联动作的绑定
      import_cmd = FXMenuCommand.new(file_menu, "导入..." )
      import_cmd.connect(SEL_COMMAND) do
        dialog = FXFileDialog.new(self, "导入图片" )
        dialog.selectMode = SELECTFILE_MULTIPLE
        dialog.patternList = ["JPEG Images (*.jpg, *.jpeg)" ]
        if dialog.execute != 0
          import_photos(dialog.filenames)
        end
      end
      new_album_command = FXMenuCommand.new(file_menu, “New Album…” )
      new_album_command.connect(SEL_COMMAND) do
        album_title = FXInputDialog.getString(”My Album” , self, “New Album” , “Name:” )
        if album_title
          album = Album.new(album_title)
          @album_list.add_album(album)
          @album_list_view.add_album(album)
          AlbumView.new(@switcher, album)
        end
      end
     exit_cmd = FXMenuCommand.new(file_menu, “退出” )# 一个简单的退出项
     exit_cmd.connect(SEL_COMMAND) do
      store_album_list
      exit
    end
  end
     
  def import_photos(filenames)
    filenames.each do |filename|
      photo = Photo.new(filename)
      current_album.add_photo(photo)
      current_album_view.add_photo(photo)
    end
    current_album_view.create
  end
 
  def current_album_view
    @switcher.childAtIndex(@switcher.current)
  end
   
  def current_album
    current_album_view.album
  end
   
  def store_album_list
    File.open(”picturebook.yml” , “w” ) do |io|
      io.write(YAML.dump(@album_list))
    end
  end
 
end
 
if __FILE__ == $0
  FXApp.new do |app|
    PictureBook.new(app)
    app.create
    app.run
  end
end

剩下的晚上再写。。。

FxRuby初体验Part3

07月 2, 2008 · Posted in Promgramming · Comment 

之前的:FxRuby初体验Part1Part2

这个V0.3的PictureBook添加了相册视图,也就是把相片都放到其中。看看下面的代码吧,我把每次都贴上完整的代码,方便大家复制粘帖:-)

#photo.rb
class Photo
  attr_reader :path
  def initialize(path)
    @path = path
  end
end
 
#album.rb
class Album
  attr_reader :title
  def initialize(title)
    @title = title
    @photos = []
  end
  def add_photo(photo)
    @photos << photo
  end
  def each_photo
    @photos.each { |photo| yield photo }
  end
end
 
#album_list.rb
class AlbumList
  def initialize
    @albums = []
  end
 
  def add_album(album)
    @albums << album
  end
  def remove_album(album)
    @albums.delete(album)
  end
  def each_album
    @albums.each { |album| yield album }
  end
end
 
#photo_view.rb
class PhotoView < FXImageFrame
  MAX_WIDTH = 200
  MAX_HEIGHT = 200
  def initialize(p, photo)
    super(p, nil)
    load_image(photo.path)
  end
  def load_image(path)
    File.open(path, “rb” ) do |io|
      self.image = FXJPGImage.new(app, io.read)
      scale_to_thumbnail
    end
  end
  def scaled_width(width)
    [width, MAX_WIDTH].min
  end
  def scaled_height(height)
    [height, MAX_HEIGHT].min
  end
  def scale_to_thumbnail
    aspect_ratio = image.width.to_f/image.height
    if image.width > image.height
      image.scale(
        scaled_width(image.width),
        scaled_width(image.width)/aspect_ratio,
        1
      )
    else
      image.scale(
        aspect_ratio*scaled_height(image.height),
        scaled_height(image.height),
        1
      )
    end
  end
end
  
#album_view.rb
require ‘photo_view’
class AlbumView < FXMatrix
  attr_reader :album
  def initialize(p, album)
    super(p, :opts => LAYOUT_FILL|MATRIX_BY_COLUMNS)
    @album = album
    @album.each_photo { |photo| add_photo(photo) }
  end
  def add_photo(photo)
    PhotoView.new(self, photo)
  end
  def layout
    self.numColumns = [width/PhotoView::MAX_WIDTH, 1].max
    super
  end
end
  
#picture_book.rb
require ‘fox16′
include Fox
require ‘album’
require ‘album_view’
require ‘photo’
class PictureBook < FXMainWindow
  def initialize(app)
    super(app, “Picture Book” , :width => 600, :height => 400)
    add_menu_bar
    @album = Album.new(”My Photos” )
    @album_view = AlbumView.new(self, @album)
  end
  def add_menu_bar
    menu_bar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
    file_menu = FXMenuPane.new(self)
    FXMenuTitle.new(menu_bar, “File” , :popupMenu => file_menu)
    import_cmd = FXMenuCommand.new(file_menu, “Import…” )
    import_cmd.connect(SEL_COMMAND) do
      dialog = FXFileDialog.new(self, “Import Photos” )
      dialog.selectMode = SELECTFILE_MULTIPLE
      dialog.patternList = ["JPEG Images (*.jpg, *.jpeg)" ]
      if dialog.execute != 0
        import_photos(dialog.filenames)
      end
    end
    exit_cmd = FXMenuCommand.new(file_menu, “Exit” )
    exit_cmd.connect(SEL_COMMAND) do
      exit
    end
  end
  def import_photos(filenames)
    filenames.each do |filename|
      photo = Photo.new(filename)
      @album.add_photo(photo)
      @album_view.add_photo(photo)
    end
    @album_view.create
  end
  def create
    super
    show(PLACEMENT_SCREEN)
  end
end
  
if __FILE__ == $0
  FXApp.new do |app|
    PictureBook.new(app)
    app.create
    app.run
  end
end

这里相对于上个版本的改动的地方有,PictureBook增加了菜单栏,增加了一个视图AlbumView,PhotoView实例的创建放在了AlbumView中,PhotoView中增加了图片的缩略图操作。

菜单栏的创建也听挺麻烦的,先创建FXMenuBar的实例,然后是创建FXMenuTitleFXMenuPane的实例,FXMenuTitle是FXMenuBar的下级元素,就是菜单栏的每一段,FXMenuPane是FXMenuTitle的弹出菜单。然后要创建FXMenuCommand,它是FXMenuPane的下级元素,实例化后就要用connect方法给出的代码块将其绑定到一定的行为上。

File>Importd这个动作是打开一个文件对话框FXFileDialog让你选择文件,然后用filenames方法获得选择得到的文件的数组。退出的菜单项很简单,就是一个exit方法。

在PhotoView中的图片操作功能是从FXImageFrame继承得到的,这个能力和接口很像RMagic。 AlbumView 是FXMatrix的实例,FXMatrix是一种布局管理器,它以行列的方式来对组件进行布局。好像布局管理器的基类就是FXPacker ,可以通过重写它的Layout方法来改变布局流。像这里就改变了FXMatrix的行数。

接着书中作者又改了一下,因为FXMatrix不能够在图片太多的情况下全部显示,会产生因为图片过多导致产生很多行,然后让超出主窗体的图片行无法看见,所以作者又对AlbumView换了一个布局管理器。

#album_view.rb
require 'photo_view'
class AlbumView < FXScrollWindow
  attr_reader :album
  def initialize(p, album)
    super(p, :opts => LAYOUT_FILL)
    @album = album
    FXMatrix.new(self, :opts => LAYOUT_FILL|MATRIX_BY_COLUMNS)
    @album.each_photo { |photo| add_photo(photo) }
  end
  def layout
    contentWindow.numColumns = [width/PhotoView::MAX_WIDTH, 1].max
    super
  end
  def add_photo(photo)
    PhotoView.new(contentWindow, photo)
  end
end

FXScrollWindow是另一种布局管理器,它只是多了滚动条。其中还是包含了一个FXMatrix。

FxRuby初体验Part2

07月 1, 2008 · Posted in Promgramming · Comment 

接上一篇:FxRuby初体验Part1

本书的入门例子是个相册管理的桌面应用,名曰Picture Book。这个例子书中用了5 Chapter(2-6)来讲,基本讲到了常用的Gui组件。

不废话现在来看看代码,下面是第一个版本的Picture Book App:

#photo.rb
class Photo
  attr_reader :path
  def initialize(path)
    @path = path
  end
end
 
#album.rb
class Album
  attr_reader :title
  def initialize(title)
    @title = title
    @photos = []
  end
  def add_photo(photo)
    @photos << photo
  end
  def each_photo
    @photos.each { |photo| yield photo }
  end
end
 
#album_list.rb
class AlbumList
  def initialize
    @albums = []
  end
 
  def add_album(album)
    @albums << album
  end
  def remove_album(album)
    @albums.delete(album)
  end
  def each_album
    @albums.each { |album| yield album }
  end
end
 
#photo_view.rb
class PhotoView < FXImageFrame
   def initialize(p, photo)
      super(p, nil)
      load_image(photo.path)
   end
   def load_image(path)
      File.open(path, “rb” ) do |io|
        self.image = FXJPGImage.new(app, io.read)
      end
   end
end
 
#picturebook.rb
require ‘fox16′
include Fox
require ‘photo’
require ‘photo_view’
class PictureBook < FXMainWindow
  def initialize(app)
    super(app, “Picture Book” , :width => 600, :height => 400)
    photo = Photo.new(”shoe.jpg” )
    photo_view = PhotoView.new(self, photo)
  end
  def create
    super
    show(PLACEMENT_SCREEN)
  end
end
if __FILE__ == $0
  FXApp.new do |app|
    PictureBook.new(app)
    app.create
    app.run
  end
end

这是个V0.1的版本。不过你从中看出这个应用写得很MVC。

Model部分就是Photo,Album,AlbumList三个,Controller部分(当然它还没有细化)就是PictureBook,View部分就是PhotoView。就是如此清晰的结构,我想如果是正在学着什么MFC的可怜人儿们看到了之后会把那本什么深入浅出MFC扔了吧。

对比那个HelloWorld,这堆代码除了多了几个普通的Ruby Class(扮演Model的那几个)外,就是多了一个继承自FXImageFrame的PhotoView,还有在FXMainWindow的构造方法中多了对PhotoView的实例化,实例化时将其自身挂钩到PictureBook(构造方法的第一个参数)。之后在App实例化后会实例化MainWindow,接着实例化MainWindow包含的组件,比如PhotoView这个FxImageFrame。PhotoView中对图片的包装是这样的,它先读入Photo的路径,然后用FxImage组件对图片进行包装,然后保存为自己的一个实例变量image中。

PictureBook的第一个版本就是这样。

接着下一篇讲下个版本和下下篇讲下下个版本,然后就介绍完了。

下一页 »