generic_job 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +126 -7
- metadata +70 -10
- data/lib/tasks/generic_job_tasks.rake +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92d3bc04b8a275912c8db7c199066a1fd2b9a490c95c8885bb6dd81fa85afab3
|
4
|
+
data.tar.gz: 9952a976e9a4b2fbe71ed1201643ce04355f75c238c366bb8bd1a5d234b989a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d64823b2bfbd3ee24f754f8232a3e6d56014d039ae918dd9021466e2cfa5b6efe73c8d987f02b048f1853a87cff67fc3e4a4d59c625986b25a6b48960a0836f1
|
7
|
+
data.tar.gz: bd04831cdf0bbc45fa395a0b48b29b178d8b81868c883fc06c0943d5e533ae96239eb7c30b71aabb3be1e6662f8f86082070a767e710f30b8aae9d31eef57b9a
|
data/README.md
CHANGED
@@ -1,10 +1,123 @@
|
|
1
1
|
# GenericJob
|
2
|
-
Short description and motivation.
|
3
2
|
|
4
|
-
##
|
5
|
-
|
3
|
+
## 🤔 Why you may need it?
|
4
|
+
|
5
|
+
GenericJob is a Rails plugin.
|
6
|
+
|
7
|
+
Active Job does a great work when it comes to declaring jobs and making them run on a variety of queuing backends.
|
8
|
+
To do so, you have to create a job in `app/jobs`, implement `perform` method and enqueue a job by calling `perform_later`.
|
9
|
+
|
10
|
+
But most often you just want to call a given model's or service object's method in the background.
|
11
|
+
|
12
|
+
There is an effort involved with that:
|
13
|
+
|
14
|
+
1. You have to define another _job_ for every class or even a method that you want to run in the background.
|
15
|
+
2. If the purpose of this `ApplicationJob` class is to only run a specific method in the background, it feels redundant.
|
16
|
+
3. On the other hand, if you decide to have an additional logic in the _Job_ class, you basically lock it down to work in the background process only.
|
17
|
+
|
18
|
+
There should be an easier way. And there is. But before looking at the details, let's form our manifesto.
|
19
|
+
|
20
|
+
|
21
|
+
### 📜 Manifesto
|
22
|
+
|
23
|
+
**Every method should be possible to run in the background with the minimal effort. Wherever it makes sense.**
|
24
|
+
|
25
|
+
_Controller's method running in the background does not make sense for example_ 😉
|
26
|
+
|
27
|
+
|
28
|
+
This is what GenericJob does. It creates a default _Job_ called `GenericJob` and delivers a module named `GenericJob::Async`.
|
29
|
+
Include it in a given class to be able to run its methods in the background.
|
30
|
+
|
31
|
+
## 🎮 Usage
|
32
|
+
|
33
|
+
Let's assume that we have following model and "service" classes in the app.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class User < ApplicationRecord
|
37
|
+
include GenericJob::Async
|
38
|
+
|
39
|
+
validates :full_name, presence: true
|
40
|
+
|
41
|
+
def self.fetch_twitter_for_all! opts = {}
|
42
|
+
find_each { |user| user.fetch_twitter! opts }
|
43
|
+
end
|
44
|
+
|
45
|
+
# This method stays in the model for the sake of convenience.
|
46
|
+
# Remember that the optimal way when dealing with external services like Twitter API
|
47
|
+
# is to call methods like this *** in the background ***
|
48
|
+
# to avoid hanging up other application requests
|
49
|
+
def fetch_twitter! opts = {}
|
50
|
+
TwitterFetcher.new(resource: self).fetch(
|
51
|
+
skip_email: opts[:only_name]
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class TwitterFetcher
|
57
|
+
include GenericJob::Async
|
58
|
+
|
59
|
+
def self.fetch_for_all class_name = 'User', ids = [], opts = {}
|
60
|
+
klass = class_name.constantize
|
61
|
+
records = ids.empty? ? klass.all : klass.find(ids)
|
62
|
+
records.each { |record| new(resource: record).fetch opts }
|
63
|
+
end
|
64
|
+
|
65
|
+
def initialize resource: nil, resource_id: nil, resource_class: 'User'
|
66
|
+
@resource = resource
|
67
|
+
@resource ||= resource_class.constantize.find resource_id
|
68
|
+
end
|
69
|
+
|
70
|
+
def fetch opts = {}
|
71
|
+
fetch_name
|
72
|
+
fetch_email unless opts[:skip_email]
|
73
|
+
@resource.save!
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def fetch_name
|
79
|
+
# implement!
|
80
|
+
end
|
81
|
+
|
82
|
+
def fetch_email
|
83
|
+
# implement!
|
84
|
+
end
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
All you need to do to be able to run methods in the background is to include `GenericJob::Async` in both classes.
|
89
|
+
|
90
|
+
Now you can do things like these:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
# this code calls the "fetch_twitter!" method in the background for the 1st User
|
94
|
+
# in the DB with the all args passed. Before that the job is enqueued on the "low" queue
|
95
|
+
User.first.async(queue: 'low')
|
96
|
+
.fetch_twitter! only_name: true
|
97
|
+
|
98
|
+
# this line calls "fetch_twitter_for_all!" class method on a queuing backend
|
99
|
+
# with the passed args. The job is enqueued on the 'default' queue
|
100
|
+
User.async.fetch_twitter_for_all! only_name: true
|
101
|
+
|
102
|
+
# this code initializes an object in the background and then calls
|
103
|
+
# the "fetch" method. Given arguments are passed to the constructor
|
104
|
+
# and the "fetch" method accordingly
|
105
|
+
TwitterFetcher.async(queue: :default)
|
106
|
+
.new(resource_id: 101)
|
107
|
+
.fetch skip_email: true
|
108
|
+
|
109
|
+
# this line calls "fetch_for_all" class method on a queuing backend
|
110
|
+
# with the passed args through the "default" queue
|
111
|
+
TwitterFetcher.async.fetch_for_all 'User', [12, 13], skip_email: true
|
112
|
+
```
|
113
|
+
|
114
|
+
As you can see on the preceding examples - the usage of the `async` method is essential. This method calls `ActiveJob::Core`'s [**set** class method](http://api.rubyonrails.org/v5.0/classes/ActiveJob/Core/ClassMethods.html#method-i-set) under the hood, so you can pass to `async` method all the options that `set` supports. And remember - this is still an `ActiveJob`, so passed method attributes must have serialized type.
|
115
|
+
|
116
|
+
For more examples look inside the `test` directory.
|
117
|
+
Both exemplary classes above are taken from the dummy test app inside.
|
118
|
+
|
119
|
+
## 📥 Installation
|
6
120
|
|
7
|
-
## Installation
|
8
121
|
Add this line to your application's Gemfile:
|
9
122
|
|
10
123
|
```ruby
|
@@ -21,8 +134,14 @@ Or install it yourself as:
|
|
21
134
|
$ gem install generic_job
|
22
135
|
```
|
23
136
|
|
24
|
-
##
|
25
|
-
Contribution directions go here.
|
137
|
+
## 📄 License
|
26
138
|
|
27
|
-
## License
|
28
139
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
140
|
+
|
141
|
+
## 👨🏭 Author
|
142
|
+
|
143
|
+
Zbigniew Humeniuk from [Art of Code](http://artofcode.co)
|
144
|
+
|
145
|
+
## 👀 See also
|
146
|
+
|
147
|
+
If you want to make your life easier in the other areas of the web app development as well, I strongly recommend you to take a look at my other project called [Loco framework](https://github.com/locoframework) 🙂. It is even more powerful and makes a front-end <-> back-end communication a breeze (among other things).
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: generic_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zbigniew Humeniuk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '5.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7.0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,21 +29,83 @@ dependencies:
|
|
29
29
|
version: '5.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7.0'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: listen
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
39
|
+
version: 3.1.5
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '3.2'
|
40
43
|
type: :development
|
41
44
|
prerelease: false
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
44
47
|
- - ">="
|
45
48
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
49
|
+
version: 3.1.5
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '3.2'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: overcommit
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - '='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.49.1
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - '='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.49.1
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rubocop
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.74.0
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 0.74.0
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rubocop-rails
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 2.3.1
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 2.3.1
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: sqlite3
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.4.1
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 1.4.1
|
47
109
|
description: Run instance and class methods in the background jobs with ease.
|
48
110
|
email:
|
49
111
|
- hello@artofcode.co
|
@@ -58,7 +120,6 @@ files:
|
|
58
120
|
- lib/generic_job/async.rb
|
59
121
|
- lib/generic_job/perform.rb
|
60
122
|
- lib/generic_job/stub.rb
|
61
|
-
- lib/tasks/generic_job_tasks.rake
|
62
123
|
homepage: https://artofcode.co
|
63
124
|
licenses:
|
64
125
|
- MIT
|
@@ -78,8 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
139
|
- !ruby/object:Gem::Version
|
79
140
|
version: '0'
|
80
141
|
requirements: []
|
81
|
-
|
82
|
-
rubygems_version: 2.7.6
|
142
|
+
rubygems_version: 3.0.3
|
83
143
|
signing_key:
|
84
144
|
specification_version: 4
|
85
145
|
summary: Higher level abstraction on the top of ActiveJob.
|