spaced 0.2.0 → 0.3.1

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: 66ee2fb1875b3430e05c8c415823ae7ea872a15a515b1a9c2516e0f641e85951
4
- data.tar.gz: 659031771e54f892c823e65f1b3fab58eb2ada0ceec407dbcaec146497a1062d
3
+ metadata.gz: 496fc25b4cc4a7b4d8332661ace97b36a26ee5cb9592bfeb06e1743483c47c3b
4
+ data.tar.gz: 96b4ddf6c1c5e89ead4f894ced1f71c2b2a671c7838766572f94f85462bedf82
5
5
  SHA512:
6
- metadata.gz: 212bae85a0fdcf3dbdfc717e29328fd7fd8f8401b80082fec88464e03efe1d9adf07e24bb156f9b850c65104807d7cddf53343ea2582c30d8eb164b5b3cc921f
7
- data.tar.gz: 979e2988cdefc614aeb3ff884434f747fa1e5ebce38bb1de9212695ea9b53410e60b0cd72a4ba28054ce6d4689ee4088c3e4d7e9c3053124eb819f19f663b028
6
+ metadata.gz: 4751df5962de7c88361b534dff26007baeed5a91bd8a4f796aa75d6ff31f5a48c10c8b9dc8d53528af00f9089cc8bc8865b3c97b209227cb5c9dab96f84f4c33
7
+ data.tar.gz: eb9fd26c2e44f605bf9c9f733b22263ff86a0f5fd4d8003fe1457544b3a4b2a7f08ac13b3132a7447230c3017aab6c1c4bce5d407ee4bc56d53a6fc4dd86f8ef
data/.rubocop.yml CHANGED
@@ -14,6 +14,6 @@ Style/StringLiteralsInInterpolation:
14
14
  Layout/LineLength:
15
15
  Max: 120
16
16
  Metrics/MethodLength:
17
- Max: 15
17
+ Max: 20
18
18
  Style/Documentation:
19
19
  Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- spaced (0.1.1)
4
+ spaced (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,24 +1,32 @@
1
1
  # Spaced
2
2
 
3
- Spaced is a super simple and convenient way to isolate and namespace a collection of related methods.
3
+ Spaced is a super simple and convenient way to isolate and namespace a collection of related methods into any class.
4
+
5
+ ## Usage
4
6
 
5
7
  ```ruby
6
8
  class User
7
- namespace :twitter do
8
- def create(msg)
9
- api.create_tweet msg
10
- end
11
-
12
- def read(id)
13
- api.read_tweet id
14
- end
9
+ include Spaced
15
10
 
16
- private
11
+ # Pass a black with a bunch of methods.
12
+ namespace :twitter do
13
+ def create(msg)
14
+ api.create_tweet msg
15
+ end
17
16
 
18
- def api
19
- @api ||= TwitterClient.new(api_token: parent.api_token)
20
- end
17
+ def read(id)
18
+ api.read_tweet id
21
19
  end
20
+
21
+ private
22
+
23
+ def api
24
+ @api ||= TwitterClient.new(api_token: parent.api_token)
25
+ end
26
+ end
27
+
28
+ # Or pass a predefined class, which should subclass `Spaced::Base`.
29
+ namespace :facebook, Facebook::Api
22
30
  end
23
31
 
24
32
  user = User.new
@@ -28,6 +36,37 @@ user.twitter.read(id)
28
36
 
29
37
  In the example above, `namespace` creates and initializes a new class `Twitter` and returns it from the `#twitter` method. The parent class - in this case `User` - is available at `#parent` and `@parent` from within the namespace.
30
38
 
39
+ ## Magic bang and predicate methods
40
+
41
+ If you define a `call` method in your namespaced class, you can then conveniently call that with a bang method:
42
+
43
+ ```ruby
44
+ class User < Spaced::Base
45
+ include Spaced
46
+
47
+ namespace :tweet do
48
+ def call(content)
49
+ create_tweet content
50
+ end
51
+ end
52
+ end
53
+
54
+ user = User.new
55
+ user.tweet!('my new tweet') # Will call the `#call` method with whatever arguments you give it.
56
+ ```
57
+
58
+ There is also an equivalent `predicate` method:
59
+
60
+ ```ruby
61
+ namespace :tweet do
62
+ def predicate
63
+ false
64
+ end
65
+ end
66
+ user = User.new
67
+ user.tweet? # Will call the `#predicate` method.
68
+ ```
69
+
31
70
  ## Installation
32
71
 
33
72
  Add this line to your application's Gemfile:
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spaced
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/spaced.rb CHANGED
@@ -15,14 +15,18 @@ module Spaced
15
15
 
16
16
  module ClassMethods
17
17
  def namespace(name, klass = nil, &)
18
- unless klass
18
+ if klass
19
+ raise "#{klass} must be a subclass of Spaced::Base" unless klass < Spaced::Base
20
+ else
19
21
  class_name = name.to_s.split("_").collect(&:capitalize).join
20
- klass = eval <<-RUBY, binding, __FILE__, __LINE__ + 1 # rubocop:disable Security/Eval
22
+ klass = module_eval <<-RUBY, __FILE__, __LINE__ + 1
21
23
  #{self}::#{class_name} = Class.new(Base, &) # Parent::Namespace = Class.new(Base, &)
22
24
  RUBY
23
25
  end
24
26
 
25
27
  inst_name = :"@#{name}"
28
+
29
+ # Define the memoized namespace method.
26
30
  define_method name do
27
31
  if instance_variable_defined?(inst_name)
28
32
  instance_variable_get inst_name
@@ -32,6 +36,28 @@ module Spaced
32
36
  instance_variable_set inst_name, cls
33
37
  end
34
38
  end
39
+
40
+ # Define the bang and predicate methods.
41
+ methods = klass.instance_methods(false)
42
+
43
+ if methods.include?(:call)
44
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
45
+ def #{name}!(...); #{name}.call(...); end # def user!(...); user.call(...); end
46
+ RUBY
47
+ else
48
+ define_method :"#{name}!" do
49
+ raise NoMethodError, "undefined method `#{name}!' for #<#{klass}>. Have you defined `#{klass}#call`?", caller
50
+ end
51
+ end
52
+
53
+ if methods.include?(:predicate)
54
+ define_method(:"#{name}?") { send(name).predicate }
55
+ else
56
+ define_method :"#{name}?" do
57
+ raise NoMethodError, "undefined method `#{name}?' for #<#{klass}>. Have you defined `#{klass}#predicate`?",
58
+ caller
59
+ end
60
+ end
35
61
  end
36
62
  end
37
63
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spaced
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Moss
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-30 00:00:00.000000000 Z
11
+ date: 2022-10-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: