trinkets 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []