ground 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NDU5YmZhOTU0YTdjMzIxOGNlNWY0MDliZDJiZTliNTE0YTQ5NDdkMA==
4
+ MjIwZmFhYTk5YWI3NTk3ZGMyMjExNTczMzAyOTJhZWE5MjVjZjNjYg==
5
5
  data.tar.gz: !binary |-
6
- MzczMGFkMGZmYTY5YzgxYWNmOTU2M2E2MzMxYTgzMmUzNDBiZjc5NQ==
6
+ ZWI0NzM1OTY3YjFhN2NiNmMyMzRlOTk3NzljM2YwYmM3MjY3NjJiZg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NzgwZTg4YjE0ZDg1ODhhMzNkNGEzYzcyNDZmOGVhOTQwNjI4MmRiMTdkMDg1
10
- MDUwNDk0ZGNmMWZhZTNiYTUzODVhYmI4OWNlMTE1ZjkxZmZkNTU5ODMyMzUw
11
- NTUyODg5ZjMyMzM4MTc2YjRhMDdiOGRjNTU4MTUwNGQ5YTIwZTg=
9
+ ZDIzODkyN2ZjMmJiNTMzZTEzMjI2MDVmYWQ1MTVlODhkOTY3OTYxNzliMTUz
10
+ NTJlMDBkNGQzNmIyYmU3NGQ4YmQzZjg0MjA5MGI4YzNmNDhiOWQ5YTVjMTc3
11
+ NzQ1MjQyM2Y0ZmY3MjVkMGJjYmJhMmVkYzFhMDM4NWExMTQ5ODE=
12
12
  data.tar.gz: !binary |-
13
- ZWQwZWYyZDBiN2RmZjBiNWMyZmE3ODc2NDQ3NmNkNGNkNDMwZGUwMzc1NWVh
14
- YmM4MmFlMWYwMTJmYWYyMmJiMDgxNDBiMGQ5OWU0MjZjZDlkNzNiNTUyMmYy
15
- NDNiMzVhZTk3ODgxNWQ2MmVlNWJmMGE2MGViNjg2NDNhNjIzOTE=
13
+ MWQ0MmRkNTQ0NGJjNmViY2NmNmQ5YWFiZTNmYWE5YzU0OWIzMmQ5ZGQ0ZDg1
14
+ MjM1NjI0Yzk4ZTk1Y2YyZWVjNGNmNTQ0NGE1NjY0MWFjNGUyNmMzNmRiODNj
15
+ NzM2M2Q1ZGUwM2Q2NjZiMWM3NTJkNzY3MDZiMzdlNWQ0N2QyMzY=
@@ -0,0 +1,53 @@
1
+ require 'dun'
2
+ require 'rack'
3
+ require 'logger'
4
+ require 'ground/activity'
5
+ require 'ground/mime_type'
6
+ require 'ground/protocol/render'
7
+ require 'ground/protocol/render/template'
8
+ require 'ground/activity/ridge'
9
+ require 'ground/protocol/verb'
10
+ require 'ground/protocol/helper'
11
+ require 'ground/activity/log'
12
+ require 'ground/activity/locate'
13
+ require 'ground/activity/state'
14
+ require 'ground/activity/validate'
15
+ require 'ground/rack/url_suffix'
16
+ require 'ground/rack/base_rack'
17
+ require 'ground/activity/hash_with_double_access'
18
+ require 'ground/activity/create_application'
19
+
20
+
21
+ module Ground
22
+ extend Protocol::Verb
23
+ extend Protocol::Helper
24
+
25
+ class << self
26
+
27
+ MetaG = self
28
+
29
+ def set(attr, value)
30
+ MetaG.class_eval { attr_reader attr }
31
+ instance_variable_set "@#{attr}", value
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ if not Kernel.method_defined?('Ground')
39
+ Kernel.class_eval do
40
+ def Ground(app_name = nil, &p)
41
+ if app_name
42
+ Ground::CreateApplication(name: app_name, &p)
43
+ else
44
+ Ground.instance_eval &p
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Ground do
51
+ set :logger, ::Logger.new(STDOUT)
52
+ end
53
+
@@ -0,0 +1,3 @@
1
+ module Ground
2
+ Activity = ::Dun::Activity
3
+ end
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Ground
3
+
4
+ class CreateApplication < Activity
5
+ data_reader :name
6
+
7
+ def initialize(data)
8
+ super
9
+ @middlewares = []
10
+ end
11
+
12
+ def call(&p)
13
+ app = Class.new(Ground::BaseRack)
14
+ instance_eval &p
15
+ app_with_middlewares = pack_middlewares_to_app app
16
+ end
17
+
18
+ private
19
+
20
+ def use(middleware, *args, &p)
21
+ @middlewares << lambda {|app| middleware.new(app, *args, &p)}
22
+ end
23
+
24
+ def pack_middlewares_to_app(app)
25
+ app_with_middlewares = app.new
26
+ @middlewares.reverse.each {|middleware|
27
+ app_with_middlewares = middleware.call(app_with_middlewares)
28
+ }
29
+ app_with_middlewares
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,28 @@
1
+ class HashWithDoubleAccess < Ground::Activity
2
+
3
+ def call
4
+ str_h = access_with(data, :to_s)
5
+ sym_h = access_with(data, :to_sym)
6
+ sym_h.merge str_h
7
+ end
8
+
9
+
10
+ private
11
+
12
+ def access_with(d, m)
13
+ tmp_h = {}
14
+ d.each {|k, v|
15
+ if v.is_a? Hash
16
+ tmp_h[k.send(m)] = access_with(v, m)
17
+ elsif v.is_a? Array
18
+ v_dup = v.dup
19
+ v_dup.each_with_index {|item, index| v_dup[index] = access_with(item, m) if item.is_a? Hash}
20
+ tmp_h[k.send(m)] = v_dup
21
+ else
22
+ tmp_h[k.send(m)] = v
23
+ end
24
+ }
25
+ tmp_h
26
+ end
27
+
28
+ end
@@ -0,0 +1,41 @@
1
+ module Ground
2
+
3
+ class Locate < Activity
4
+ data_reader :verb, :path
5
+
6
+ def initialize(data)
7
+ super
8
+ @verb = verb.upcase
9
+ end
10
+
11
+ def call
12
+ path_segs = split_to_segs(path)
13
+
14
+ length_match_routes = Ridge.routes[verb].select {|route|
15
+ route_segs = split_to_segs(route[0])
16
+ route_segs.size == path_segs.size
17
+ }
18
+
19
+ length_match_routes.detect {|route|
20
+ match = true
21
+ route_segs = split_to_segs(route[0])
22
+ route_segs.each_with_index {|route_seg, index|
23
+ match = (path_segs[index] == route_seg) if not route_seg =~ /^:\w+/
24
+ break if not match
25
+ }
26
+ match
27
+ }
28
+
29
+ end
30
+
31
+ private
32
+
33
+ def split_to_segs(path)
34
+ segs = path.split('/')
35
+ segs[0] = '/'
36
+ segs
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,28 @@
1
+ module Ground
2
+ class Log < Activity
3
+ set :format, %{(%0.4fs) %s %s %s %s %s %s\n}
4
+
5
+ data_reader :time
6
+ data_reader :request_method, :path_info
7
+ data_reader :state
8
+ data_reader :response
9
+ data_reader :params
10
+
11
+ def call
12
+ logger.info format % [time,
13
+ request_method,
14
+ path_info,
15
+ state,
16
+ response[0],
17
+ response[1],
18
+ "Parameters: #{params.select{|k, _| k.is_a? Symbol}}"]
19
+ end
20
+
21
+ private
22
+
23
+ def logger
24
+ Ground.logger
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,42 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Ground
3
+
4
+ class Ridge < Activity
5
+
6
+ data_reader :path, :verb, :state
7
+
8
+ class << self
9
+
10
+ attr_reader :routes, :states
11
+
12
+ # 路由节点的结构 [path, state]
13
+ def route(verb, path, state)
14
+
15
+ @routes ||= {'GET' => [], 'POST' => []}
16
+ @states ||= []
17
+
18
+ @routes[verb] << [path, state]
19
+ @states << state if not @states.include?(state)
20
+
21
+ end
22
+
23
+ end
24
+
25
+ def initialize(data)
26
+ super
27
+ @verb = verb.upcase
28
+ end
29
+
30
+ def call
31
+ route(state)
32
+ end
33
+
34
+ private
35
+
36
+ def route(state)
37
+ self.class.route(verb, path, state)
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,52 @@
1
+ module Ground
2
+
3
+ class State < Activity
4
+
5
+ include Ground::Protocol::Render
6
+ include Ground::Protocol::Render::Template
7
+
8
+ data_reader :request, :params
9
+
10
+ class << self
11
+
12
+ def path(*args)
13
+ paths = []
14
+ route = detect_route('GET') || detect_route('POST')
15
+
16
+ route[0].split('/').each_with_index {|route_seg, index|
17
+ paths[index] = (route_seg =~ /^:\w+/ ? args.shift : route_seg)
18
+ }
19
+ paths << '/' if paths.size == 0
20
+ paths.join('/')
21
+
22
+ end
23
+
24
+ def detect_route(verb)
25
+ Ridge.routes[verb.to_s.upcase].detect {|route| route[1] == self}
26
+ end
27
+
28
+ end
29
+
30
+
31
+ private
32
+
33
+ def response
34
+ @response ||= ::Rack::Response.new
35
+ end
36
+
37
+ def session
38
+ @session ||= request.session
39
+ end
40
+
41
+ # check Ground::MimeType for all mime type abb defined in ground
42
+ def request_accept?(mime_type_abb)
43
+ Ground::MimeType[request_accepts.first] == mime_type_abb
44
+ end
45
+
46
+ def request_accepts
47
+ @request_accepts ||= request.env['HTTP_ACCEPT'].split(', ')
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,37 @@
1
+ module Ground
2
+ class Validate < Activity
3
+
4
+ attr_reader :errors, :validations
5
+
6
+ def initialize(data)
7
+ super
8
+ @errors = {}
9
+ @validations = []
10
+ end
11
+
12
+ def call
13
+ execute_validations
14
+ end
15
+
16
+ private
17
+
18
+ def validates(attr, error_msg, &p)
19
+ validation = validations.detect {|validation|
20
+ validation[0] == attr and validation[1] == error_msg
21
+ } || [attr, error_msg, p]
22
+ validations << validation
23
+ end
24
+
25
+ def execute_validations
26
+ validations.each {|validation|
27
+ attr, error_msg, p = validation
28
+ if !p.call
29
+ errors[attr] ||= []
30
+ errors[attr] << error_msg if !errors[attr].include?(error_msg)
31
+ end
32
+ }
33
+ errors
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ module Ground
2
+ MimeType = {
3
+ "*/*" => :all,
4
+ "text/plain" => :text,
5
+ "text/html" => :html,
6
+ "application/xhtml+xml" => :html,
7
+ "text/javascript" => :js,
8
+ "application/javascript" => :js,
9
+ "application/x-javascript" => :js,
10
+ "text/calendar" => :ics,
11
+ "text/csv" => :csv,
12
+ "application/xml" => :xml,
13
+ "text/xml" => :xml,
14
+ "application/x-xml" => :xml,
15
+ "text/yaml" => :yaml,
16
+ "application/x-yaml" => :yaml,
17
+ "application/rss+xml" => :rss,
18
+ "application/atom+xml" => :atom,
19
+ "application/json" => :json,
20
+ "text/x-json" => :json,
21
+ "text/markdown" => :md
22
+ }
23
+ end
@@ -0,0 +1,19 @@
1
+ module Ground::Protocol
2
+
3
+ module Helper
4
+
5
+ Ridge = Ground::Ridge
6
+
7
+ def help(*args, &p)
8
+ if args.first == :all_states
9
+ help Ground::State, &p
10
+ else
11
+ args.each {|obj|
12
+ obj.class_eval &p if block_given?
13
+ }
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,59 @@
1
+ module Ground::Protocol
2
+ module Render
3
+
4
+ include ::Rack::Utils
5
+
6
+ def json(content, status = 200)
7
+ response_with(content, status, 'application/json; charset=UTF-8')
8
+ end
9
+
10
+ def xml(content, status = 200)
11
+ response_with(content, status, 'application/xml; charset=UTF-8')
12
+ end
13
+
14
+ def html(content, status = 200)
15
+ response_with(content, status, 'text/html; charset=UTF-8')
16
+ end
17
+
18
+ def text(content, status = 200)
19
+ response_with(content, status, 'text/plain; charset=UTF-8')
20
+ end
21
+
22
+ def non_found(content)
23
+ response_as 404, content
24
+ end
25
+
26
+ def forbid(content = nil)
27
+ response_as 403, content
28
+ end
29
+
30
+ def not_accept(content = nil)
31
+ response_as 406, content
32
+ end
33
+
34
+ def unauthorized(content = nil)
35
+ response_as 401, content
36
+ end
37
+
38
+ def redirect(target, status = 302)
39
+ response.status = status
40
+ response['Location'] = target
41
+ response.finish
42
+ end
43
+
44
+ private
45
+
46
+ def response_as(status, content=nil)
47
+ content ||= HTTP_STATUS_CODES[status]
48
+ text content, status
49
+ end
50
+
51
+ def response_with(content, status, content_type)
52
+ response['Content-Type'] = content_type
53
+ response.status = status
54
+ response.write(content)
55
+ response.finish
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,26 @@
1
+ module Ground::Protocol
2
+ module Render
3
+ module Template
4
+
5
+ def haml(path, &p)
6
+ template = Tilt::HamlTemplate.new(File.join(Ground.views, "#{path}.haml"))
7
+ template.render self, &p
8
+ end
9
+
10
+ def slim(path, &p)
11
+ template = Slim::Template.new(File.join(Ground.views, "#{path}.slim"))
12
+ template.render self, &p
13
+ end
14
+
15
+ def erb(file, &p)
16
+ template = ERB.new(File.read(File.join(Ground.root, file)))
17
+ template.result(binding)
18
+ end
19
+
20
+ def plain(file, &p)
21
+ File.read(File.join(Ground.root, file))
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ module Ground::Protocol
2
+ module Verb
3
+
4
+ def get(path, state)
5
+ ridge path: path, verb: 'get', state: state
6
+ end
7
+
8
+ def post(path, state)
9
+ ridge path: path, verb: 'post', state: state
10
+ end
11
+
12
+ def ridge(data)
13
+ Ground::Ridge data
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ module Ground
2
+ class BaseRack
3
+
4
+ attr_reader :env
5
+ attr_reader :request
6
+
7
+ def call(env)
8
+ start_time = Time.now
9
+ set_request Rack::Request.new(env)
10
+
11
+ route, state = Ground::Locate(verb: request_method, path: path_info)
12
+ return non_exist_route if state.nil?
13
+
14
+ params = get_params route
15
+ response = state << {request: request, params: params}
16
+ time = Time.now - start_time
17
+ Ground::Log({
18
+ time: time,
19
+ request_method: request_method,
20
+ path_info: request.env['REQUEST_PATH'],
21
+ state: state,
22
+ response: response,
23
+ params: params
24
+ })
25
+
26
+ response
27
+ end
28
+
29
+ private
30
+
31
+ def set_request request
32
+ @request = request
33
+ end
34
+
35
+ def request_method
36
+ request.request_method
37
+ end
38
+
39
+ def path_info
40
+ request.path_info
41
+ end
42
+
43
+ def get_params(route)
44
+ p = {}
45
+ path_segs = request.path_info.split('/')
46
+ route.split('/').each_with_index {|route_seg, index|
47
+ p[route_seg.sub(':', '')] = path_segs[index] if route_seg =~ /^:\w+/
48
+ }
49
+ HashWithDoubleAccess p.merge(request.params)
50
+ end
51
+
52
+ def non_exist_route
53
+ Rack::Response.new(["Non Exist Route: #{request_method} #{path_info}"], 500)
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,42 @@
1
+ module Ground
2
+
3
+ # When request's path contains a suffix like json, xml etc,
4
+ # it will git rid of the suffix and set the accept header
5
+ # by the suffix
6
+ #
7
+ # Example:
8
+ # get '/book/:id.json'
9
+ #
10
+ # the request path '/book/2.json' will become '/book/2', and
11
+ # the request accept header will be added a 'application/json'
12
+ # mime type
13
+ class UrlSuffix
14
+
15
+ def initialize(app)
16
+ @app = app
17
+ end
18
+
19
+ def call(env)
20
+ suffix = /\.(\w+)$/
21
+ if env['PATH_INFO'].match(suffix)
22
+ accept_type = suffix_to_accept_type $1
23
+ if accept_type
24
+ env['HTTP_ACCEPT'] = "#{accept_type}, #{env['HTTP_ACCEPT']}"
25
+ env['PATH_INFO'] = env['PATH_INFO'].sub(suffix, '')
26
+ end
27
+ end
28
+
29
+ @app.call(env)
30
+
31
+ end
32
+
33
+ private
34
+
35
+ def suffix_to_accept_type(suffix)
36
+ accept = Ground::MimeType.detect {|_, v| v == suffix.to_sym}
37
+ accept[0] if accept
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,13 @@
1
+ require 'test_helper'
2
+
3
+ Ground do
4
+ set :env, (ENV['RACK_ENV'] || :development).to_sym
5
+ end
6
+
7
+ class GroundSetTest < Test::Unit::TestCase
8
+
9
+ def test_set_attribute
10
+ assert_equal Ground.env, :development
11
+ end
12
+
13
+ end
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'test_helper'
3
+
4
+ class HashWithDoubleAccessTest < Test::Unit::TestCase
5
+
6
+ def test_double_access
7
+ h = {:a => 1, 'b' => 2, 'c' => {'d' => 4, :e => 5}, 'g' => [1,2,3], 'h' => [{'a' => 1, 'cc' => [{'b' => 2}, {'c' => 3}]}, {'b' => 5}]}
8
+
9
+ hd = HashWithDoubleAccess h
10
+
11
+ assert_equal hd[:a], 1
12
+ assert_equal hd['a'], 1
13
+ assert_equal hd['c']['d'], 4
14
+ assert_equal hd[:c][:d], 4
15
+ assert_equal hd['c']['e'], 5
16
+ assert_equal hd[:c][:e], 5
17
+
18
+ assert_equal hd[:c]['d'], nil
19
+ assert_equal hd[:c]['e'], nil
20
+ assert_equal hd['c'][:e], nil
21
+ assert_equal hd['c'][:d], nil
22
+
23
+ assert_equal hd[:h].size, 2
24
+ assert_equal hd[:h][0][:a], 1
25
+ assert_equal hd[:h][1][:b], 5
26
+ assert_equal hd['h'][0][:a], nil
27
+ assert_equal hd['h'][1][:b], nil
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+ require 'routes'
3
+
4
+ class LocateTest < Test::Unit::TestCase
5
+
6
+ def test_locate
7
+ location = Ground::Locate(verb: 'get', path: '/')
8
+ assert_equal location, ['/', SiteIndex]
9
+
10
+ location = Ground::Locate(verb: 'get', path: '/books')
11
+ assert_equal location, ['/books', BooksIndex]
12
+
13
+ location = Ground::Locate(verb: 'get', path: '/book/2')
14
+ assert_equal location, ['/book/:id', BookShow]
15
+
16
+ location = Ground::Locate(verb: 'post', path: '/book/3/comments')
17
+ assert_equal location, ['/book/:id/comments', BookComments]
18
+
19
+ location = Ground::Locate(verb: 'get', path: '/jim/notes')
20
+ assert_equal location, ['/:username/notes', UserNotes]
21
+ end
22
+
23
+ end
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'test_helper'
3
+ require 'routes'
4
+
5
+ class RidgeTest < Test::Unit::TestCase
6
+
7
+ def test_state_path
8
+ assert_equal SiteIndex.path, '/'
9
+ assert_equal BookShow.path(1), '/book/1'
10
+ assert_equal BooksIndex.path, '/books'
11
+ assert_equal BookComments.path(1), '/book/1/comments'
12
+ assert_equal UserNotes.path('jim'), '/jim/notes'
13
+ end
14
+
15
+ end
@@ -0,0 +1,13 @@
1
+ SiteIndex = Class.new(Ground::State)
2
+ BooksIndex = Class.new(Ground::State)
3
+ BookShow = Class.new(Ground::State)
4
+ BookComments = Class.new(Ground::State)
5
+ UserNotes = Class.new(Ground::State)
6
+
7
+ Ground::Ridge(verb: 'get', path: '/', state: SiteIndex)
8
+ Ground::Ridge(verb: 'get', path: '/book/:id', state: BookShow)
9
+ Ground::Ridge(verb: 'get', path: '/books', state: BooksIndex)
10
+ Ground::Ridge(verb: 'post', path: '/book/:id/comments', state: BookComments)
11
+ Ground::Ridge(verb: 'get', path: '/:username/notes', state: UserNotes)
12
+
13
+
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+
3
+ testdir = File.dirname(__FILE__)
4
+ $LOAD_PATH.unshift testdir unless $LOAD_PATH.include?(testdir)
5
+
6
+ libdir = File.dirname(File.dirname(__FILE__)) + '/lib'
7
+ $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
8
+
9
+ require 'ground'
10
+
11
+
@@ -0,0 +1,10 @@
1
+ require 'test_helper'
2
+
3
+ class ValidateTest < Test::Unit::TestCase
4
+
5
+ def test_validate
6
+ errors = Ground::Validate()
7
+ assert_equal errors, {}
8
+ end
9
+
10
+ end
metadata CHANGED
@@ -1,43 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ground
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
- - guimin jiang
7
+ - jgm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2014-06-25 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: dun
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ! '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ! '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: rack
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ! '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ! '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
12
+ dependencies: []
41
13
  description: ! ' A simple ruby web framework
42
14
 
43
15
  '
@@ -46,9 +18,29 @@ executables: []
46
18
  extensions: []
47
19
  extra_rdoc_files: []
48
20
  files:
49
- - README.md
50
- - Rakefile
51
- - licenses.txt
21
+ - lib/ground.rb
22
+ - lib/ground/activity.rb
23
+ - lib/ground/activity/create_application.rb
24
+ - lib/ground/activity/hash_with_double_access.rb
25
+ - lib/ground/activity/locate.rb
26
+ - lib/ground/activity/log.rb
27
+ - lib/ground/activity/ridge.rb
28
+ - lib/ground/activity/state.rb
29
+ - lib/ground/activity/validate.rb
30
+ - lib/ground/mime_type.rb
31
+ - lib/ground/protocol/helper.rb
32
+ - lib/ground/protocol/render.rb
33
+ - lib/ground/protocol/render/template.rb
34
+ - lib/ground/protocol/verb.rb
35
+ - lib/ground/rack/base_rack.rb
36
+ - lib/ground/rack/url_suffix.rb
37
+ - test/ground_set_test.rb
38
+ - test/hash_with_double_access_test.rb
39
+ - test/locate_test.rb
40
+ - test/ridge_test.rb
41
+ - test/routes.rb
42
+ - test/test_helper.rb
43
+ - test/validate_test.rb
52
44
  homepage: https://github.com/baya/ground
