dsl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ Rakefile
@@ -0,0 +1,49 @@
1
+ # DSL
2
+
3
+ ## Description
4
+
5
+ dsl.rb is a small script (26 lines) to help create domain specific languages within Ruby.
6
+
7
+ ## Install
8
+
9
+ Until I setup the gem... just clone and play around with it.
10
+
11
+ ## Quick Example
12
+
13
+ require 'dsl'
14
+
15
+ class UserDSL < DSL
16
+ def name(n); @name = n; end
17
+ def gender(g); @gender = g; end
18
+ def age(a); @age = a; end
19
+ end
20
+
21
+ class User
22
+ attr :name, :gender, :age
23
+ dsl_method :edit => UserDSL
24
+ end
25
+
26
+ ryguy = User.new
27
+
28
+ ryguy.edit do
29
+ name 'Ryan Lewis'
30
+ gender :male
31
+ age 19
32
+ end
33
+
34
+ p ryguy
35
+ # => #<User:0x00000001b6dc78 @name="Ryan Lewis", @gender=:male, @age=19>
36
+
37
+ As you can see, simply requiring DSL adds the Module/Class method `dsl_method`, which defines a new instance method for your class that only accepts a block.
38
+
39
+ `dsl_method` only accepts a `Hash`, the key being the instance method name and the value being the DSL class the method will use.
40
+
41
+ When your DSL instance method is called (with a block, of course), all of your object's instance variables are delegated into a new instance of the DSL class assigned to the called DSL instance method.
42
+ The block is then `instance_eval`'d within the new DSL class instance where you can use the instance variables.
43
+ When the block is closed, all of the instance variables are then transfered back to your object.
44
+
45
+ Therefor, creating a Domain Specific Language is as easy as subclassing the `DSL` class. That's it!
46
+
47
+ ## Copyright
48
+
49
+ Copyright (c) 2010 Ryan Lewis. See LICENSE for details.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/dsl.rb ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class DSL
4
+ def self.call(parent, &blk)
5
+ instance = new
6
+ # Add all of the parents instance variables to the instance
7
+ parent.instance_variables.each do |instance_variable|
8
+ value = parent.instance_variable_get(instance_variable)
9
+ instance.instance_variable_set(instance_variable, value)
10
+ end
11
+ # Instance eval the block in the instance
12
+ instance.instance_eval(&blk)
13
+ # Replace all of the parents instance variables with the instance's
14
+ instance.instance_variables.each do |instance_variable|
15
+ value = instance.instance_variable_get(instance_variable)
16
+ parent.instance_variable_set(instance_variable, value)
17
+ end
18
+ end
19
+ end
20
+
21
+ class Module
22
+ def dsl_method(opts)
23
+ # Complain if the argument isn't a hash
24
+ raise(TypeError) unless opts.is_a?(Hash)
25
+ # For each dsl_method, define it in the class
26
+ # The methods do not accept arguments, only blocks
27
+ opts.each do |method, dsl_class|
28
+ define_method(method) do |&blk|
29
+ raise(ArgumentError, "method #{method} requires a block") unless block_given?
30
+ dsl_class.call(self, &blk)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'dsl')
4
+
5
+ class Database
6
+ class Table
7
+ def initialize
8
+ @schema = {}
9
+ @entries = []
10
+ end
11
+
12
+ def create(opts)
13
+ raise(TypeError) unless opts.is_a?(Hash)
14
+ opts.each do |name, v|
15
+ raise("key '#{name}' not defined in schema") unless @schema.has_key?(name)
16
+ if @schema[name] == :primary_key
17
+ raise('You cannot set primary keys')
18
+ else
19
+ raise("key '#{name}' not of type #{@schema[name]}") unless v.is_a?(@schema[name])
20
+ end
21
+ end
22
+ @schema.select { |name, v| v == :primary_key }.each do |name, v|
23
+ opts[name] = @entries.count
24
+ end
25
+ @entries << opts
26
+ end
27
+
28
+ def [](id)
29
+ @entries.find_all do |entry|
30
+ entry[:id] == id
31
+ end
32
+ end
33
+ end
34
+
35
+ class SchemaDSL < DSL
36
+ def primary_key(name); @schema[name] = :primary_key; end
37
+ def String(name); @schema[name] = ::String; end
38
+ def Integer(name); @schema[name] = ::Integer; end
39
+ end
40
+
41
+ def initialize
42
+ @tables = {}
43
+ end
44
+
45
+ def table(name, &blk)
46
+ if block_given?
47
+ raise("Table '#{name}' already exists") unless @tables[name].nil?
48
+ @tables[name] = Table.new
49
+ SchemaDSL.call(@tables[name], &blk)
50
+ else
51
+ @tables[name]
52
+ end
53
+ end
54
+ end
55
+
56
+ require 'ap'
57
+
58
+ db = Database.new
59
+
60
+ db.table(:users) do
61
+ primary_key :id
62
+ String :username
63
+ Integer :age
64
+ end
65
+
66
+ db.table(:users).create(:username => 'Foo', :age => 19)
67
+ db.table(:users).create(:username => 'Bar', :age => 43)
68
+
69
+ p db.table(:users)[0]
70
+ # => [{:username=>"Foo", :age=>19, :id=>0}]
71
+
72
+ p db.table(:users)[1]
73
+ # => [{:username=>"Bar", :age=>43, :id=>1}]
74
+
75
+ db.table(:users).create(:username => 'Baz', :age => 'One Hundred')
76
+ # => ERROR: key 'age' not of type Integer (RuntimeError)
77
+
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'dsl')
4
+
5
+ class UserDSL < DSL
6
+ def name(n); @name = n; end
7
+ def gender(g); @gender = g; end
8
+ def age(a); @age = a; end
9
+ end
10
+
11
+ class User
12
+ attr :name, :gender, :age
13
+ dsl_method :edit => UserDSL
14
+ end
15
+
16
+ ryguy = User.new
17
+
18
+ ryguy.edit do
19
+ name 'Ryan Lewis'
20
+ gender :male
21
+ age 19
22
+ end
23
+
24
+ p ryguy
25
+ # => #<User:0x00000001b6dc78 @name="Ryan Lewis", @gender=:male, @age=19>
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'dsl')
4
+
5
+ class ConfigDSL < DSL
6
+ def add_helpers(*h)
7
+ @helpers.concat(h)
8
+ end
9
+ end
10
+
11
+ class WebApp
12
+ attr :helpers
13
+ dsl_method :config => ConfigDSL
14
+
15
+ #===--- OR:
16
+ # dsl_method :config => Class.new(DSL) {
17
+ # def add_helpers(*h)
18
+ # @helpers.concat(h)
19
+ # end
20
+ # }
21
+
22
+ #===--- MAYBE:
23
+ # define_dsl_method :config do
24
+ # def add_helpers; end
25
+ # end
26
+
27
+ def initialize
28
+ @helpers = ['helpers/foo', 'helpers/bar']
29
+ end
30
+ end
31
+
32
+ web_app = WebApp.new
33
+
34
+ p web_app.helpers
35
+ # => ["helpers/foo", "helpers/bar"]
36
+
37
+ web_app.config do
38
+ add_helpers 'helpers/baz', 'helpers/qux'
39
+ end
40
+
41
+ p web_app.helpers
42
+ # => ["helpers/foo", "helpers/bar", "helpers/baz", "helpers/qux"]
43
+
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dsl
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Ryan Lewis
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-16 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Easily create Domain Specific Languages with any block. You can also link instance methods to your DSL.
23
+ email: c00lryguy@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.md
30
+ files:
31
+ - .gitignore
32
+ - README.md
33
+ - VERSION
34
+ - dsl.rb
35
+ - examples/database.rb
36
+ - examples/user.rb
37
+ - examples/webapp.rb
38
+ has_rdoc: true
39
+ homepage: http://github.com/c00lryguy/dsl
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ hash: 3
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.7
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: A small library for creating Domain Specific Languages (DSLs)
72
+ test_files:
73
+ - examples/webapp.rb
74
+ - examples/database.rb
75
+ - examples/user.rb