liars 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,148 @@
1
+ Liars is a tiny MVC web framework.
2
+ ==================================
3
+
4
+ "liars" = "#{'rail'.reverse}s".
5
+ It's a very quick and dirty hack, just demonstrating some concepts. As its name said, Don't trust it. :-)
6
+
7
+ Install
8
+ =======
9
+
10
+ gem install liars.
11
+
12
+
13
+ Usage
14
+ =====
15
+
16
+ 1. Create a new scaffold file. The command below generates a scaffold ruby file named test.rb.
17
+ liars -s test
18
+ 2. Run it. The command below also generates a database file named db.yaml.
19
+ liars test.rb
20
+ 3. Now lauch your browser to <http://localhost:2008>
21
+
22
+ Help
23
+ ====
24
+
25
+ liars --help
26
+
27
+ An extra blog example:
28
+ ======================
29
+
30
+ Copy code below blog.rb to a new ruby file such as blog.rb, then run:
31
+
32
+ liars blog.rb -d blog.yaml
33
+
34
+ blog.rb:
35
+
36
+ module Liars
37
+ # Model ======================================================================
38
+ class Article < M
39
+ has_field :title
40
+ has_field :content
41
+ has_many :comments
42
+ end
43
+
44
+ class Comment < M
45
+ has_field :title
46
+ has_field :content
47
+ belongs_to :article
48
+ end
49
+
50
+ class ArticleC < C
51
+ route_of :index, '/', '/index', '/default'
52
+ def index
53
+ @articles = Article.find(:all)
54
+ render
55
+ end
56
+
57
+ route_of :show, '/show/(\d+)'
58
+ def show(id)
59
+ @article = Article.find(id.to_i)
60
+ render
61
+ end
62
+
63
+ route_of :create, '/create'
64
+ def create
65
+ Article.create(params[:article])
66
+ redirect_to '/'
67
+ end
68
+
69
+ route_of :add_comment, '/add_comment/(\d+)'
70
+ def add_comment(id)
71
+ @article = Article.find(id.to_i)
72
+ @article.comments << Comment.create(params[:comment])
73
+ @article.save
74
+ redirect_to "/show/#{id}"
75
+ end
76
+
77
+ route_of :style, '/styles.css'
78
+ def style
79
+ @headers["Content-Type"] = "text/css; charset=utf-8"
80
+ @body = %[
81
+ body {
82
+ font-family: Utopia, Georga, serif;
83
+ }
84
+ h1 {
85
+ background-color: #fef;
86
+ margin: 0; padding: 10px;
87
+ }
88
+ div {
89
+ padding: 10px;
90
+ }
91
+ ]
92
+ end
93
+ end
94
+
95
+ class ArticleV < V
96
+ def layout
97
+ html do
98
+ head do
99
+ title 'Liars never tell lies!'
100
+ link :rel => 'stylesheet', :type => 'text/css',
101
+ :href => '/styles.css', :media => 'screen'
102
+ end
103
+ body do
104
+ h1 { a 'Articles', :href => "/" }
105
+ div do
106
+ yield
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def index
113
+ h1 'Articles'
114
+ hr
115
+ @articles.each do |ar|
116
+ b ar.title
117
+ p ar.content
118
+ a 'show comments', :href=> "/show/#{ar.id}"
119
+ hr
120
+ end
121
+ form :action=>'/create', :method=>'Post' do
122
+ input :type=>'text', :name=>'article[title]'; br
123
+ textarea '', :name=>'article[content]'; br
124
+ input :type=>'submit'
125
+ end
126
+ end
127
+
128
+ def show
129
+ h1 'Articles'
130
+ a 'index', :href=> "/"
131
+ hr
132
+ b @article.title
133
+ p @article.content
134
+ h1 'Comments'
135
+ hr
136
+ @article.comments.each do |c|
137
+ b c.title
138
+ p c.content
139
+ end
140
+ hr
141
+ form :action=> "/add_comment/#{@article.id}", :method=>'Post' do
142
+ input :type=>'text', :name=>'comment[title]'; br
143
+ textarea '', :name=>'comment[content]'; br
144
+ input :type=>'submit'
145
+ end
146
+ end
147
+ end
148
+ end
data/bin/liars CHANGED
@@ -16,16 +16,18 @@ if conf.rc and File.exists?( conf.rc )
16
16
  end
17
17
 
18
18
  opts = OptionParser.new do |opts|
19
- opts.banner = "用法: liars example.rb..."
20
- opts.define_head "Liars, 超小型的Ruby MVC Web开发框架 Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
19
+ opts.banner = "Liars, a tiny MVC web framework. "
20
+ # opts.define_head "Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
21
+ opts.separator "usage: liars -s test.rb && liars test.rb"
22
+ opts.separator "see http://github.com/luonet/liars for more details"
21
23
  opts.separator ""
22
- opts.separator " 选项列表:"
24
+ opts.separator "options:"
23
25
 
24
- opts.on("-h", "--host HOSTNAME", "Web服务器绑定地址(默认为#{conf.host})") { |conf.host| }
25
- opts.on("-p", "--port NUM", "Web服务器绑定端口(默认为#{conf.port})") { |conf.port| }
26
- opts.on("-d", "--database FILE", "数据库文件(默认为#{conf.db})") { |conf.db| }
27
- opts.on("-c", "--console", "运行在irb模式") { conf.server = :console }
28
- opts.on("-s", "--scaffold FILE", "快速创建一个模板") do |conf.scaffold|
26
+ opts.on("-h", "--host HOSTNAME", "web server host name(default #{conf.host})") { |conf.host| }
27
+ opts.on("-p", "--port NUM", "Web server binding port(default #{conf.port})") { |conf.port| }
28
+ opts.on("-d", "--database FILE", "database file (default #{conf.db})") { |conf.db| }
29
+ opts.on("-c", "--console", "running in irb mode") { conf.server = :console }
30
+ opts.on("-s", "--scaffold FILE", "generates a scaffold file") do |conf.scaffold|
29
31
  conf.scaffold =~ /^(\w+)(\.rb)?$/
