rails-patterns 0.1.1 → 0.2.0

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
  SHA1:
3
- metadata.gz: e7a4ed45fc0663789bf4ddb050d8d1a24dfb88af
4
- data.tar.gz: 5e4b2c49b8477c44764f611439f1d556d6e361b2
3
+ metadata.gz: e92ba62b5937443b24c3399655e678b6deb2d273
4
+ data.tar.gz: '0973bdde4d88392f6cd3a2a8a08fe77a3cf1f007'
5
5
  SHA512:
6
- metadata.gz: c2e27126c96ec9d5a508ccade1c3b11db7bfbeb7dc06c7754ac8ce154ae784800a5b0bd2be9b69fb74e19855c65e5dfe95defd3f46199a5b694b4cb7082a8a5a
7
- data.tar.gz: 047f3867ed52a6a7cbad689ea8be6fff248d3acb6ead8a9abf93b9ce7ef57379aa312a351ddfe417302fd63f54c0bb6fbb415a425a0f54025bad9ab8a8866e75
6
+ metadata.gz: 8fd3b635495855827654b7b818ee074ac562a919e6610c470cce226afcdf0dfe9944ff5867858d945054732c503babd63588d3775c517f9270846901f56eeb00
7
+ data.tar.gz: '068e1a602e2e1c591853e1491cfb1bf13e48f56dbaff45ee0db72417be176036939073769212d983da7b098ca5ecccd6935b0812fd83f761ee7db9cd176488e0'
data/README.md CHANGED
@@ -71,3 +71,52 @@ class User < ApplicationRecord
71
71
  scope :recenty_activated, RecentlyActivatedUsersQuery
72
72
  end
73
73
  ```
74
+
75
+ ## Service
76
+
77
+ ### When to use it
78
+
79
+ Service objects are commonly used to mitigate problems with model callbacks that interact with external classes ([read more...](http://samuelmullen.com/2013/05/the-problem-with-rails-callbacks/)).
80
+ Service objects are also useful for handling processes involving multiple steps. E.g. a controller that performs more than one operation on its subject (usually a model instance) is a possible candidate for Extract ServiceObject (or Extract FormObject) refactoring.
81
+
82
+ ### Assumptions and rules
83
+
84
+ * Service objects are always used by calling class-level `.call` method
85
+ * Service objects have to implement `#call` method
86
+ * Calling service object's `.call` method executes `#call` and returns service object instance
87
+ * A result of `#call` method is accessible through `#result` method
88
+ * It is recommended for `#call` method to be the only public method of service object (besides state readers)
89
+ * It is recommended to name service object classes after commands (e.g. `ActivateUser` instead of `UserActivation`)
90
+
91
+ ### Examples
92
+
93
+ #### Declaration
94
+
95
+ ```ruby
96
+ class ActivateUser < Patterns::Service
97
+ def initialize(user)
98
+ @user = user
99
+ end
100
+
101
+ def call
102
+ user.activate!
103
+ NotificationsMailer.user_activation_notification(user).deliver_now
104
+ user
105
+ end
106
+
107
+ private
108
+
109
+ attr_reader :user
110
+ end
111
+ ```
112
+
113
+ #### Usage
114
+
115
+ ```ruby
116
+ user_activation = ActivateUser.call(user)
117
+ user_activation.result # <User id: 5803143, email: "tony@patterns.dev ...
118
+ ```
119
+
120
+ ## Further reading
121
+
122
+ * [7 ways to decompose fat active record models](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
@@ -0,0 +1,18 @@
1
+ module Patterns
2
+ class Service
3
+ attr_reader :result
4
+
5
+ def self.call(*args)
6
+ new(*args).tap do |service|
7
+ service.instance_variable_set(
8
+ "@result",
9
+ service.call
10
+ )
11
+ end
12
+ end
13
+
14
+ def call
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end
@@ -1,2 +1,3 @@
1
1
  require "patterns"
2
2
  require "patterns/query"
3
+ require "patterns/service"
@@ -2,11 +2,11 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: rails-patterns 0.1.1 ruby lib
5
+ # stub: rails-patterns 0.2.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "rails-patterns".freeze
9
- s.version = "0.1.1"
9
+ s.version = "0.2.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
@@ -29,9 +29,11 @@ Gem::Specification.new do |s|
29
29
  "VERSION",
30
30
  "lib/patterns.rb",
31
31
  "lib/patterns/query.rb",
32
+ "lib/patterns/service.rb",
32
33
  "lib/rails-patterns.rb",
33
34
  "rails-patterns.gemspec",
34
35
  "spec/patterns/query_spec.rb",
36
+ "spec/patterns/service_spec.rb",
35
37
  "spec/spec_helper.rb"
36
38
  ]
37
39
  s.homepage = "http://github.com/selleo/pattern".freeze
@@ -0,0 +1,65 @@
1
+ RSpec.describe Patterns::Service do
2
+ after { Object.send(:remove_const, :DoSomething) if defined?(DoSomething) }
3
+
4
+ describe ".call" do
5
+ it "returns instance of service object" do
6
+ DoSomething = Class.new(Patterns::Service) do
7
+ def call; end
8
+ end
9
+
10
+ expect(DoSomething.call).to be_kind_of(DoSomething)
11
+ end
12
+
13
+ it "instantiates service object passing arguments to constructor" do
14
+ DoSomething = Class.new(Patterns::Service) do
15
+ def initialize(argument_1:, argument_2:); end
16
+ def call; end
17
+ end
18
+
19
+ expect {
20
+ DoSomething.call
21
+ }.to raise_error ArgumentError
22
+
23
+ expect {
24
+ DoSomething.call(argument_1: 10, argument_2: 20)
25
+ }.not_to raise_error
26
+ end
27
+
28
+ it "calls #call method on service object instance" do
29
+ Spy = Class.new do
30
+ def self.some_method; end
31
+ end
32
+ allow(Spy).to receive(:some_method)
33
+ DoSomething = Class.new(Patterns::Service) do
34
+ def call
35
+ Spy.some_method
36
+ end
37
+ end
38
+
39
+ DoSomething.call
40
+
41
+ expect(Spy).to have_received(:some_method)
42
+ end
43
+
44
+ it "requires #call method to be implemented" do
45
+ DoSomething = Class.new(Patterns::Service)
46
+
47
+ expect {
48
+ DoSomething.call
49
+ }.to raise_error NotImplementedError
50
+ end
51
+ end
52
+
53
+ describe "#result" do
54
+ it "returns a result of expression within #call method" do
55
+ DoSomething = Class.new(Patterns::Service) do
56
+ def call
57
+ 50
58
+ end
59
+ end
60
+
61
+ service = DoSomething.call
62
+ expect(service.result).to eq 50
63
+ end
64
+ end
65
+ end
@@ -17,7 +17,7 @@
17
17
  #
18
18
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
19
 
20
- require "pattern"
20
+ require "rails-patterns"
21
21
 
22
22
  RSpec.configure do |config|
23
23
  # rspec-expectations config goes here. You can use an alternate
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-patterns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stevo
@@ -84,9 +84,11 @@ files:
84
84
  - VERSION
85
85
  - lib/patterns.rb
86
86
  - lib/patterns/query.rb
87
+ - lib/patterns/service.rb
87
88
  - lib/rails-patterns.rb
88
89
  - rails-patterns.gemspec
89
90
  - spec/patterns/query_spec.rb
91
+ - spec/patterns/service_spec.rb
90
92
  - spec/spec_helper.rb
91
93
  homepage: http://github.com/selleo/pattern
92
94
  licenses: