def_initialize 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da9558b590f6a5b33da3f9871f016f3407be482fc9897da72f2161943d12aebd
4
- data.tar.gz: 6bf1414cd27b93b2cdbcb45a813bbe6516f2cce65c28ae5d70a85710e0aa1249
3
+ metadata.gz: baa0280d5bf1bcf38f202c06e1504b5fdd365977a7ec6695c579349ef0006b65
4
+ data.tar.gz: 3768cfd27fc19807146acf23403aa07c438398acb41e1bb7bb36ed1113a23150
5
5
  SHA512:
6
- metadata.gz: dba72131210affed9c9eb65d5e7397295cfcd4eda192c0fb87af25402d1d83016a7ff98caed26aac48a152b8254dfd6b9bf121c2ced1406c56b50c833447fa8f
7
- data.tar.gz: 3ef56b6df19bd719dec4d92a2780ea8145c7bb3f3c303bc5685b20121331ef97864f90930d51ee3bb8e3470f8c77096a2fd32b562e5275e5f65d5cd4f5584c0a
6
+ metadata.gz: fc0fdec0a482a0bf7429f59a97bd280e293da25c544f9570f88fc1bc39545188964ccc055c10ca7b95aaf158647877b5172d8edd38c3cb15f595bbc5082d6e27
7
+ data.tar.gz: f2f19e386c0809565eaf97d3c75163d0951b551a11ee92ee92c6263728e9dbec041752872289cdca64d5e5a0e6dfc9868977ade3f0a3972615d1064f732dd1e9
@@ -3,5 +3,8 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.3.3
6
+ - 2.3
7
+ - 2.4
8
+ - 2.5
9
+ - 2.6
7
10
  before_install: gem install bundler -v 2.0.1
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://travis-ci.org/antoshalee/def_initialize.svg?branch=master)](https://travis-ci.org/antoshalee/def_initialize)
2
+
1
3
  # DefInitialize (WIP)
2
4
 
3
5
  Another approach to reduce initialization boilerplate
@@ -23,26 +25,96 @@ Or install it yourself as:
23
25
 
24
26
  ```ruby
25
27
  class Employee
26
- include DefInitialize.with("name, uuid = SecureRandom.uuid, age, position: 'manager'")
28
+ include DefInitialize.with("name, uuid = SecureRandom.uuid, age:, position: 'manager'")
27
29
  end
28
30
 
29
31
  # is the same as:
30
32
 
31
33
  class Employee
32
- attr_reader :name, :uuid, :age, :position
33
-
34
34
  def initialize(name, uuid = SecureRandom.uuid, age:, position: 'manager')
35
35
  @name = name
36
36
  @uuid = uuid
37
37
  @age = age
38
38
  @position = position
39
39
  end
40
+
41
+ private
42
+
43
+ attr_reader :name, :uuid, :age, :position
44
+ end
45
+ ```
46
+
47
+ By convention, parameters starting with underscore symbol `'_'` are ignored:
48
+
49
+ ```ruby
50
+ class Point
51
+ include DefInitialize.with("x, y, _c")
52
+ end
53
+
54
+ # transforms to:
55
+
56
+ class Point
57
+ def initialize(x, y, _c) # Note that `_c` is still required to pass
58
+ @x = x
59
+ @y = y
60
+ end
61
+
62
+ private
63
+
64
+ attr_reader :x, :y
40
65
  end
41
66
  ```
42
67
 
68
+ ### DSL
69
+
70
+ Alternatively, you can extend a class with `DefInitialize::DSL` and use `def_initialize` method. Note, how close it looks to the native declaration!
71
+
72
+ ```ruby
73
+ class Base
74
+ extend DefInitialize::DSL
75
+ end
76
+
77
+ class Circle < Base
78
+ def_initialize("radius")
79
+ end
80
+
81
+ class Rectangle < Base
82
+ def_initialize("length, width")
83
+ end
84
+ ```
85
+
86
+ ### Access control
87
+
88
+ You can specify level of access for your readers and writers:
89
+
90
+ ```ruby
91
+ class Person < Base
92
+ def_initialize("name", readers: :public, writers: :private)
93
+ end
94
+
95
+ # transforms to:
96
+
97
+ class Person
98
+ def initialize(name)
99
+ @name = name
100
+ end
101
+
102
+ attr_reader :name
103
+
104
+ private
105
+
106
+ attr_writer :name
107
+ end
108
+
109
+ ```
110
+ Allowed values are `:public`, `:private`, `:protected` and `nil`. If value is `nil`, accessors won't be defined at all.
111
+
112
+ default value for `readers` is `private`, default value for `writers` is `nil`
113
+
114
+
43
115
  ### What should I do in more complex cases?
44
116
 
45
- Just write old plain `def initialize`
117
+ Just write plain old `def initialize`.
46
118
 
47
119
 
48
120
  ## Development
@@ -6,10 +6,10 @@ require 'def_initialize/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'def_initialize'
8
8
  spec.version = DefInitialize::VERSION
9
- spec.authors = ['Anton Lee']
10
- spec.email = ['antoshalee@gmail.com']
9
+ spec.authors = ['Anton Lee', 'Vladimir Kochnev']
10
+ spec.email = ['antoshalee@gmail.com', 'hashtable@yandex.ru']
11
11
 