30
32
  File.open("#{Dir.pwd}/#{$1}.rb", 'w') do |f|
31
33
  class_name = $1.singularize.camelize
@@ -61,19 +63,19 @@ module Liars
61
63
  end
62
64
  EOF
63
65
  end
64
- puts "模板文件#{$1}.rb创建成功"
66
+ puts "template #{$1}.rb generated"
65
67
  exit
66
68
  end
67
69
 
68
70
  opts.separator ""
69
- opts.separator "其他选项:"
71
+ opts.separator "other options:"
70
72
 
71
- opts.on_tail("-?", "--help", "显示帮助信息") do
73
+ opts.on_tail("-?", "--help", "show help messages") do
72
74
  puts opts
73
75
  exit
74
76
  end
75
77
 
76
- opts.on_tail("-v", "--version", "显示版本信息") do
78
+ opts.on_tail("-v", "--version", "show version") do
77
79
  class << Gem; attr_accessor :loaded_specs; end
78
80
  puts Gem.loaded_specs['liars'].version
79
81
  exit
@@ -95,7 +97,6 @@ if conf.server == :console
95
97
  ENV['IRBRC'] = ".irbrc" if File.exists? ".irbrc"
96
98
  IRB.start
97
99
  else
98
- # 建立数据库
99
100
  Liars::DbEngine.db_name = conf.db
100
101
  Liars::DbEngine.create_db
101
102
 
@@ -109,4 +110,4 @@ else
109
110
  Liars::DbEngine.write_db
110
111
  end
111
112
  s.start
112
- end
113
+ end
@@ -7,37 +7,37 @@ module Liars
7
7
  def subclasses; @@subclasses; end
8
8
 
9
9
  def run(r=$stdin, e=ENV)
10
- route = e['PATH_INFO']
11
- @@subclasses.each do |klass|
12
- action, args = klass.get_action_and_args(route)
13
- if action
14
- controller = klass.new(r, e, e['REQUEST_METHOD']||"GET")
15
- return controller.send(action, *args) && controller
16
- end
17
- end
10
+ route = e['PATH_INFO']
11
+ @@subclasses.each do |klass|
12
+ action, args = klass.get_action_and_args(route)
13
+ if action
14
+ controller = klass.new(r, e, e['REQUEST_METHOD']||"GET")
15
+ return controller.send(action, *args) && controller
16
+ end
17
+ end
18
18
  end
19
19
 
20
20
  def route_of(action, *routes)
21
- @@routes ||= {}
22
- @@routes[action] = routes
21
+ @@routes ||= {}
22
+ @@routes[action] = routes
23
23
  end
24
24
 
25
25
  # 实际上是返回一个action的名称和这个action所有可能用到的参数列表
26
26
  # 如edit上映射的route是'/edit/(\d+)',而实际访问的路径是'/edit/1'时
27
27
  # 1将会被作为一个参数传给edit方法
28
28
  def get_action_and_args(route)
29
- @@routes.each do |action, action_routes|
30
- action_routes.find do |r|
31
- match = Regexp.new("^#{r}$").match(route)
32
- return action, match[1..-1] if match
33
- end
29
+ @@routes.each do |action, action_routes|
30
+ action_routes.find do |r|
31
+ match = Regexp.new("^#{r}$").match(route)
32
+ return action, match[1..-1] if match
33
+ end
34
34
  end
35
35
  end
36
36
  end
37
37
 
38
38
  def initialize(r, e, m)
39
39
  @status, @method, @env, @headers, @root = 200, m.downcase, e,
40
- {'Content-Type'=>'text/html'}, e["SCRIPT_NAME"].sub(/\/$/,'')
40
+ {'Content-Type'=>'text/html'}, e["SCRIPT_NAME"].sub(/\/$/,'')
41
41
  @params = qsp(e["QUERY_STRING"])
42
42
  @cookies = kp(e["HTTP_COOKIE"])
43
43
  @params.merge!(qsp(r.read)) if @method == "post"
@@ -73,30 +73,30 @@ module Liars
73
73
 
74
74
  def qsp(qs, d='&;')
