maiha-dsl_accessor 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,131 @@
1
+ DslAccessor
2
+ ===========
3
+
4
+ This plugin gives hybrid accessor class methods to classes by DSL like definition,
5
+ here hybrid means getter and setter. The accessor method acts as getter method
6
+ if no argments given, otherwise it acts as setter one with the arguments.
7
+
8
+
9
+ Usage
10
+ =====
11
+
12
+ class Foo
13
+ dsl_accessor "<METHOD NAME>"
14
+ end
15
+
16
+
17
+ Example
18
+ =======
19
+
20
+ class Foo
21
+ dsl_accessor :greeting
22
+ end
23
+
24
+ This code gives 'greeting' class method to Foo class.
25
+
26
+ Foo.greeting # means getter, and the default value is nil.
27
+ => nil
28
+
29
+ Foo.greeting "I'm Foo." # means setter with given arguments
30
+ => "I'm Foo."
31
+
32
+ Foo.greeting
33
+ => "I'm Foo."
34
+
35
+
36
+ Difference
37
+ ==========
38
+
39
+ I'm convinced that you want to propose me to use 'cattr_accessor'.
40
+ Although the difference is just whether we needs '=' operation or not,
41
+ it makes a large different on class definition especially subclass.
42
+
43
+ class Foo
44
+ cattr_accessor :greeting
45
+ end
46
+
47
+ class Bar < Foo
48
+ self.greeting = "I'm bar."
49
+ end
50
+
51
+ We must write redundant code represented by "self." to distinguish
52
+ a local variable and a class method when we use 'cattr_accessor'.
53
+ This is ugly and boring work.
54
+
55
+ class Foo
56
+ dsl_accessor :greeting
57
+ end
58
+
59
+ class Bar < Foo
60
+ greeting "I'm bar."
61
+ end
62
+
63
+ There are no longer redundant prefix code like "self." and "set_".
64
+ Don't you like this dsl-like coding with simple declaration?
65
+
66
+
67
+ Special Options
68
+ ===============
69
+
70
+ 'dsl_accessor' method can take two options, those are :writer and :default.
71
+ "writer" option means callback method used when setter is executed.
72
+ "default" option means default static value or proc that creates some value.
73
+
74
+ class PseudoAR
75
+ dsl_accessor :primary_key, :default=>"id", :writer=>proc{|value| value.to_s}
76
+ dsl_accessor :table_name, :default=>proc{|klass| klass.name.demodulize.underscore.pluralize}
77
+ end
78
+
79
+ class Item < PseudoAR
80
+ end
81
+
82
+ class User < PseudoAR
83
+ primary_key :user_code
84
+ table_name :user_table
85
+ end
86
+
87
+ Item.primary_key # => "id"
88
+ Item.table_name # => "items"
89
+ User.primary_key # => "user_code"
90
+ User.table_name # => :user_table
91
+
92
+ Note that "User.primary_key" return a String by setter proc.
93
+
94
+
95
+ Instance Method
96
+ ===============
97
+
98
+ "instance" option automatically defines its instance method
99
+
100
+ class Search
101
+ dsl_accessor :url, :instance=>true, :default=>"http://localhost/"
102
+ end
103
+
104
+ Search.url # => "http://localhost/"
105
+ Search.new.url # => "http://localhost/"
106
+
107
+ and it uses @options instance variable with special value :options
108
+
109
+ class Window
110
+ dsl_accessor :width, :default=>640, :instance=>:options
111
+ def initialize(options = {})
112
+ @options = options
113
+ end
114
+ end
115
+
116
+ Window.width # => 640
117
+ Window.new.width # => 640
118
+
119
+ window = Window.new(:width=>320)
120
+ window.width # =>320
121
+
122
+
123
+ Install
124
+ =======
125
+
126
+ git://github.com/maiha/dsl_accessor.git
127
+
128
+
129
+ Author
130
+ ======
131
+ Maiha <anna@wota.jp>
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the dsl_accessor plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the dsl_accessor plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'DslAccessor'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,71 @@
1
+ class Class
2
+ def dsl_accessor(name, *args)
3
+ options = args.last.is_a?(Hash) ? args.pop : {}
4
+ options[:default] = args.shift unless args.empty?
5
+
6
+ case options[:instance]
7
+ when nil
8
+ # nop
9
+ when :options
10
+ module_eval(<<-EOS, "(__DSL_ACCESSOR__)", 1)
11
+ def #{ name }
12
+ unless @options
13
+ raise TypeError, "DSL Error: missing @options for %s##{name}" % self.class.name
14
+ end
15
+ @options[:#{ name }] || self.class.#{ name }
16
+ end
17
+ EOS
18
+ when true
19
+ delegate name, :to=>"self.class"
20
+ else
21
+ raise TypeError, "DSL Error: :instance should be true or :instance, but got `%s' class" % options[:instance].class
22
+ end
23
+
24
+ raise TypeError, "DSL Error: options should be a hash. but got `#{options.class}'" unless options.is_a?(Hash)
25
+ writer = options[:writer] || options[:setter]
26
+ writer =
27
+ case writer
28
+ when NilClass then Proc.new{|value| value}
29
+ when Symbol then Proc.new{|value| __send__(writer, value)}
30
+ when Proc then writer
31
+ else raise TypeError, "DSL Error: writer should be a symbol or proc. but got `#{options[:writer].class}'"
32
+ end
33
+ write_inheritable_attribute(:"#{name}_writer", writer)
34
+
35
+ default =
36
+ case options[:default]
37
+ when NilClass then nil
38
+ when [] then Proc.new{[]}
39
+ when {} then Proc.new{{}}
40
+ when Symbol then Proc.new{__send__(options[:default])}
41
+ when Proc then options[:default]
42
+ else Proc.new{options[:default]}
43
+ end
44
+ write_inheritable_attribute(:"#{name}_default", default)
45
+
46
+ (class << self; self end).class_eval do
47
+ define_method("#{name}=") do |value|
48
+ writer = read_inheritable_attribute(:"#{name}_writer")
49
+ value = writer.call(value) if writer
50
+ write_inheritable_attribute(:"#{name}", value)
51
+ end
52
+
53
+ define_method(name) do |*values|
54
+ if values.empty?
55
+ # getter method
56
+ key = :"#{name}"
57
+ if !inheritable_attributes.has_key?(key)
58
+ default = read_inheritable_attribute(:"#{name}_default")
59
+ value = default ? default.call(self) : nil
60
+ __send__("#{name}=", value)
61
+ end
62
+ read_inheritable_attribute(key)
63
+ else
64
+ # setter method
65
+ __send__("#{name}=", *values)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+
2
+ require File.dirname(__FILE__) + '/core_ext/class/dsl_accessor'
3
+
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1 @@
1
+ # DslAccessor
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :dsl_accessor do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,64 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+
4
+ class DslDefaultAccessorTest < Test::Unit::TestCase
5
+
6
+ class CoolActiveRecord
7
+ dsl_accessor :primary_key, :default=>"id"
8
+ dsl_accessor :table_name, :default=>proc{|klass| klass.name.demodulize.underscore.pluralize}
9
+ end
10
+
11
+ class Item < CoolActiveRecord
12
+ end
13
+
14
+ class User < CoolActiveRecord
15
+ end
16
+
17
+ class Folder
18
+ dsl_accessor :array_folder, :default=>[]
19
+ dsl_accessor :hash_folder, :default=>{}
20
+ end
21
+
22
+ class SubFolder < Folder
23
+ end
24
+
25
+ def test_default_accessor_with_string
26
+ assert_equal "id", Item.primary_key
27
+ assert_equal "id", User.primary_key
28
+ end
29
+
30
+ def test_default_accessor_with_proc
31
+ assert_equal "items", Item.table_name
32
+ assert_equal "users", User.table_name
33
+ end
34
+
35
+ def test_default_accessor_should_duplicate_empty_array_or_hash
36
+ Folder.array_folder << 1
37
+ Folder.hash_folder[:name] = "maiha"
38
+
39
+ assert_equal([1], Folder.array_folder)
40
+ assert_equal({:name=>"maiha"}, Folder.hash_folder)
41
+
42
+ assert_equal([], SubFolder.array_folder)
43
+ assert_equal({}, SubFolder.hash_folder)
44
+ end
45
+ end
46
+
47
+
48
+ class DslOverwritenDefaultAccessorTest < Test::Unit::TestCase
49
+ class CoolActiveRecord
50
+ dsl_accessor :primary_key, :default=>"id"
51
+ dsl_accessor :table_name, :default=>proc{|klass| klass.name.demodulize.underscore.pluralize}
52
+ end
53
+
54
+ class Item < CoolActiveRecord
55
+ primary_key :item_id
56
+ table_name :item_table
57
+ end
58
+
59
+ def test_overwrite_default_accessor
60
+ assert_equal :item_id, Item.primary_key
61
+ assert_equal :item_table, Item.table_name
62
+ end
63
+ end
64
+
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+
4
+ class DslAccessorTest < Test::Unit::TestCase
5
+ class CoolActiveRecord
6
+ dsl_accessor :primary_key
7
+ dsl_accessor :table_name
8
+ end
9
+
10
+ class Item < CoolActiveRecord
11
+ end
12
+
13
+ class LegacyItem < CoolActiveRecord
14
+ primary_key :itcd
15
+ table_name :item
16
+ end
17
+
18
+ class OtherClass
19
+ end
20
+
21
+ def test_dsl_accessor_doesnt_affect_other_classes
22
+ assert !OtherClass.respond_to?(:primary_key)
23
+ end
24
+
25
+ def test_accessor_without_initialization
26
+ assert_equal nil, Item.primary_key
27
+ assert_equal nil, Item.table_name
28
+
29
+ Item.primary_key :itcd
30
+ Item.table_name :item
31
+
32
+ assert_equal :itcd, Item.primary_key
33
+ assert_equal :item, Item.table_name
34
+ end
35
+
36
+ def test_accessor_with_initialization
37
+ assert_equal :itcd, LegacyItem.primary_key
38
+ assert_equal :item, LegacyItem.table_name
39
+
40
+ LegacyItem.primary_key :item_id
41
+ LegacyItem.table_name :item_table
42
+
43
+ assert_equal :item_id, LegacyItem.primary_key
44
+ assert_equal :item_table, LegacyItem.table_name
45
+ end
46
+ end
47
+
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class DefineInstanceMethodWithOptionsTest < Test::Unit::TestCase
4
+ class Window
5
+ dsl_accessor :width, :default=>640, :instance=>:options
6
+ end
7
+
8
+ class OptionedWindow
9
+ dsl_accessor :width, :default=>640, :instance=>:options
10
+ def initialize(options = {})
11
+ @options = options
12
+ end
13
+ end
14
+
15
+ def test_class_method
16
+ assert_equal Window.width, 640
17
+ assert_equal OptionedWindow.width, 640
18
+ end
19
+
20
+ def test_instance_method
21
+ assert_raises(TypeError) { Window.new.width }
22
+ assert_equal OptionedWindow.new.width, 640
23
+ end
24
+
25
+ def test_use_options_variable_rather_than_default_value
26
+ window = OptionedWindow.new( :width => 320 )
27
+ assert_equal window.width, 320
28
+ end
29
+
30
+ def test_instance_options_value_doesnt_affect_to_class_method
31
+ window = OptionedWindow.new( :width => 320 )
32
+ assert_equal OptionedWindow.width, 640
33
+ end
34
+
35
+ end
36
+
37
+
38
+
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class DefineInstanceMethodTest < Test::Unit::TestCase
4
+ class Item
5
+ dsl_accessor :primary_key, "code", :instance=>true
6
+ end
7
+
8
+ class OtherClass
9
+ end
10
+
11
+ def test_dsl_accessor_doesnt_affect_other_classes
12
+ assert !OtherClass.respond_to?(:primary_key)
13
+ end
14
+
15
+ def test_dsl_accessor_doesnt_affect_other_instances
16
+ assert !OtherClass.new.respond_to?(:primary_key)
17
+ end
18
+
19
+ def test_class_method
20
+ assert Item.respond_to?(:primary_key)
21
+ assert_nothing_raised do
22
+ Item.primary_key
23
+ end
24
+ end
25
+
26
+ def test_class_method_value
27
+ assert_equal "code", Item.primary_key
28
+ end
29
+
30
+ def test_instance_method
31
+ assert Item.new.respond_to?(:primary_key)
32
+ assert_nothing_raised do
33
+ Item.new.primary_key
34
+ end
35
+ end
36
+
37
+ def test_instance_method_value
38
+ assert_equal "code", Item.new.primary_key
39
+ end
40
+ end
41
+
42
+
43
+
@@ -0,0 +1,14 @@
1
+ require 'test/unit'
2
+
3
+ def __DIR__; File.dirname(__FILE__); end
4
+
5
+ begin
6
+ require 'rubygems'
7
+ require 'active_support'
8
+ rescue LoadError
9
+ $:.unshift(__DIR__ + '/../../../rails/activesupport/lib')
10
+ require 'active_support'
11
+ end
12
+
13
+ require File.dirname(__FILE__) + '/../init'
14
+
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+
4
+ class DslWriterAccessorTest < Test::Unit::TestCase
5
+ class Item
6
+ dsl_accessor :primary_key, :writer=>proc{|value| value.to_s}
7
+ end
8
+
9
+ def test_string_writer
10
+ assert_equal "", Item.primary_key
11
+
12
+ Item.primary_key :id
13
+ assert_equal "id", Item.primary_key
14
+
15
+ Item.primary_key "id"
16
+ assert_equal "id", Item.primary_key
17
+ end
18
+ end
19
+
20
+
21
+
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: maiha-dsl_accessor
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.2"
5
+ platform: ruby
6
+ authors:
7
+ - maiha
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-02 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: ""
17
+ email: maiha@wota.jp
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - Rakefile
27
+ - core_ext/class/dsl_accessor.rb
28
+ - init.rb
29
+ - install.rb
30
+ - lib/dsl_accessor.rb
31
+ - tasks/dsl_accessor_tasks.rake
32
+ - test/default_test.rb
33
+ - test/dsl_accessor_test.rb
34
+ - test/instance_options_test.rb
35
+ - test/instance_test.rb
36
+ - test/test_helper.rb
37
+ - test/writer_test.rb
38
+ has_rdoc: true
39
+ homepage: http://github.com/maiha/dsl_accessor
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.0.1
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: ""
64
+ test_files: []
65
+