trinkets 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 68ed0792dc692c54ba0b00f781bc49b0baf2ce0d79b98fca94c2807c5532e8d7
4
+ data.tar.gz: f5724dff46a3b64e7ee40ac72fb852bc8e47e0b6683fc95704c901bbd19c7f0b
5
+ SHA512:
6
+ metadata.gz: 9d2738f9ce51557a84ae9c70896556d20cb321feb7ea31e9eee2be023dc25fa66bae7f85db4e720829b9d0338611b6c9c75e8fe7ac2f93df7db3728856c4bbf2
7
+ data.tar.gz: 2b0bb1da03c91f7eebff9a9f1994b5590c52cee0ab11b8643b1155805be00c79017092fcf49c017d52f95f1a8d08fc59e84659d913d4e35c6784b8bd7b541cba
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
File without changes
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 SilverPhoenix99
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # Trinkets
2
+
3
+ It's the bootleg [facets](https://github.com/rubyworks/facets?tab=readme-ov-file#ruby-facets).
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ gem install trinkets
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ There are 3 ways to load trinkets:
14
+ * As refinements;
15
+ * As explicit `include` or `extend`;
16
+ * As implicit `include` or `extend`, a.k.a. monkey-patching.
17
+
18
+ ### Refinement
19
+
20
+ ```ruby
21
+ require 'trinkets/refine/class/init'
22
+
23
+ using ::Trinkets::Class::Init
24
+ ```
25
+
26
+ ### Extend
27
+
28
+ ```ruby
29
+ require 'trinkets/extend/class/init'
30
+
31
+ class Test
32
+ extend ::Trinkets::Class::Init
33
+ end
34
+ ```
35
+
36
+ ### Mokey Patching
37
+
38
+ ```ruby
39
+ require 'trinkets/patch/class/init'
40
+ ```
41
+
42
+ ## Available modules
43
+
44
+ |Trinket|
45
+ |---|
46
+ |[class/init](doc/class/init.md)|
47
+
48
+ [//]: # (TODO: Development)
49
+ [//]: # (TODO: Contributing)
50
+
51
+ ## License
52
+
53
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/doc/class/init.md ADDED
@@ -0,0 +1,122 @@
1
+ # Description
2
+
3
+ It allows generating simple `#initialize` methods.
4
+
5
+ To use it define a class and call `::init` like you would call `::attr` methods:
6
+ * pass the name of the arguments as symbols
7
+ * pass options at the end:
8
+ * `attr` : what getters and/or setters to define
9
+ * can be `:accessor`, `:reader` or `:writer`
10
+ * defaults to `:accessor`
11
+ * `kw` : if arguments are to be set as keyword arguments
12
+ * defaults to `false`
13
+
14
+ The same options can be used per individual argument
15
+
16
+ # Examples
17
+
18
+ ## Simple Initialize
19
+ ```ruby
20
+ class Test
21
+ init :a, :b
22
+ end
23
+
24
+ # would be the same as
25
+ class Test
26
+ attr_accessor :a, :b
27
+ def initialize(a, b)
28
+ @a = a
29
+ @b = b
30
+ end
31
+ end
32
+
33
+ test = Test.new(1, 2)
34
+ test.a
35
+ # 1
36
+
37
+ test.b
38
+ # 2
39
+
40
+ test.a = 3
41
+ test.a
42
+ # 3
43
+ ```
44
+
45
+ ## Read only access to instance variables
46
+ ```ruby
47
+ class TestAttr
48
+ init :a, :b, attr: :reader
49
+ end
50
+
51
+ # would be the same as
52
+ class Test
53
+ attr_reader :a, :b
54
+ def initialize(a, b)
55
+ @a = a
56
+ @b = b
57
+ end
58
+ end
59
+
60
+ test = Test.new(1, 2)
61
+ test.a
62
+ # 1
63
+
64
+ test.b
65
+ # 2
66
+
67
+ test.a = 3
68
+ # > raises ArgumentError
69
+ ```
70
+
71
+ ## Initialize uses keyword arguments
72
+ ```ruby
73
+ class TestKW
74
+ init :a, :b, kw: :true
75
+ end
76
+
77
+ # would be the same as
78
+ class Test
79
+ attr_accessor :a, :b
80
+ def initialize(a:, b:)
81
+ @a = a
82
+ @b = b
83
+ end
84
+ end
85
+
86
+ test = Test.new(a: 1, b: 2)
87
+ test.a
88
+ # 1
89
+
90
+ test.b
91
+ # 2
92
+ ```
93
+
94
+ ## Individual argument options
95
+ ```ruby
96
+ class TestIndividualArgsOptions
97
+ init [:a, kw: true, attr: :reader], :b, [:c, kw: true]
98
+ end
99
+
100
+ # would be the same as
101
+ class Test
102
+ attr_reader :a
103
+ attr_accessor :b, :c
104
+ def initialize(b, a:, c:)
105
+ @a = a
106
+ @b = b
107
+ end
108
+ end
109
+
110
+ test = Test.new(2, a: 1, c: 3)
111
+ test.a
112
+ # 1
113
+
114
+ test.b
115
+ # 2
116
+
117
+ test.c
118
+ # 3
119
+
120
+ test.a = 4
121
+ # > raises ArgumentError
122
+ ```
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trinkets
4
+ module Class
5
+ module Init
6
+ ATTR = %i[accessor reader writer].freeze
7
+
8
+ def init(*attrs, attr: ATTR.first, kw: false)
9
+ raise ArgumentError, 'At least 1 attribute is required.' if attrs.empty?
10
+ raise ArgumentError, '`attr` must be one of :accessor (default), :reader or :writer' unless ATTR.include?(attr)
11
+
12
+ default_attr_options = { attr: attr, kw: kw }
13
+
14
+ # Normalize attrs into a hash: { :name => **options }
15
+ # @type [Hash[Symbol, Hash]]
16
+ attrs = attrs.map { |a| [*a] }
17
+ .map { |a| a.size == 1 ? a << {} : a }
18
+ .each_with_object({}) do |(name, opts), h|
19
+ # name, opts = a
20
+ name = name.to_s.sub(/^@/, '').to_sym
21
+ opts = default_attr_options.merge(opts)
22
+ h[name] = opts
23
+ end
24
+
25
+ attr_methods = ATTR
26
+ .each_with_object({}) do |name, h|
27
+ h[name] = method("attr_#{name}")
28
+ end
29
+
30
+ # even though options like `kw` aren't used, they serve here to validate the `attrs` options
31
+ attr_init = ->(name, attr: ATTR.first, kw: false) do
32
+ unless ATTR.include?(attr)
33
+ raise ArgumentError, "attr `#{name}`, option attr` must be one of :accessor (default), :reader or :writer"
34
+ end
35
+ attr_methods[attr].call(name)
36
+ end
37
+
38
+ attrs.each { |name, opts| attr_init.call(name, **opts) }
39
+
40
+ # 2 hashes: { :name => bool }
41
+ kw_attrs, attrs = attrs
42
+ .map { |name, opts| [name, opts[:kw]] }
43
+ .partition { |_, kw_opt| kw_opt }
44
+ .map(&:to_h)
45
+
46
+ init_method = ::Trinkets::Class.send :define_initialize, attrs, kw_attrs
47
+ define_method :initialize, init_method
48
+ end
49
+ end
50
+
51
+ class << self
52
+ # @param [Hash[Symbol Boolean]] attrs
53
+ # @param [Hash[Symbol Boolean]] kw_attrs
54
+ private def define_initialize(attrs, kw_attrs)
55
+ ->(*values, **kw_values) do
56
+
57
+ unless attrs.size == values.size
58
+ raise ArgumentError, "wrong number of arguments (given #{values.size}, expected #{attrs.size})"
59
+ end
60
+
61
+ missing_keys = kw_attrs.except(*kw_values.keys)
62
+ unless missing_keys.empty?
63
+ missing_keys = missing_keys.keys.map(&:inspect).join(', ')
64
+ raise ArgumentError, "missing keywords: #{missing_keys}"
65
+ end
66
+
67
+ unknown_keywords = kw_values.except(*kw_attrs.keys)
68
+ unless unknown_keywords.empty?
69
+ unknown_keywords = unknown_keywords.keys.map(&:to_sym).map(&:inspect).join(', ')
70
+ raise ArgumentError, "unknown keywords: #{unknown_keywords}"
71
+ end
72
+
73
+ attrs.keys.zip(values).each do |name, value|
74
+ instance_variable_set "@#{name}", value
75
+ end
76
+
77
+ kw_values.each do |name, value|
78
+ instance_variable_set "@#{name}", value
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../extend/class/init'
2
+
3
+ class ::Class
4
+ include ::Trinkets::Class::Init
5
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../../extend/class/init'
2
+
3
+ module Trinkets
4
+ module Class
5
+ module Init
6
+ refine ::Class do
7
+ import_methods ::Trinkets::Class::Init
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trinkets
4
+ VERSION = "0.1.0"
5
+ end
data/lib/trinkets.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'trinkets/version'
data/trinkets.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/trinkets/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'trinkets'
7
+ spec.version = Trinkets::VERSION
8
+ spec.authors = %w[SilverPhoenix99 P3t3rU5]
9
+ spec.email = %w[antoniopedrosilvapinto@gmail.com pedro.at.miranda@gmail.com]
10
+
11
+ spec.summary = 'Trinkets in your box.'
12
+ spec.description = 'Truly outrageous trinkets.'
13
+ spec.homepage = 'http://nowhere.example.com'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 3.2.0'
16
+
17
+ # spec.metadata['allowed_push_host'] = 'TODO: Set to your gem server "https://example.com"'
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ # spec.metadata['source_code_uri'] = "TODO: Put your gem's public repo URL here."
21
+ # spec.metadata['changelog_uri'] = "TODO: Put your gem's CHANGELOG.md URL here."
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(__dir__) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (File.expand_path(f) == __FILE__) ||
28
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
29
+ end
30
+ end
31
+ spec.require_paths = ['lib']
32
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trinkets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - SilverPhoenix99
8
+ - P3t3rU5
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2024-01-28 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Truly outrageous trinkets.
15
+ email:
16
+ - antoniopedrosilvapinto@gmail.com
17
+ - pedro.at.miranda@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".rspec"
23
+ - CHANGELOG.md
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - doc/class/init.md
28
+ - lib/trinkets.rb
29
+ - lib/trinkets/extend/class/init.rb
30
+ - lib/trinkets/patch/class/init.rb
31
+ - lib/trinkets/refine/class/init.rb
32
+ - lib/trinkets/version.rb
33
+ - trinkets.gemspec
34
+ homepage: http://nowhere.example.com
35
+ licenses:
36
+ - MIT
37
+ metadata:
38
+ homepage_uri: http://nowhere.example.com
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.2.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.5.3
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Trinkets in your box.
58
+ test_files: []