def_initialize 0.0.1 → 0.1.0

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,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: []