maiha-dsl_accessor 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.
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
+