53
45
  licenses:
54
46
  - MIT
data/README.md DELETED
@@ -1,114 +0,0 @@
1
- # Ground
2
- Ground is a web framework, no controller, no model, no views and no mvc. Most of the ground codes are inherited from
3
- [Dun::Activity](https://github.com/baya/dun/blob/master/lib/dun.rb). So ground is a high unified web framework.
4
-
5
- ## states
6
-
7
- ```ruby
8
- class SiteIndex < Ground::State
9
- def call
10
- text 'Site Index'
11
- end
12
- end
13
-
14
- module Book
15
- State = Ground::State
16
-
17
- class Index < State
18
- def call
19
- @books = Book.all
20
- html erb('views/book/index.html.erb')
21
- end
22
- end
23
-
24
- class Show < State
25
- def call
26
- @book = Book.find(params[:id])
27
- html erb('views/book/show.html.erb')
28
- end
29
- end
30
-
31
- class Create < State
32
- def call
33
- @book = Book.create(params[:book])
34
- rediret '/books'
35
- end
36
- end
37
-
38
- end
39
- ```
40
-
41
- ## routes
42
-
43
- ```ruby
44
- Ground do
45
- get '/', SiteIndex
46
- get '/books', Book::Index
47
- get '/book/:id', Book::Show
48
- post '/book', Book::Create
49
- end
50
- ```
51
-
52
- ## route helpers
53
-
54
- ```ruby
55
- SiteIndex.path # '/'
56
- Book::Index.path # '/books'
57
- Book::Show.path(2) # '/book/2'
58
- Book::Create.path # '/book'
59
- ```
60
-
61
- ## sets
62
-
63
- ```ruby
64
- Ground do
65
- set :env, (ENV['RACK_ENV'] || 'development').to_s
66
- set :logger, ::Logger.new(STDOUT)
67
- en
68
-
69
- Ground.env #=> development
70
- Ground.logger.info("debug+++")
71
- ```
72
-
73
- ## helpers
74
-
75
- ```ruby
76
- # Book::Index, Book::Show will hava instance method 'hello_ground'
77
- Ground do
78
- help Book::Index, Book::Show do
79
-
80
- def hello_ground
81
- 'hello ground'
82
- end
83
-
84
- end
85
- end
86
- ```
87
-
88
- ## create a ground app
89
-
90
- ```ruby
91
- module BookStore
92
- App = Ground 'book store' do
93
- use Rack::ShowExceptions
94
- use Rack::Static, urls: ['/js', '/css', '/lib', '/partials'], :root => "lib/app"
95
- ...
96
- end
97
- end
98
- ```
99
-
100
- ## config.ru
101
-
102
- ``` ruby
103
- $: << '.'
104
- require 'app'
105
- run BookStore::App
106
- ```
107
-
108
- ## Apps using ground
109
-
110
- * [SceneMaster](https://github.com/baya/SceneMaster)
111
- * [Description](https://github.com/baya/description)
112
- * [Gstar](https://github.com/baya/Gstar)
113
-
114
-
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- require 'rake/testtask'
2
- Rake::TestTask.new do |t|
3
- t.libs << 'test'
4
- t.test_files = FileList['test/*_test.rb']
5
- end
6
-
7
- desc "Run tests"
8
- task :default => :test
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) <year> <copyright holders>
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.