ruby-method-arguments 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: f98c731e8db7e8e471e0933be31868fe5551aff1a85202deec96d8c32b6b1aa7
4
+ data.tar.gz: fec0a5cfcbe4f7d120f741c24dbcf09cd8899b211b4a4cedb8f1ad4a2898b95b
5
+ SHA512:
6
+ metadata.gz: 12f76e8e6e3b6f13b0785ac28f95e2137d90267155c73f6c98e8aa07dd486485a34ffc9067d07cea3039684e46a9d77568ec032c3b920a5f3df191b9673d94a9
7
+ data.tar.gz: 3f78d6c1fc80d5370f5c18358046b3471ff77ae2f4ca5991a7d9eb601ad0c27fa36c814958bf249f9b2474eddad532635d73cbbe49f5813c44cd25906ff35dbc
data/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # method_arguments gem
2
+
3
+ With the [method_arguments](https://github.com/gorodulin/method_arguments?tab=readme-ov-file#method_arguments-gem) gem you can easily set object attributes from method arguments.
4
+
5
+ Transform this:
6
+
7
+ ```ruby
8
+ def initialize(user_entity, first_name:, last_name:, email:, phone:, dob:)
9
+ @user_entity = user_entity
10
+ @first_name = first_name
11
+ @last_name = last_name
12
+ @email = email
13
+ @phone = phone
14
+ @dob = dob
15
+ end
16
+ ```
17
+
18
+ into this streamlined version:
19
+
20
+ ```ruby
21
+ def initialize(user_entity, first_name:, last_name:, email:, phone:, dob:)
22
+ set_instance_vars(__method_args__)
23
+ end
24
+ ```
25
+
26
+ ## Features
27
+
28
+ ### 1. Reading Method Arguments
29
+
30
+ Within any method, call `__method_args__` to retrieve its arguments as a Hash.
31
+
32
+ ```ruby
33
+ def initialize(user_entity, first_name:, last_name:, age:, **kw_rest)
34
+ "Method ##{__method__} received #{__method_args__.inspect} arguments"
35
+ end
36
+ ```
37
+
38
+ <details>
39
+ <summary>Limitations</summary>
40
+ <br>
41
+
42
+ 1. Argument types `*rest` and `**keyrest` are ignored regardless of their name:
43
+
44
+ ```ruby
45
+ def initialize(arg, *arg_rest, kw_arg:, **kw_rest)
46
+ __method_args__ # returns { a: <value>, kw_arg: <value> }
47
+ end
48
+ ```
49
+
50
+ Casting unknown arbitrary arguments to instance variables is not recommended for security reasons.
51
+
52
+ 2. The method does not support [argument forwarding](https://docs.ruby-lang.org/en/3.2/syntax/methods_rdoc.html#label-Argument+Forwarding):
53
+
54
+ ```ruby
55
+ def self.call(...)
56
+ new(__method_args__).call # raises error
57
+ end
58
+ ```
59
+
60
+ </details>
61
+
62
+ ### 2. Filling instance @variables
63
+
64
+ Use `set_instance_vars(hash)` to assign instance variables from a Hash.
65
+
66
+ ### 3. Filling instance @variables using attribute writers
67
+
68
+ To leverage setters ([attribute writers](https://docs.ruby-lang.org/en/3.1/Module.html#method-i-attr_writer)), add `use_writers: true` argument. If a writer with the corresponding name exists, it will be invoked.
69
+
70
+ <details>
71
+ <summary>Example</summary>
72
+ <br>
73
+
74
+ Before:
75
+
76
+ ```ruby
77
+ def initialize(user_entity, first_name:, last_name:, age:)
78
+ @user_entity = user_entity
79
+ @first_name = first_name
80
+ @last_name = last_name
81
+ self.age = age
82
+ end
83
+
84
+ def age=(val)
85
+ @age = Integer(val)
86
+ end
87
+ ```
88
+
89
+ After:
90
+
91
+ ```ruby
92
+ def initialize(user_entity, first_name:, last_name:, age:, ...)
93
+ set_instance_vars(__method_args__, use_writers: true)
94
+ end
95
+
96
+ def age=(val)
97
+ @age = Integer(val)
98
+ end
99
+ ```
100
+ </details>
101
+
102
+ ## Installation
103
+
104
+ 1. Add to your Gemfile, then run `bundle install`:
105
+
106
+ ```ruby
107
+ gem "method_arguments"
108
+ ```
109
+
110
+ 2. Prepend your code with
111
+
112
+ ```ruby
113
+ require "method_arguments"
114
+ ```
115
+
116
+
117
+ ## Supported Ruby Versions
118
+
119
+ This gem is designed to be compatible with Ruby 2.7 and above. It has been tested on the following MRI versions:
120
+
121
+ - v2.7.2
122
+ - v3.0.3
123
+ - v3.1.2
124
+
125
+ If you encounter any issues with later versions, please feel free to report them.
126
+
@@ -0,0 +1,4 @@
1
+
2
+ module MethodArguments
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MethodArguments
4
+ module InstanceMethods
5
+
6
+ def set_instance_vars(args, use_writers: false)
7
+ raise "Call this method on instances only" if self.instance_of?(Class) || self.instance_of?(Module)
8
+
9
+ args.each_pair do |name, value|
10
+ if use_writers && respond_to?(writer = :"#{name}=", true)
11
+ send(writer, value)
12
+ else
13
+ instance_variable_set("@#{name}", value)
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ module BindingMethods
21
+ # See https://bugs.ruby-lang.org/issues/18487
22
+ define_method :__method_args__, ::Kernel::method(:binding) >> ->(bng) {
23
+ caller_info = caller_locations(1,1)[0]
24
+ caller_method_name = caller_info.base_label
25
+ begin
26
+ params = bng.receiver.method(caller_method_name).parameters.map do |type, varname|
27
+ (type == :keyrest || type == :rest || type == :block) ? nil : varname
28
+ end.compact
29
+ params.map { |varname| [varname, bng.local_variable_get(varname)] }.to_h
30
+ rescue NameError => err
31
+ raise err unless err.message.start_with?("undefined method `<")
32
+ raise RuntimeError, "__method_args__ called outside method", cause: nil
33
+ end
34
+ }
35
+ end
36
+ end
37
+
38
+ Object.include MethodArguments::BindingMethods unless Object.included_modules.include?(MethodArguments::BindingMethods)
39
+ Object.include MethodArguments::InstanceMethods unless Object.included_modules.include?(MethodArguments::InstanceMethods)
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-method-arguments
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Vladimir Gorodulin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-03-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ description: |
28
+ The 'method_arguments' gem simplifies the process of setting object attributes from method arguments in Ruby.
29
+ It introduces a streamlined approach to assign instance variables directly from method arguments with minimal boilerplate code.
30
+ This utility is especially useful in constructors or methods with numerous parameters, enhancing code readability and maintainability.
31
+ email:
32
+ - ru.hostmaster@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - README.md
38
+ - lib/method_arguments.rb
39
+ - lib/method_arguments/version.rb
40
+ homepage: https://github.com/gorodulin/method_arguments
41
+ licenses:
42
+ - MIT
43
+ metadata:
44
+ changelog_uri: https://github.com/gorodulin/method_arguments/CHANGELOG.md
45
+ homepage_uri: https://github.com/gorodulin/method_arguments
46
+ source_code_uri: https://github.com/gorodulin/method_arguments
47
+ rubygems_mfa_required: 'true'
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 2.7.0
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.2.32
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Read method arguments and assign instance variables
67
+ test_files: []