75
75
  (qs || '').split(/[#{d}] */n).inject({}) do |h, p|
76
- k, v = un(p).split('=', 2)
77
- if (k = k.split(/[\]\[]+/)).length == 1
78
- h[k[0].to_sym] = v
79
- else
80
- (h[k[0].to_sym] ||= {})[k[1].to_sym] = v
81
- end
82
- h
76
+ k, v = un(p).split('=', 2)
77
+ if (k = k.split(/[\]\[]+/)).length == 1
78
+ h[k[0].to_sym] = v
79
+ else
80
+ (h[k[0].to_sym] ||= {})[k[1].to_sym] = v
81
+ end
82
+ h
83
83
  end
84
84
  end
85
85
 
86
86
  def kp(s); qsp(s, ';,'); end
87
-
87
+
88
88
  def render(action=(caller[0]=~/`(\w+)'/;$1))
89
89
  # 查找当前controller对应的view,然后根据action来找到渲染方法
90
90
  name = (self.class.to_s =~ /(\w+)(C|Controller)$/; $1)
91
91
  view_class = eval("#{name}View") rescue eval("#{name}V")
92
92
  view_instance = view_class.new
93
93
  instance_variables.each do |iv|
94
- view_instance.instance_variable_set(iv, instance_variable_get(iv))
94
+ view_instance.instance_variable_set(iv, instance_variable_get(iv))
95
95
  end
96
96
  render_result = view_instance.respond_to?(:layout) ?
97
- view_instance.send(:layout, &view_instance.method(action)) :
98
- view_instance.send(action)
97
+ view_instance.send(:layout, &view_instance.method(action)) :
98
+ view_instance.send(action)
99
99
  @body = view_instance.stream || render_result
100
100
  end
101
101
  end
102
- end
102
+ end
data/lib/db.rb CHANGED
@@ -22,99 +22,99 @@ module Liars
22
22
  class DbEngine
23
23
  class << self
24
24
  def all_models
25
- @all_models ||= []
25
+ @all_models ||= []
26
26
  end
27
27
 
28
28
  def db_name
29
- @db_name || "db.yaml"
29
+ @db_name || "db.yaml"
30
30
  end
31
31
 
32
32
  def db_name=(name)
33
- @db_name = name
33
+ @db_name = name
34
34
  end
35
-
35
+
36
36
  def create_db
37
- return if File.exists?(db_name)
38
- data = all_models.inject({}) do |data_hash, model|
39
- data_hash[model.to_s.to_sym] = { :max_id=>0, :records=>[] }
40
- data_hash
41
- end
42
- write_db(data)
43
- end
44
-
37
+ return if File.exists?(db_name)
38
+ data = all_models.inject({}) do |data_hash, model|
39
+ data_hash[model.to_s.to_sym] = { :max_id=>0, :records=>[] }
40
+ data_hash
41
+ end
42
+ write_db(data)
43
+ end
44
+
45
45
  def write_db(data=nil)
46
- File.open(db_name, "w") {|f| YAML.dump((data || @db_data), f)}
46
+ File.open(db_name, "w") {|f| YAML.dump((data || @db_data), f)}
47
47
  end
48
48
 
49
49
  def db_data
50
- @db_data ||= YAML.load_file(db_name)
50
+ @db_data ||= YAML.load_file(db_name)
51
51
  end
52
52
 
53
53
  def records_of(klass)
54
- db_data[klass.to_s.to_sym][:records]
54
+ db_data[klass.to_s.to_sym][:records]
55
55
  end
56
56
 
57
57
  def record_of(obj)
58
- records_of(obj.class).find {|x| x[:id] == obj.id} if obj.id
58
+ records_of(obj.class).find {|x| x[:id] == obj.id} if obj.id
59
59
  end
60
60
 
61
61
  def increase_max_id_of(klass)
62
- db_data[klass.to_s.to_sym][:max_id] += 1
62
+ db_data[klass.to_s.to_sym][:max_id] += 1
63
63
  end
64
64
 
65
65
  def find(klass, ids)
66
- case ids
67
- when [] then []
68
- when :all then records_of(klass).collect {|r| klass.new(r)}
69
- when Array then find_records(klass, ids).collect! {|r| klass.new(r)}
70
- else find_records(klass, [ids]).collect! {|r| klass.new(r)}.first
66
+ case ids
67
+ when [] then []
68
+ when :all then records_of(klass).collect {|r| klass.new(r)}
69
+ when Array then find_records(klass, ids).collect! {|r| klass.new(r)}
70
+ else find_records(klass, [ids]).collect! {|r| klass.new(r)}.first
71
71
  end
72
72
  end
73
73
 
74
74
  def find_records(klass, ids)
75
- records_of(klass).select {|x| ids.include? x[:id]}
75
+ records_of(klass).select {|x| ids.include? x[:id]}
76
76
  end
77
77
 
78
78
  def insert(obj)
79
- records_of(obj.class) << obj.data
80
- obj
79
+ records_of(obj.class) << obj.data
80
+ obj
81
81
  end
82
82
 
83
83
  def delete(obj)
84
- records_of(obj.class).delete_if {|x| x[:id] == obj.id }
84
+ records_of(obj.class).delete_if {|x| x[:id] == obj.id }
85
85
  end
86
86
 
87
87
  def update(obj)
88
- record_of(obj).merge!(obj.data)
89
- obj
88
+ record_of(obj).merge!(obj.data)
89
+ obj
90
90
  end
91
91
 
92
92
  def save(obj)
93
- if obj.new?
94
- obj.instance_variable_set("@id", increase_max_id_of(obj.class))
95
- new_record = true
96
- end
97
- save_associations(obj)
98
- new_record ? insert(obj) : update(obj)
93
+ if obj.new?
94
+ obj.instance_variable_set("@id", increase_max_id_of(obj.class))
95
+ new_record = true
96
+ end
97
+ save_associations(obj)
98
+ new_record ? insert(obj) : update(obj)
99
99
  end
100
100
 
101
101
  def save_associations(obj)
102
- obj.class.associations.each do |assoc|
103
- assoc_type, assoc_name = assoc
104
- save_has_many_associations(obj, assoc_name) if assoc_type == :has_many
102
+ obj.class.associations.each do |assoc|
103
+ assoc_type, assoc_name = assoc
104
+ save_has_many_associations(obj, assoc_name) if assoc_type == :has_many
105
105
  end
106
106
  end
107
107
 
108
108
  def save_has_many_associations(obj, assoc_name)
109
- assoc_objs = obj.instance_variable_get("@#{assoc_name}_obj") || []
110
- assoc_ids = []
111
- assoc_objs.each do |assoc_obj|
112
- assoc_obj.instance_variable_set("@#{obj.class.to_s.underscore.sub(/.*\//, '')}", obj.id)
113
- assoc_obj.save
114
- assoc_ids << assoc_obj.id
115
- end
116
- obj.instance_variable_set("@#{assoc_name}", assoc_ids)
109
+ assoc_objs = obj.instance_variable_get("@#{assoc_name}_obj") || []
110
+ assoc_ids = []
111
+ assoc_objs.each do |assoc_obj|
112
+ assoc_obj.instance_variable_set("@#{obj.class.to_s.underscore.sub(/.*\//, '')}", obj.id)
113
+ assoc_obj.save
114
+ assoc_ids << assoc_obj.id
115
+ end
116
+ obj.instance_variable_set("@#{assoc_name}", assoc_ids)
117
117
  end
118
118
  end
119
119
  end
120
- end
120
+ end
@@ -24,7 +24,7 @@ module Liars
24
24
  @article = Article.find(id.to_i)
25
25
  render
26
26
  end
27
-
27
+
28
28
  route_of :create, '/create'
29
29
  def create
30
30
  Article.create(params[:article])
@@ -38,21 +38,21 @@ module Liars
38
38
  @article.save
39
39
  redirect_to "/show/#{id}"
40
40
  end
41
-
41
+
42
42
  route_of :style, '/styles.css'
43
43
  def style
44
44
  @headers["Content-Type"] = "text/css; charset=utf-8"
45
45
  @body = %[
46
- body {
47
- font-family: Utopia, Georga, serif;
48
- }
49
- h1 {
50
- background-color: #fef;
51
- margin: 0; padding: 10px;
52
- }
53
- div {
54
- padding: 10px;
55
- }
46
+ body {
47
+ font-family: Utopia, Georga, serif;
48
+ }
49
+ h1 {
50
+ background-color: #fef;
51
+ margin: 0; padding: 10px;
52
+ }
53
+ div {
54
+ padding: 10px;
55
+ }
56
56
  ]
57
57
  end
58
58
  end
@@ -60,33 +60,33 @@ module Liars
60
60
  class ArticleV < V
61
61
  def layout
62
62
  html do
63
- head do
64
- title 'Liars never tell lies!'
65
- link :rel => 'stylesheet', :type => 'text/css',
66
- :href => '/styles.css', :media => 'screen'
67
- end
68
- body do
69
- h1 { a 'Articles', :href => "http://www.google.cn" }
70
- div do
71
- yield
72
- end
73
- end
63
+ head do
64
+ title 'Liars never tell lies!'
65
+ link :rel => 'stylesheet', :type => 'text/css',
66
+ :href => '/styles.css', :media => 'screen'
67
+ end
68
+ body do
69
+ h1 { a 'Articles', :href => "/" }
70
+ div do
71
+ yield
72
+ end
73
+ end
74
74
  end
75
75
  end
76
-
76
+
77
77
  def index
78
78
  h1 'Articles'
79
79
  hr
80
80
  @articles.each do |ar|
81
- b ar.title
82
- p ar.content
83
- a 'show comments', :href=> "/show/#{ar.id}"
84
- hr
81
+ b ar.title
82
+ p ar.content
83
+ a 'show comments', :href=> "/show/#{ar.id}"
84
+ hr
85
85
  end
86
86
  form :action=>'/create', :method=>'Post' do
87
- input :type=>'text', :name=>'article[title]'; br
88
- textarea '', :name=>'article[content]'; br
89
- input :type=>'submit'
87
+ input :type=>'text', :name=>'article[title]'; br
88
+ textarea '', :name=>'article[content]'; br
89
+ input :type=>'submit'
90
90
  end
91
91
  end
92
92
 
@@ -99,14 +99,14 @@ module Liars
99
99
  h1 'Comments'
100
100
  hr
101
101
  @article.comments.each do |c|
102
- b c.title
103
- p c.content
102
+ b c.title
103
+ p c.content
104
104
  end
105
105
  hr
106
106
  form :action=> "/add_comment/#{@article.id}", :method=>'Post' do
107
- input :type=>'text', :name=>'comment[title]'; br
108
- textarea '', :name=>'comment[content]'; br
109
- input :type=>'submit'
107
+ input :type=>'text', :name=>'comment[title]'; br
108
+ textarea '', :name=>'comment[content]'; br
109
+ input :type=>'submit'
110
110
  end
111
111
  end
112
112
  end
@@ -187,4 +187,4 @@ module Liars
187
187
  # end
188
188
  # end
189
189
  # end
190
- end
190
+ end
@@ -21,69 +21,69 @@ module Liars
21
21
 
22
22
  class << self
23
23
  def inherited(child)
24
- DbEngine.all_models << child
24
+ DbEngine.all_models << child
25
25
  end
26
26
 
27
27
  def fields
28
- @fields ||= [:id]
28
+ @fields ||= [:id]
29
29
  end
30
30
 
31
31
  def associations
32
- (@associations ||= [])
32
+ (@associations ||= [])
33
33
  end
34
34
 
35
35
  def fields_and_associations
36
- fields + associations.collect {|x| x[1]}
36
+ fields + associations.collect {|x| x[1]}
37
37
  end
38
38
 
39
39
  def create(fields={})
40
- self.new(fields).save
40
+ self.new(fields).save
41
41
  end
42
42
 
43
43
  def find(ids)
44
- DbEngine.find(self, ids)
44
+ DbEngine.find(self, ids)
45
45
  end
46
46
 
47
47
  def has_field(name)
48
- attr_accessor name
49
- fields << name
48
+ attr_accessor name
49
+ fields << name
50
50
  end
51
51
 
52
52
  def has_many(name)
53
- class_name = name.singularize.camelize
54
- associations << [:has_many, name]
55
- class_eval <<-EOF
53
+ class_name = name.singularize.camelize
54
+ associations << [:has_many, name]
55
+ class_eval <<-EOF
56
56
  def #{name}
57
57
  @#{name} ||= []
58
58
  @#{name}_obj ||= DbEngine.find(#{class_name}, @#{name})
59
59
  end
60
-
60
+
61
61
  def #{name}=(value)
62
62
  @#{name}_obj = value
63
63
  end
64
- EOF
64
+ EOF
65
65
  end
66
66
 
67
67
  def belongs_to(name)
68
- class_name = name.camelize
69
- associations << [:belongs_to, name]
70
- class_eval <<-EOF
68
+ class_name = name.camelize
69
+ associations << [:belongs_to, name]
70
+ class_eval <<-EOF
71
71
  def #{name}
72
72
  @#{name}_obj ||= DbEngine.find(#{class_name}, @#{name})
73
73
  end
74
-
74
+
75
75
  def #{name}=(value)
76
76
  @#{name} = value.id
77
77
  @#{name}_obj = value
78
78
  end
79
- EOF
79
+ EOF
80
80
  end
81
81
  end
82
82
 
83
83
  def save
84
84
  DbEngine.save(self)
85
85
  end
86
-
86
+
87
87
  def new?
88
88
  @id == nil
89
89
  end
@@ -96,4 +96,4 @@ module Liars
96
96
  DbEngine.delete(self)
97
97
  end
98
98
  end
99
- end
99
+ end
@@ -7,17 +7,18 @@ module Liars
7
7
  super(server, klass)
8
8
  @klass = klass
9
9
  end
10
+
10
11
  # Handler for WEBrick requests (also aliased as do_POST).
11
12
  def service(req, resp)
12
13
  controller = @klass.run((req.body && StringIO.new(req.body)), req.meta_vars)
13
14
  resp.body = controller.body.to_s
14
15
  resp.status = controller.status
15
16
  controller.headers.each do |k, v|
16
- unless k =~ /^X-SENDFILE$/i
17
- [*v].each do |vi|
18
- resp[k] = vi
19
- end
20
- end
17
+ unless k =~ /^X-SENDFILE$/i
18
+ [*v].each do |vi|
19
+ resp[k] = vi
20
+ end
21
+ end
21
22
  end
22
23
  end
23
24
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - luonet
@@ -14,25 +14,20 @@ autorequire: liars
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-21 00:00:00 +08:00
17
+ date: 2010-04-06 00:00:00 +08:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
21
- description: !binary |
22
- 5pyA5bCP5YyW55qETVZD5qGG5p62
23
-
21
+ description: It's a very quick and dirty hack, just demonstrating some concepts. As its name said, Do not trust it. :-)
24
22
  email: luoxin.net@gmail.com
25
23
  executables:
26
24
  - liars
27
25
  extensions: []
28
26
 
29
- extra_rdoc_files:
30
- - README
31
- - CHANGELOG
27
+ extra_rdoc_files: []
28
+
32
29
  files:
33
- - CHANGELOG
34
- - README
35
- - Rakefile
30
+ - README.markdown
36
31
  - liars.rb
37
32
  - bin/liars
38
33
  - lib/server.rb
@@ -42,24 +37,13 @@ files:
42
37
  - lib/example.rb
43
38
  - lib/db.rb
44
39
  - lib/model.rb
45
- - extras/flipbook_rdoc.rb
46
40
  has_rdoc: true
47
41
  homepage: http://luoxin.net/
48
42
  licenses: []
49
43
 
50
44
  post_install_message:
51
- rdoc_options:
52
- - --quiet
53
- - --title
54
- - Camping, the Documentation
55
- - --opname
56
- - index.html
57
- - --line-numbers
58
- - --main
59
- - README
60
- - --inline-source
61
- - --exclude
62
- - ^(examples|extras)\/
45
+ rdoc_options: []
46
+
63
47
  require_paths:
64
48
  - .
65
49
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -82,8 +66,6 @@ rubyforge_project:
82
66
  rubygems_version: 1.3.6
83
67
  signing_key:
84
68
  specification_version: 3
85
- summary: !binary |
86
- 5pyA5bCP5YyW55qETVZD5qGG5p62
87
-
69
+ summary: tiny MVC web framework
88
70
  test_files: []
89
71
 
data/CHANGELOG DELETED
File without changes
data/README DELETED
File without changes
data/Rakefile DELETED
@@ -1,69 +0,0 @@
1
- require 'rake'
2
- require 'rake/clean'
3
- require 'rake/gempackagetask'
4
- require 'rake/rdoctask'
5
- require 'fileutils'
6
- include FileUtils
7
-
8
- NAME = "liars"
9
- VERS = "0.0.2"
10
- CLEAN.include ['**/.*.sw?', '*.gem', '.config']
11
- RDOC_OPTS = ['--quiet', '--title', "Camping, the Documentation",
12
- "--opname", "index.html",
13
- "--line-numbers",
14
- "--main", "README",
15
- "--inline-source"]
16
-
17
- # platform = if ENV['HOME'] then "POSIX" elsif ENV['APPDATA'] then "MSWIN" end
18
-
19
- desc "将liars gem打包"
20
- task :default => [:package]
21
- task :package => [:clean]
22
-
23
- task :doc => [:before_doc, :rdoc, :after_doc]
24
-
25
- Rake::RDocTask.new do |rdoc|
26
- rdoc.rdoc_dir = 'doc/rdoc'
27
- rdoc.options += RDOC_OPTS
28
- rdoc.template = "extras/flipbook_rdoc.rb"
29
- rdoc.main = "README"
30
- rdoc.title = "Liars文档"
31
- rdoc.rdoc_files.add ['README', 'CHANGELOG','lib/*.rb']
32
- end
33
-
34
- spec =
35
- Gem::Specification.new do |s|
36
- s.name = NAME
37
- s.version = VERS
38
- s.platform = Gem::Platform::RUBY
39
- s.has_rdoc = true
40
- s.extra_rdoc_files = ["README", "CHANGELOG"]
41
- s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)\/']
42
- s.summary = "最小化的MVC框架"
43
- s.description = s.summary
44
- s.author = "luonet"
45
- s.email = 'luoxin.net@gmail.com'
46
- s.homepage = 'http://luoxin.net/'
47
- s.executables = ['liars']
48
-
49
- s.files = %w(CHANGELOG README Rakefile liars.rb) +
50
- Dir.glob("{bin,doc,test,lib,extras}/**/*")
51
-
52
- s.require_path = "."
53
- s.autorequire = 'liars'
54
- s.bindir = "bin"
55
- end
56
-
57
- Rake::GemPackageTask.new(spec) do |p|
58
- p.need_tar = ENV['APPDATA'].nil?
59
- p.gem_spec = spec
60
- end
61
-
62
- task :install do
63
- sh %{rake package}
64
- sh %{sudo gem install pkg/#{NAME}-#{VERS}}
65
- end
66
-
67
- task :uninstall => [:clean] do
68
- sh %{sudo gem uninstall #{NAME}}
69
- end
@@ -1,491 +0,0 @@
1
- CAMPING_EXTRAS_DIR = File.expand_path(File.dirname(__FILE__))
2
-
3
- module Generators
4
- class HTMLGenerator
5
- def generate_html
6
- @files_and_classes = {
7
- 'allfiles' => gen_into_index(@files),
8
- 'allclasses' => gen_into_index(@classes),
9
- "initial_page" => main_url,
10
- 'realtitle' => CGI.escapeHTML(@options.title),
11
- 'charset' => @options.charset
12
- }
13
-
14
- # the individual descriptions for files and classes
15
- gen_into(@files)
16
- gen_into(@classes)
17
- gen_main_index
18
-
19
- # this method is defined in the template file
20
- write_extra_pages if defined? write_extra_pages
21
- end
22
-
23
- def gen_into(list)
24
- hsh = @files_and_classes.dup
25
- list.each do |item|
26
- if item.document_self
27
- op_file = item.path
28
- hsh['root'] = item.path.split("/").map { ".." }[1..-1].join("/")
29
- item.instance_variable_set("@values", hsh)
30
- File.makedirs(File.dirname(op_file))
31
- File.open(op_file, "w") { |file| item.write_on(file) }
32
- end
33
- end
34
- end
35
-
36
- def gen_into_index(list)
37
- res = []
38
- list.each do |item|
39
- hsh = item.value_hash
40
- hsh['href'] = item.path
41
- hsh['name'] = item.index_name
42
- res << hsh
43
- end
44
- res
45
- end
46
-
47
- def gen_main_index
48
- template = TemplatePage.new(RDoc::Page::INDEX)
49
- File.open("index.html", "w") do |f|
50
- values = @files_and_classes.dup
51
- if @options.inline_source
52
- values['inline_source'] = true
53
- end
54
- template.write_html_on(f, values)
55
- end
56
- ['Camping.gif', 'permalink.gif'].each do |img|
57
- ipath = File.join(CAMPING_EXTRAS_DIR, img)
58
- File.copy(ipath, img)
59
- end
60
- end
61
- end
62
- end
63
-
64
-
65
- module RDoc
66
- module Page
67
- ######################################################################
68
- #
69
- # The following is used for the -1 option
70
- #
71
-
72
- FONTS = "verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif"
73
-
74
- STYLE = %{
75
- body, th, td {
76
- font: normal 14px verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif;
77
- line-height: 160%;
78
- padding: 0; margin: 0;
79
- margin-bottom: 30px;
80
- /* background-color: #402; */
81
- background-color: #694;
82
- }
83
- h1, h2, h3, h4 {
84
- font-family: Utopia, Georgia, serif;
85
- font-weight: bold;
86
- letter-spacing: -0.018em;
87
- }
88
- h1 { font-size: 24px; margin: .15em 1em 0 0 }
89
- h2 { font-size: 24px }
90
- h3 { font-size: 19px }
91
- h4 { font-size: 17px; font-weight: normal; }
92
- h4.ruled { border-bottom: solid 1px #CC9; }
93
- h2.ruled { padding-top: 35px; border-top: solid 1px #AA5; }
94
-
95
- /* Link styles */
96
- :link, :visited {
97
- color: #00b;
98
- }
99
- :link:hover, :visited:hover {
100
- background-color: #eee;
101
- color: #B22;
102
- }
103
- #fullpage {
104
- width: 720px;
105
- margin: 0 auto;
106
- }
107
- .page_shade, .page {
108
- padding: 0px 5px 5px 0px;
109
- background-color: #fcfcf9;
110
- border: solid 1px #983;
111
- }
112
- .page {
113
- margin-left: -5px;
114
- margin-top: -5px;
115
- padding: 20px 35px;
116
- }
117
- .page .header {
118
- float: right;
119
- color: #777;
120
- font-size: 10px;
121
- }
122
- .page h1, .page h2, .page h3 {
123
- clear: both;
124
- text-align: center;
125
- }
126
- #pager {
127
- padding: 10px 4px;
128
- color: white;
129
- font-size: 11px;
130
- }
131
- #pager :link, #pager :visited {
132
- color: #bfb;
133
- padding: 0px 5px;
134
- }
135
- #pager :link:hover, #pager :visited:hover {
136
- background-color: #262;
137
- color: white;
138
- }
139
- #logo { float: left; }
140
- #menu { background-color: #dfa; padding: 4px 12px; margin: 0; }
141
- #menu h3 { padding: 0; margin: 0; }
142
- #menu #links { float: right; }
143
- pre { font-weight: bold; color: #730; }
144
- tt { color: #703; font-size: 12pt; }
145
- .dyn-source { background-color: #775915; padding: 4px 8px; margin: 0; display: none; }
146
- .dyn-source pre { color: #DDDDDD; font-size: 8pt; }
147
- .source-link { text-align: right; font-size: 8pt; }
148
- .ruby-comment { color: green; font-style: italic }
149
- .ruby-constant { color: #CCDDFF; font-weight: bold; }
150
- .ruby-identifier { color: #CCCCCC; }
151
- .ruby-ivar { color: #BBCCFF; }
152
- .ruby-keyword { color: #EEEEFF; font-weight: bold }
153
- .ruby-node { color: #FFFFFF; }
154
- .ruby-operator { color: #CCCCCC; }
155
- .ruby-regexp { color: #DDFFDD; }
156
- .ruby-value { color: #FFAAAA; font-style: italic }
157
- .kw { color: #DDDDFF; font-weight: bold }
158
- .cmt { color: #CCFFCC; font-style: italic }
159
- .str { color: #EECCCC; font-style: italic }
160
- .re { color: #EECCCC; }
161
- }
162
-
163
- CONTENTS_XML = %{
164
- IF:description
165
- %description%
166
- ENDIF:description
167
-
168
- IF:requires
169
- <h4>Requires:</h4>
170
- <ul>
171
- START:requires
172
- IF:aref
173
- <li><a href="%aref%">%name%</a></li>
174
- ENDIF:aref
175
- IFNOT:aref
176
- <li>%name%</li>
177
- ENDIF:aref
178
- END:requires
179
- </ul>
180
- ENDIF:requires
181
-
182
- IF:attributes
183
- <h4>Attributes</h4>
184
- <table>
185
- START:attributes
186
- <tr><td>%name%</td><td>%rw%</td><td>%a_desc%</td></tr>
187
- END:attributes
188
- </table>
189
- ENDIF:attributes
190
-
191
- IF:includes
192
- <h4>Includes</h4>
193
- <ul>
194
- START:includes
195
- IF:aref
196
- <li><a href="%aref%">%name%</a></li>
197
- ENDIF:aref
198
- IFNOT:aref
199
- <li>%name%</li>
200
- ENDIF:aref
201
- END:includes
202
- </ul>
203
- ENDIF:includes
204
-
205
- START:sections
206
- IF:method_list
207
- <h2 class="ruled">Methods</h2>
208
- START:method_list
209
- IF:methods
210
- START:methods
211
- <h4 class="ruled">%type% %category% method:
212
- IF:callseq
213
- <strong><a name="%aref%">%callseq%</a></strong> <a href="#%aref%"><img src="%root%/permalink.gif" border="0" title="Permalink to %callseq%" /></a>
214
- ENDIF:callseq
215
- IFNOT:callseq
216
- <strong><a name="%aref%">%name%%params%</a></strong> <a href="#%aref%"><img src="%root%/permalink.gif" border="0" title="Permalink to %type% %category% method: %name%" /></a></h4>
217
- ENDIF:callseq
218
-
219
- IF:m_desc
220
- %m_desc%
221
- ENDIF:m_desc
222
-
223
- IF:sourcecode
224
- <div class="sourcecode">
225
- <p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
226
- <div id="%aref%_source" class="dyn-source">
227
- <pre>
228
- %sourcecode%
229
- </pre>
230
- </div>
231
- </div>
232
- ENDIF:sourcecode
233
- END:methods
234
- ENDIF:methods
235
- END:method_list
236
- ENDIF:method_list
237
- END:sections
238
- }
239
-
240
- ############################################################################
241
-
242
-
243
- BODY = %{
244
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
245
- <html>
246
- <head>
247
- <title>
248
- IF:title
249
- %realtitle% &raquo; %title%
250
- ENDIF:title
251
- IFNOT:title
252
- %realtitle%
253
- ENDIF:title
254
- </title>
255
- <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
256
- <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
257
- <script language="JavaScript" type="text/javascript">
258
- // <![CDATA[
259
-
260
- function toggleSource( id )
261
- {
262
- var elem
263
- var link
264
-
265
- if( document.getElementById )
266
- {
267
- elem = document.getElementById( id )
268
- link = document.getElementById( "l_" + id )
269
- }
270
- else if ( document.all )
271
- {
272
- elem = eval( "document.all." + id )
273
- link = eval( "document.all.l_" + id )
274
- }
275
- else
276
- return false;
277
-
278
- if( elem.style.display == "block" )
279
- {
280
- elem.style.display = "none"
281
- link.innerHTML = "show source"
282
- }
283
- else
284
- {
285
- elem.style.display = "block"
286
- link.innerHTML = "hide source"
287
- }
288
- }
289
-
290
- function openCode( url )
291
- {
292
- window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
293
- }
294
- // ]]>
295
- </script>
296
- </head>
297
- <body>
298
- <div id="menu">
299
- <div id="links">
300
- <a href="http://redhanded.hobix.com/bits/campingAMicroframework.html">backstory</a> |
301
- <a href="http://code.whytheluckystiff.net/camping/">wiki</a> |
302
- <a href="http://code.whytheluckystiff.net/camping/newticket">bugs</a> |
303
- <a href="http://code.whytheluckystiff.net/svn/camping/">svn</a>
304
- </div>
305
- <h3 class="title">%title%</h3>
306
- </div>
307
- <div id="fullpage">
308
- <div id="logo"><img src="%root%/Camping.gif" /></div>
309
- <div id="pager">
310
- <strong>Files:</strong>
311
- START:allfiles
312
- <a href="%root%/%href%" value="%title%">%name%</a>
313
- END:allfiles
314
- IF:allclasses
315
- |
316
- <strong>classes:</strong>
317
- START:allclasses
318
- <a href="%root%/%href%" title="%title%">%name%</a>
319
- END:allclasses
320
- ENDIF:allclasses
321
- </ul>
322
- </div>
323
-
324
- !INCLUDE!
325
-
326
- </div>
327
- </body>
328
- </html>
329
- }
330
-
331
- ###############################################################################
332
-
333
- FILE_PAGE = <<_FILE_PAGE_
334
- <div id="%full_path%" class="page_shade">
335
- <div class="page">
336
- <div class="header">
337
- <div class="path">%full_path% / %dtm_modified%</div>
338
- </div>
339
- #{CONTENTS_XML}
340
- </div>
341
- </div>
342
- _FILE_PAGE_
343
-
344
- ###################################################################
345
-
346
- CLASS_PAGE = %{
347
- <div id="%full_name%" class="page_shade">
348
- <div class="page">
349
- IF:parent
350
- <h3>%classmod% %full_name% &lt; HREF:par_url:parent:</h3>
351
- ENDIF:parent
352
- IFNOT:parent
353
- <h3>%classmod% %full_name%</h3>
354
- ENDIF:parent
355
-
356
- IF:infiles
357
- (in files
358
- START:infiles
359
- HREF:full_path_url:full_path:
360
- END:infiles
361
- )
362
- ENDIF:infiles
363
- } + CONTENTS_XML + %{
364
- </div>
365
- </div>
366
- }
367
-
368
- ###################################################################
369
-
370
- METHOD_LIST = %{
371
- IF:includes
372
- <div class="tablesubsubtitle">Included modules</div><br>
373
- <div class="name-list">
374
- START:includes
375
- <span class="method-name">HREF:aref:name:</span>
376
- END:includes
377
- </div>
378
- ENDIF:includes
379
-
380
- IF:method_list
381
- START:method_list
382
- IF:methods
383
- <table cellpadding=5 width="100%">
384
- <tr><td class="tablesubtitle">%type% %category% methods</td></tr>
385
- </table>
386
- START:methods
387
- <table width="100%" cellspacing = 0 cellpadding=5 border=0>
388
- <tr><td class="methodtitle">
389
- <a name="%aref%">
390
- IF:callseq
391
- <b>%callseq%</b>
392
- ENDIF:callseq
393
- IFNOT:callseq
394
- <b>%name%</b>%params%
395
- ENDIF:callseq
396
- IF:codeurl
397
- <a href="%codeurl%" target="source" class="srclink">src</a>
398
- ENDIF:codeurl
399
- </a></td></tr>
400
- </table>
401
- IF:m_desc
402
- <div class="description">
403
- %m_desc%
404
- </div>
405
- ENDIF:m_desc
406
- IF:aka
407
- <div class="aka">
408
- This method is also aliased as
409
- START:aka
410
- <a href="%aref%">%name%</a>
411
- END:aka
412
- </div>
413
- ENDIF:aka
414
- IF:sourcecode
415
- <div class="sourcecode">
416
- <p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
417
- <div id="%aref%_source" class="dyn-source">
418
- <pre>
419
- %sourcecode%
420
- </pre>
421
- </div>
422
- </div>
423
- ENDIF:sourcecode
424
- END:methods
425
- ENDIF:methods
426
- END:method_list
427
- ENDIF:method_list
428
- }
429
-
430
-
431
- ########################## Index ################################
432
-
433
- FR_INDEX_BODY = %{
434
- !INCLUDE!
435
- }
436
-
437
- FILE_INDEX = %{
438
- <html>
439
- <head>
440
- <meta http-equiv="Content-Type" content="text/html; charset=%charset%">
441
- <style>
442
- <!--
443
- body {
444
- background-color: #ddddff;
445
- font-family: #{FONTS};
446
- font-size: 11px;
447
- font-style: normal;
448
- line-height: 14px;
449
- color: #000040;
450
- }
451
- div.banner {
452
- background: #0000aa;
453
- color: white;
454
- padding: 1;
455
- margin: 0;
456
- font-size: 90%;
457
- font-weight: bold;
458
- line-height: 1.1;
459
- text-align: center;
460
- width: 100%;
461
- }
462
-
463
- -->
464
- </style>
465
- <base target="docwin">
466
- </head>
467
- <body>
468
- <div class="banner">%list_title%</div>
469
- START:entries
470
- <a href="%href%">%name%</a><br>
471
- END:entries
472
- </body></html>
473
- }
474
-
475
- CLASS_INDEX = FILE_INDEX
476
- METHOD_INDEX = FILE_INDEX
477
-
478
- INDEX = %{
479
- <HTML>
480
- <HEAD>
481
- <META HTTP-EQUIV="refresh" content="0;URL=%initial_page%">
482
- <TITLE>%realtitle%</TITLE>
483
- </HEAD>
484
- <BODY>
485
- Click <a href="%initial_page%">here</a> to open the Camping docs.
486
- </BODY>
487
- </HTML>
488
- }
489
-
490
- end
491
- end