12
- spec.summary = 'Define your initializer along with attribute readers in one line'
12
+ spec.summary = 'Define an initializer along with attribute accessors in one line'
13
13
  spec.homepage = 'https://github.com/antoshalee/def_initialize'
14
14
  spec.license = 'MIT'
15
15
 
@@ -1,51 +1,43 @@
1
- require "def_initialize/version"
1
+ # frozen_string_literal: true
2
2
 
3
3
  module DefInitialize
4
- # Simply parses input string as a method parameter string
5
- # It raises an exception, If it fails
6
- # Otherwise returns all argument names including keyword arguments
7
- class Parser
8
- VAR_RE = /(\w+)/
9
- ARG_RE = /#{VAR_RE}(?:\s=\s.+?)*/
10
- ARGS_RE = /#{ARG_RE}(?:, #{ARG_RE})*/
11
- KWARG_RE = /#{VAR_RE}:(?:\s.+?)*/
12
- KWARGS_RE = /#{KWARG_RE}(?:, #{KWARG_RE})*/
13
- RE = /\A#{ARGS_RE}(?:, #{KWARGS_RE})?\z/
14
-
15
- class << self
16
- def parse(str)
17
- if(match_data = str.match(RE))
18
- match_data.captures
19
- else
20
- raise ArgumentError, 'Failed to parse arguments'
21
- end
22
- end
23
- end
24
- end
4
+ require 'def_initialize/version'
5
+ require 'def_initialize/dsl'
6
+ require 'def_initialize/accessors_builder'
25
7
 
26
8
  class Mixin < Module
27
- def initialize(args_str)
28
- args = Parser.parse(args_str)
9
+ def initialize(args_str, readers: :private, writers: nil)
10
+ accessors_options = { readers_mode: readers, writers_mode: writers }
11
+
12
+ # Create empty method just to inspect its parameters.
13
+ module_eval <<-CODE, __FILE__, __LINE__ + 1
14
+ def initialize(#{args_str}); end
15
+ CODE
29
16
 
30
- readers = args.map { |a| ":#{a}"}.join(", ")
17
+ parameters = instance_method(:initialize).parameters
31
18
 
32
- body = args.reduce(''.dup) do |acc, arg|
33
- acc << "@#{arg} = #{arg}\n"
34
- end
19
+ accessors, rows = [], []
20
+
21
+ parameters
22
+ .each do |(_type, name)|
23
+ next if !name || name.to_s.start_with?('_')
24
+ accessors << ":#{name}"
25
+ rows << "@#{name} = #{name}"
26
+ end
35
27
 
36
28
  module_eval <<-CODE, __FILE__, __LINE__ + 1
37
29
  def initialize(#{args_str})
38
- #{body}
30
+ #{rows.join("\n")}
39
31
  end
40
32
 
41
- attr_reader #{readers}
33
+ #{AccessorsBuilder.build(accessors, accessors_options)}
42
34
  CODE
43
35
  end
44
36
  end
45
37
 
46
38
  class << self
47
- def with(args_str)
48
- Mixin.new(args_str)
39
+ def with(args_str, **opts)
40
+ Mixin.new(args_str, **opts)
49
41
  end
50
42
  end
51
43
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefInitialize
4
+ module AccessorsBuilder
5
+ class << self
6
+ def build(accessors, readers_mode:, writers_mode:)
7
+ check_option!(readers_mode)
8
+ check_option!(writers_mode)
9
+
10
+ result = ''.dup
11
+
12
+ if readers_mode
13
+ result << "#{readers_mode}\n"
14
+ result << "attr_reader #{accessors.join(', ')}\n"
15
+ end
16
+
17
+ if writers_mode
18
+ result << "#{writers_mode}\n"
19
+ result << "attr_writer #{accessors.join(', ')}\n"
20
+ end
21
+
22
+ result
23
+ end
24
+
25
+ private
26
+
27
+ def check_option!(value)
28
+ return unless value
29
+ return if %w[private public protected].include?(value.to_s)
30
+
31
+ raise ArgumentError,
32
+ "Uknown value #{value}. Must be :private, :public, :protected or nil"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ module DefInitialize
2
+ module DSL
3
+ def def_initialize(args_str, **opts)
4
+ include(DefInitialize.with(args_str, **opts))
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module DefInitialize
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.1.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: def_initialize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Lee
8
+ - Vladimir Kochnev
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2019-03-08 00:00:00.000000000 Z
12
+ date: 2019-03-11 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
@@ -55,6 +56,7 @@ dependencies:
55
56
  description:
56
57
  email:
57
58
  - antoshalee@gmail.com
59
+ - hashtable@yandex.ru
58
60
  executables: []
59
61
  extensions: []
60
62
  extra_rdoc_files: []
@@ -71,6 +73,8 @@ files:
71
73
  - bin/setup
72
74
  - def_initialize.gemspec
73
75
  - lib/def_initialize.rb
76
+ - lib/def_initialize/accessors_builder.rb
77
+ - lib/def_initialize/dsl.rb
74
78
  - lib/def_initialize/version.rb
75
79
  homepage: https://github.com/antoshalee/def_initialize
76
80
  licenses:
@@ -94,5 +98,5 @@ requirements: []
94
98
  rubygems_version: 3.0.3
95
99
  signing_key:
96
100
  specification_version: 4
97
- summary: Define your initializer along with attribute readers in one line
101
+ summary: Define an initializer along with attribute accessors in one line
98
102
  test_files: []