nifty_services 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +266 -25
- data/lib/nifty_services/base_action_service.rb +13 -34
- data/lib/nifty_services/base_create_service.rb +38 -24
- data/lib/nifty_services/base_crud_service.rb +19 -12
- data/lib/nifty_services/base_delete_service.rb +17 -10
- data/lib/nifty_services/base_service.rb +20 -16
- data/lib/nifty_services/base_update_service.rb +33 -22
- data/lib/nifty_services/configuration.rb +2 -2
- data/lib/nifty_services/version.rb +1 -1
- data/nifty_services.gemspec +5 -6
- metadata +20 -22
- data/daily_news.log +0 -7
- data/test.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b51ddb57c9b14189952188821a22c36ea9b7c35
|
4
|
+
data.tar.gz: 1bf6174e4899e88817ea3ec77db991d2cf249cdc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b098ca14f8ad2789d6dc7e0fc4026452a79d30697f241d31d6b74dfb7397e50b89df681e7648648550e66b66e2f2ec52605dc96359a741ead9c4ebf456645024
|
7
|
+
data.tar.gz: ee3633820cc0690f469acd67a74c3ff63d6f86d19f08f92b4b09d26296cc448cfb003159295485ab5c4a47532defc8ca7072c302e523ee2cdbfcd7a69db251c8
|
data/README.md
CHANGED
@@ -4,18 +4,19 @@
|
|
4
4
|
|
5
5
|
Nifty Services comes to solve your Ruby applications(*including but not limited to* Rails, Grape, Sinatra, and plain Ruby) code mess with **simplicity in mind**!
|
6
6
|
|
7
|
-
NiftyServices
|
7
|
+
NiftyServices provides a very nifty, simple & clear API to **organize and reuse** your application **domain logic in plain Ruby Services Objects** turning your codebase in a very extensible, standardized and reusable components.
|
8
8
|
|
9
9
|
**Most important:** You and your team win what I consider the best benefit when using Nifty Services: **Easily and scalable maintained code.**
|
10
10
|
Believe me, you'll fall in :heart_eyes: with this small piece of code, keep reading!
|
11
11
|
|
12
|
-
This gem was designed and conventioned to be used specially with **Web API applications**, but this is just a convention, you can use it
|
12
|
+
This gem was designed and conventioned to be used specially with **Web API applications**, but this is just a convention, you can use it even with [shoes (for desktop apps)](https://github.com/shoes/shoes) applications if you want, for example.
|
13
13
|
|
14
14
|
#### :book: I know, this README is very huge
|
15
15
|
|
16
16
|
As you can see, this README needs some time to be full read, but is very difficulty to explain all things, concepts and philosophy of this gem without writing a lot, we can't escape this :(
|
17
17
|
|
18
|
-
But remember one thing: This is a **tecnical documentation**, not a blog post, I'm pretty sure you can take
|
18
|
+
But remember one thing: This is a **tecnical documentation**, not a blog post, I'm pretty sure you can take about 30 minutes + some cups of :coffee: to better understand all NiftyServices can
|
19
|
+
do for you and your project. Good reading, and if you have some question, [please let me know](issues/new).
|
19
20
|
|
20
21
|
---
|
21
22
|
|
@@ -60,6 +61,11 @@ But remember one thing: This is a **tecnical documentation**, not a blog post, I
|
|
60
61
|
* [Web Frameworks integration](#web-frameworks-integrations)
|
61
62
|
* [Ruby on Rails](#frameworks-rails)
|
62
63
|
* [Grape/Sinatra/Rack](#frameworks-rack)
|
64
|
+
* [ Basic Services class Markups](#pray-basic-service-markups-raised_hands)
|
65
|
+
* [BaseCreateService Basic Markup](#basecreateservice-basic-markup)
|
66
|
+
* [BaseUpdateService Basic Markup](#baseupdateservice-basic-markup)
|
67
|
+
* [BaseDeleteService Basic Markup](#basedeleteservice-basic-markup)
|
68
|
+
* [BaseActionService Basic Markup](#baseactionservice-basic-markup)
|
63
69
|
* [CLI Generators](#cli-generators)
|
64
70
|
* [Roadmap](#roadmap)
|
65
71
|
* [Development](#computer-development)
|
@@ -99,7 +105,7 @@ Now you know the basic concepts and philosophy of `NiftyServices`, lets start wo
|
|
99
105
|
Add this line to your application's Gemfile:
|
100
106
|
|
101
107
|
```ruby
|
102
|
-
gem 'nifty_services'
|
108
|
+
gem 'nifty_services', '~> 0.0.5'
|
103
109
|
```
|
104
110
|
|
105
111
|
And then execute:
|
@@ -139,7 +145,7 @@ class SemanticServiceName < NiftyServices::BaseService
|
|
139
145
|
|
140
146
|
return not_found_error!('errors.message_key') if another_condition
|
141
147
|
|
142
|
-
return unprocessable_entity_error('errors.message_key') if other_condition
|
148
|
+
return unprocessable_entity_error!('errors.message_key') if other_condition
|
143
149
|
|
144
150
|
# ok, this service can be executed
|
145
151
|
return true
|
@@ -208,21 +214,31 @@ class DailyNewsMailSendService < NiftyServices::BaseService
|
|
208
214
|
|
209
215
|
unless @user.abble_to_receive_daily_news_mail?
|
210
216
|
# returns false
|
211
|
-
return forbidden_error!('users.
|
217
|
+
return forbidden_error!('users.already_received_daily_news_mail')
|
212
218
|
end
|
213
219
|
|
214
220
|
return true
|
215
221
|
end
|
222
|
+
|
216
223
|
def send_mail_to_user
|
217
224
|
# just to fake, a real implementation could be something like:
|
218
225
|
# @user.send_daily_news_mail!
|
219
226
|
return true
|
220
227
|
end
|
221
|
-
|
228
|
+
|
222
229
|
def valid_user?
|
223
230
|
# check if object is valid and is a User class type
|
224
231
|
valid_object?(@user, User)
|
225
232
|
end
|
233
|
+
|
234
|
+
# you can use `default_options` method to add default { keys => values } to @options
|
235
|
+
# so you can use the option_enabled?(key) to verify if option is enabled
|
236
|
+
# or option_disabled?(key) to verify is option is disabled
|
237
|
+
# This default values can be override when creating new instance of Service, eg:
|
238
|
+
# DailyNewsMailSendService.new(User.last, validate_api_key: false)
|
239
|
+
def default_options
|
240
|
+
{ validate_api_key: true }
|
241
|
+
end
|
226
242
|
end
|
227
243
|
|
228
244
|
class User < Struct.new(:name, :email)
|
@@ -268,7 +284,7 @@ W, [2016-07-15T17:12:10.955186 #756] WARN -- : Something went wrong
|
|
268
284
|
|
269
285
|
E, [2016-07-15T17:12:11.019645 #756] ERROR -- : Error sending email to user. See details below :(
|
270
286
|
|
271
|
-
E, [2016-07-15T17:12:11.019838 #756] ERROR -- : ["User
|
287
|
+
E, [2016-07-15T17:12:11.019838 #756] ERROR -- : ["User has already received daily news mail today"]
|
272
288
|
|
273
289
|
I, [2016-07-15T17:12:11.020073 #756] INFO -- : Routine ended at: 2016-07-15 17:12:11 -0300
|
274
290
|
|
@@ -387,7 +403,7 @@ error!(409, :conflict_error, reason: 'unkown')
|
|
387
403
|
|
388
404
|
#### Custom error response methods
|
389
405
|
|
390
|
-
But you can always add new convenience errors methods via API, this way you
|
406
|
+
But you can always add new convenience errors methods via API, this way you will have more expressivity and sintax sugar:
|
391
407
|
|
392
408
|
```ruby
|
393
409
|
## API
|
@@ -397,7 +413,7 @@ NiftyServices.add_response_error_method(status, status_code)
|
|
397
413
|
|
398
414
|
NiftyServices.add_response_error_method(:conflict, 409)
|
399
415
|
|
400
|
-
## now you
|
416
|
+
## now you have the methods:
|
401
417
|
|
402
418
|
## conflict_error(:conflict_error)
|
403
419
|
## conflit_error!(:conflict_error)
|
@@ -409,7 +425,7 @@ NiftyServices.add_response_error_method(:conflict, 409)
|
|
409
425
|
|
410
426
|
So, until now we saw how to use `NiftyServices::BaseService` to create generic services to couple specific domain logic for actions, this is very usefull, but things get a lot better when you're working with **CRUD** actions for your api.
|
411
427
|
|
412
|
-
|
428
|
+
Follow an example of **Create, Update and Delete** CRUD services for `Post` resource:
|
413
429
|
|
414
430
|
## :white_check_mark: CRUD: Create
|
415
431
|
|
@@ -428,13 +444,14 @@ class PostCreateService < NiftyServices::BaseCreateService
|
|
428
444
|
|
429
445
|
WHITELIST_ATTRIBUTES = [:title, :content]
|
430
446
|
|
431
|
-
def
|
447
|
+
def record_attributes_whitelist
|
432
448
|
WHITELIST_ATTRIBUTES
|
433
449
|
end
|
434
450
|
|
435
|
-
|
436
|
-
|
437
|
-
|
451
|
+
# use custom scope to create the record
|
452
|
+
# scope returned below must respond_to :build instance method
|
453
|
+
def build_record_scope
|
454
|
+
@user.posts
|
438
455
|
end
|
439
456
|
|
440
457
|
# this key is used for I18n translations
|
@@ -445,9 +462,9 @@ class PostCreateService < NiftyServices::BaseCreateService
|
|
445
462
|
def user_can_create_record?
|
446
463
|
# (here you can do any kind of validation, eg:)
|
447
464
|
# check if user is trying to recreate a recent resource
|
448
|
-
# this will return false if user
|
465
|
+
# this will return false if user has already created a post with
|
449
466
|
# this title in the last 30 seconds (usefull to ban bots)
|
450
|
-
@user.posts.exists(title:
|
467
|
+
@user.posts.exists(title: record_allowed_attributes[:title], created_at: "NOW() - interval(30 seconds)")
|
451
468
|
end
|
452
469
|
end
|
453
470
|
|
@@ -534,7 +551,7 @@ class PostUpdateService < NiftyServices::BaseUpdateService
|
|
534
551
|
|
535
552
|
WHITELIST_ATTRIBUTES = [:title, :content]
|
536
553
|
|
537
|
-
def
|
554
|
+
def record_allowed_attributes
|
538
555
|
WHITELIST_ATTRIBUTES
|
539
556
|
end
|
540
557
|
|
@@ -817,9 +834,9 @@ NiftyServices::BaseCreateService.class_eval do
|
|
817
834
|
end
|
818
835
|
end
|
819
836
|
|
820
|
-
# This register
|
837
|
+
# This register a callback for ALL services who inherit from `NiftyServices::BaseCreateService`
|
821
838
|
# In other words: Every and all records created in my application will be tracked
|
822
|
-
# I can believe that
|
839
|
+
# I can believe that is easy like this, I need a beer right now!
|
823
840
|
NiftyServices::BaseCreateService.register_callback(:after_success, :create_origin_for_record) do
|
824
841
|
create_origin(@record, @options)
|
825
842
|
end
|
@@ -859,7 +876,7 @@ end
|
|
859
876
|
|
860
877
|
### Rails <a name="frameworks-rails"></a>
|
861
878
|
|
862
|
-
You need a very minimal setup to integrate with
|
879
|
+
You need a very minimal setup to integrate with your existing or new Rails application. I prefer to put my services files inside the `lib/services` folder, cause this allow better namespacing configuration over `app/services`, but this is up to you to decide.
|
863
880
|
|
864
881
|
First thing to do is add `lib/` folder in `autoload` path, place the following in your `config/application.rb`
|
865
882
|
|
@@ -875,13 +892,13 @@ Second, create `lib/services` directory:
|
|
875
892
|
`$ mkdir -p lib/services/v1/users`
|
876
893
|
|
877
894
|
Next, configure:
|
878
|
-
**Note**: See Configurations section below to see all available configs
|
879
895
|
|
880
896
|
```ruby
|
881
897
|
NiftyServices.configure do |config|
|
882
898
|
config.user_class = User
|
883
899
|
end
|
884
900
|
```
|
901
|
+
**Note**: See [Configurations](#construction-configuration-construction) section to see all available configs
|
885
902
|
|
886
903
|
Create your first service:
|
887
904
|
|
@@ -909,7 +926,7 @@ class UsersController < BaseController
|
|
909
926
|
end
|
910
927
|
```
|
911
928
|
|
912
|
-
This can be even better if you move response code to
|
929
|
+
This can be even better if you move response code to a helper:
|
913
930
|
|
914
931
|
```ruby
|
915
932
|
# helpers/users_helper.rb
|
@@ -920,7 +937,7 @@ module UsersHelper
|
|
920
937
|
generic_response_for_service(service, success_response)
|
921
938
|
end
|
922
939
|
|
923
|
-
# THIS IS GREAT, you can use this method to
|
940
|
+
# THIS IS GREAT, you can use this method to standardize ALL of your
|
924
941
|
# endpoints responses, THIS IS SO FUCKING COOL!
|
925
942
|
def generic_response_for_service(service, success_response)
|
926
943
|
default_response = {
|
@@ -978,6 +995,230 @@ NiftyServices - Sinatra Sample
|
|
978
995
|
|
979
996
|
---
|
980
997
|
|
998
|
+
## :pray: Basic Service Markups :raised_hands:
|
999
|
+
|
1000
|
+
Here, for your convenience and sanity all basic service structures for reference when you start a brand new Service.
|
1001
|
+
Most of time, the best way is to copy all content from each service described below and change according to your needs.
|
1002
|
+
|
1003
|
+
### BaseCreateService Basic Markup
|
1004
|
+
|
1005
|
+
```ruby
|
1006
|
+
class SomeCreateService < NiftyServices::BaseCreateService
|
1007
|
+
|
1008
|
+
# [Required]
|
1009
|
+
# remember that inside the Service you always can use
|
1010
|
+
# @record variable to access current record
|
1011
|
+
# and from outside (service instance):
|
1012
|
+
# service.record or service.record_type
|
1013
|
+
# eg:
|
1014
|
+
# record_type BlogPost
|
1015
|
+
# service.record # BlogPost.new(...)
|
1016
|
+
# service.blog_post # BlogPost.new(...)
|
1017
|
+
# service.record == service.blog_post # true
|
1018
|
+
# alias_name can be used to create a custom alias name
|
1019
|
+
# eg:
|
1020
|
+
# record_type BlogPost, alias_name: :post
|
1021
|
+
# service.record # BlogPost.new(...)
|
1022
|
+
# service.post # BlogPost.new(...)
|
1023
|
+
# service.record == service.post # true
|
1024
|
+
|
1025
|
+
record_type RecordType, alias_name: :my_custom_alias_name
|
1026
|
+
|
1027
|
+
private
|
1028
|
+
# [Required]
|
1029
|
+
# Always validate if @user can create the current record_type
|
1030
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1031
|
+
def user_can_create_record?
|
1032
|
+
return forbidden_error!('errors.some_error') if (some_validation)
|
1033
|
+
|
1034
|
+
return bad_request_error!('errors.some_other_error') if (another_validation)
|
1035
|
+
|
1036
|
+
# remember to return true after all validations
|
1037
|
+
# if you don't return true Service will not be able to create the record
|
1038
|
+
return true
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
# [Optional]
|
1042
|
+
# method called when save_error method call raises an exception
|
1043
|
+
# this ocurr for example with ActiveRecord objects
|
1044
|
+
# default: unprocessable_entity_error!(error)
|
1045
|
+
def on_save_record_error(error)
|
1046
|
+
logger.error(error)
|
1047
|
+
if error.is_a?(ActiveRecord::RecordNotUnique)
|
1048
|
+
return unprocessable_entity_error!(%s(posts.duplicate_record))
|
1049
|
+
end
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
# [Optional]
|
1053
|
+
# determine wheter user will be validate as valid object before
|
1054
|
+
# record creation
|
1055
|
+
# (default: true)
|
1056
|
+
def validate_user?
|
1057
|
+
return true
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
# [Optional]
|
1061
|
+
# custom scope for record, eg: @user.posts
|
1062
|
+
# default is nil
|
1063
|
+
def build_record_scope
|
1064
|
+
end
|
1065
|
+
end
|
1066
|
+
```
|
1067
|
+
|
1068
|
+
### BaseUpdateService Basic Markup
|
1069
|
+
|
1070
|
+
```ruby
|
1071
|
+
class SomeUpdateService < NiftyServices::BaseUpdateService
|
1072
|
+
|
1073
|
+
# [Required]
|
1074
|
+
record_type RecordType, alias_name: :custom_alias_name
|
1075
|
+
|
1076
|
+
WHITELIST_ATTRIBUTES = [
|
1077
|
+
:safe_attribute_1,
|
1078
|
+
:safe_attribute_2,
|
1079
|
+
]
|
1080
|
+
|
1081
|
+
private
|
1082
|
+
# [Required]
|
1083
|
+
# When a new instance of Service is created, the @options variables receive some
|
1084
|
+
# values, eg: { user: { email: "...", name: "...."} }
|
1085
|
+
# use record_attributes_hash to tell the Service from where to pull theses values
|
1086
|
+
# eg: @options.fetch(:user, {})
|
1087
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1088
|
+
def record_attributes_hash
|
1089
|
+
@options.fetch(options_key, {})
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
# [Required]
|
1093
|
+
# whitelisted attributes (must be an Array) which can be updated by this Service
|
1094
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1095
|
+
def record_attributes_whitelist
|
1096
|
+
WHITELIST_ATTRIBUTES
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
# [required]
|
1100
|
+
# This is a VERY IMPORTANT point of attention
|
1101
|
+
# always verify if @user has permissions to update the current @record object
|
1102
|
+
# Hint: if @record respond_to `user_can_update?(user)` you can remove this
|
1103
|
+
# method and do the validation inside `user_can_update(user)` method in @record
|
1104
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1105
|
+
def user_can_update_record?
|
1106
|
+
@record.user_id == @user.id
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
|
1110
|
+
# [Optional]
|
1111
|
+
# This is the default implementation of update record, you may overwrite it
|
1112
|
+
# to to custom updates (MOST OF TIME YOU DONT NEED TO DO THIS)
|
1113
|
+
# only change this if you know what you are really doing
|
1114
|
+
def update_record
|
1115
|
+
@record.class.send(:update, @record.id, record_allowed_attributes)
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
|
1119
|
+
# [optional]
|
1120
|
+
# Any callback is optional, this is just a example
|
1121
|
+
def after_success
|
1122
|
+
if changed?
|
1123
|
+
logger.info 'Successfully update record ID %s' % @record.id
|
1124
|
+
logger.info 'Changed attributes are %s' % changed_attributes
|
1125
|
+
end
|
1126
|
+
end
|
1127
|
+
end
|
1128
|
+
```
|
1129
|
+
|
1130
|
+
---
|
1131
|
+
|
1132
|
+
### BaseDeleteService Basic Markup
|
1133
|
+
|
1134
|
+
```ruby
|
1135
|
+
class SomeDeleteService < NiftyServices::BaseDeleteService
|
1136
|
+
|
1137
|
+
# [Required]
|
1138
|
+
record_type RecordType, alias_name: :custom_alias_name
|
1139
|
+
|
1140
|
+
private
|
1141
|
+
|
1142
|
+
# [Required]
|
1143
|
+
# This is a VERY IMPORTANT point of attention
|
1144
|
+
# always verify if @user has permissions to delete the current @record object
|
1145
|
+
# Hint: if @record respond_to `user_can_delete?(user)` you can remove this
|
1146
|
+
# method and do the validation inside `user_can_delete(user)` method in @record
|
1147
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1148
|
+
|
1149
|
+
def user_can_delete_record?
|
1150
|
+
@record.user_id == @user.id
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
# [optional]
|
1154
|
+
# Any callback is optional, this is just a example
|
1155
|
+
def after_success
|
1156
|
+
logger.info('Successfully Deleted resource ID %s' % @record.id)
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
# [Optional]
|
1160
|
+
# This is the default implementation of delete record, you may overwrite it
|
1161
|
+
# to do custom delete (MOST OF TIME YOU DONT NEED TO DO THIS)
|
1162
|
+
# only change this if you know what you are really doing
|
1163
|
+
def destroy_record
|
1164
|
+
@record.try(:destroy) || @record.try(:delete)
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
```
|
1170
|
+
|
1171
|
+
### BaseActionService Basic Markup
|
1172
|
+
|
1173
|
+
```ruby
|
1174
|
+
class SomeCustomActionService < NiftyServices::BaseActionService
|
1175
|
+
|
1176
|
+
# [required]
|
1177
|
+
# this is the action identifier used internally
|
1178
|
+
# and to generate error messages
|
1179
|
+
# see: invalid_action_error_key method
|
1180
|
+
action_name :custom_action_name
|
1181
|
+
|
1182
|
+
private
|
1183
|
+
# [Required]
|
1184
|
+
# Always validate if Service can execute the action
|
1185
|
+
# This method MUST return a boolean value indicating if Service can or not
|
1186
|
+
# run the method `execute_service_action`
|
1187
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1188
|
+
def user_can_execute_action?
|
1189
|
+
# do some specific validation here, you can return errors such:
|
1190
|
+
# return not_found_error!(%(users.invalid_user)) # returns false and avoid execution
|
1191
|
+
return true
|
1192
|
+
end
|
1193
|
+
|
1194
|
+
# [Required]
|
1195
|
+
# The core function of BaseActionServices
|
1196
|
+
# This method is called when all validations passes, so here you can put
|
1197
|
+
# all logic for Service (eg: send mails, clear logs, any kind of action you want)
|
1198
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1199
|
+
def execute_service_action
|
1200
|
+
# (do some complex stuff)
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
# You dont need to overwrite this method, just `record_error_key`
|
1204
|
+
# But it's important you know how final message key will be created
|
1205
|
+
# using the pattern below
|
1206
|
+
def invalid_action_error_key
|
1207
|
+
"#{record_error_key}.cant_execute_#{action_name}"
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
# [Required]
|
1211
|
+
# Key used to created the error messages for this Service
|
1212
|
+
# If this method is not implemented a NotImplementedError exception will be raised
|
1213
|
+
def record_error_key
|
1214
|
+
:users
|
1215
|
+
end
|
1216
|
+
end
|
1217
|
+
```
|
1218
|
+
|
1219
|
+
|
1220
|
+
---
|
1221
|
+
|
981
1222
|
## Full Public API methods list
|
982
1223
|
|
983
1224
|
You can use any of the methods above with your `services instances`:
|
@@ -1016,7 +1257,7 @@ Currently NiftyServices don't have CLI(command line interface) generators, but i
|
|
1016
1257
|
|
1017
1258
|
- :white_medium_small_square: Remove ActiveSupport dependency
|
1018
1259
|
- :white_medium_small_square: Create CLI Generators
|
1019
|
-
- :white_medium_small_square:
|
1260
|
+
- :white_medium_small_square: Beter documentation for `BaseActionService`
|
1020
1261
|
- :white_medium_small_square: Write Sample Applications
|
1021
1262
|
- :white_medium_small_square: Write better tests for all `Crud Services`
|
1022
1263
|
- :white_medium_small_square: Write better tests for `BaseActionServices`
|
@@ -8,12 +8,12 @@ module NiftyServices
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def execute
|
11
|
-
|
12
|
-
|
11
|
+
execute_action do
|
12
|
+
with_before_and_after_callbacks(:action) do
|
13
|
+
# here user can
|
14
|
+
execute_service_action
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
if success_runned_action?
|
16
|
+
if valid?
|
17
17
|
success_response
|
18
18
|
else
|
19
19
|
errors = action_errors
|
@@ -21,8 +21,6 @@ module NiftyServices
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
25
|
-
success?
|
26
24
|
end
|
27
25
|
|
28
26
|
private
|
@@ -30,50 +28,31 @@ module NiftyServices
|
|
30
28
|
[]
|
31
29
|
end
|
32
30
|
|
33
|
-
def
|
34
|
-
unless
|
35
|
-
return
|
36
|
-
end
|
37
|
-
|
38
|
-
unless valid_user?
|
39
|
-
return not_found_error!('users.not_found')
|
40
|
-
end
|
41
|
-
|
42
|
-
unless can_execute?
|
43
|
-
if @errors.blank?
|
44
|
-
return unprocessable_entity_error!("#{record_error_key}.user_cant_execute_#{action_name}")
|
45
|
-
else
|
46
|
-
return false
|
47
|
-
end
|
31
|
+
def can_execute?
|
32
|
+
unless user_can_execute_action?
|
33
|
+
return (valid? ? unprocessable_entity_error!(invalid_action_error_key) : false)
|
48
34
|
end
|
49
35
|
|
50
36
|
return true
|
51
37
|
end
|
52
38
|
|
53
|
-
def
|
54
|
-
|
55
|
-
return false unless valid_record?
|
56
|
-
|
57
|
-
user_can_execute_action?
|
58
|
-
end
|
59
|
-
|
60
|
-
def success_runned_action?
|
61
|
-
not_implemented_exception(__method__)
|
39
|
+
def invalid_action_error_key
|
40
|
+
"#{record_error_key}.cant_execute_#{action_name}"
|
62
41
|
end
|
63
42
|
|
64
43
|
def user_can_execute_action?
|
65
44
|
not_implemented_exception(__method__)
|
66
45
|
end
|
67
46
|
|
68
|
-
def
|
47
|
+
def execute_service_action
|
69
48
|
not_implemented_exception(__method__)
|
70
49
|
end
|
71
50
|
|
72
|
-
def
|
51
|
+
def record_error_key
|
73
52
|
not_implemented_exception(__method__)
|
74
53
|
end
|
75
54
|
|
76
|
-
def
|
55
|
+
def action_name
|
77
56
|
not_implemented_exception(__method__)
|
78
57
|
end
|
79
58
|
end
|
@@ -25,7 +25,16 @@ module NiftyServices
|
|
25
25
|
|
26
26
|
private
|
27
27
|
def save_record
|
28
|
-
|
28
|
+
begin
|
29
|
+
@record.save
|
30
|
+
rescue => e
|
31
|
+
on_save_record_error(e)
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_save_record_error(error)
|
37
|
+
return unprocessable_entity_error!(error)
|
29
38
|
end
|
30
39
|
|
31
40
|
def create_error_response(record)
|
@@ -40,21 +49,20 @@ module NiftyServices
|
|
40
49
|
success_created_response
|
41
50
|
end
|
42
51
|
|
43
|
-
def after_success
|
44
|
-
end
|
45
|
-
|
46
52
|
def build_record
|
47
|
-
|
48
|
-
|
49
|
-
if record_type.present? && _record_params.present?
|
50
|
-
return build_from_record_type(_record_params)
|
53
|
+
if record_type.present?
|
54
|
+
return build_from_record_type(record_allowed_attributes)
|
51
55
|
end
|
52
56
|
|
53
57
|
return not_implemented_exception(__method__)
|
54
58
|
end
|
55
59
|
|
56
|
-
def build_from_record_type(
|
57
|
-
|
60
|
+
def build_from_record_type(params)
|
61
|
+
if !build_record_scope.nil? && build_record_scope.respond_to?(:build)
|
62
|
+
return build_record_scope.send(:build, params)
|
63
|
+
end
|
64
|
+
|
65
|
+
record_type.send(:new, params)
|
58
66
|
end
|
59
67
|
|
60
68
|
def can_execute?
|
@@ -62,25 +70,27 @@ module NiftyServices
|
|
62
70
|
return forbidden_error!(%s(users.ip_temporarily_blocked))
|
63
71
|
end
|
64
72
|
|
65
|
-
|
66
|
-
return not_found_error!(
|
73
|
+
if validate_user? && !valid_user?
|
74
|
+
return not_found_error!(invalid_user_error_key)
|
67
75
|
end
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
|
80
|
+
def can_create_record?
|
81
|
+
unless user_can_create_record?
|
82
|
+
return (valid? ? forbidden_error!(user_cant_create_error_key) : false)
|
75
83
|
end
|
76
84
|
|
77
|
-
return
|
85
|
+
return true
|
78
86
|
end
|
79
87
|
|
80
|
-
def
|
81
|
-
|
88
|
+
def user_can_create_record?
|
89
|
+
not_implemented_exception(__method__)
|
90
|
+
end
|
82
91
|
|
83
|
-
|
92
|
+
def can_execute_action?
|
93
|
+
return can_create_record?
|
84
94
|
end
|
85
95
|
|
86
96
|
def can_create_with_ip?
|
@@ -92,8 +102,12 @@ module NiftyServices
|
|
92
102
|
false
|
93
103
|
end
|
94
104
|
|
95
|
-
def
|
96
|
-
|
105
|
+
def build_record_scope
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def user_cant_create_error_key
|
110
|
+
"#{record_error_key}.user_cant_create"
|
97
111
|
end
|
98
112
|
end
|
99
113
|
end
|
@@ -37,28 +37,31 @@ module NiftyServices
|
|
37
37
|
super(options)
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
|
40
|
+
def changed_attributes
|
41
|
+
[]
|
42
|
+
end
|
43
|
+
|
44
|
+
def changed?
|
45
|
+
changed_attributes.any?
|
42
46
|
end
|
43
47
|
|
44
48
|
def record_type
|
45
49
|
not_implemented_exception(__method__)
|
46
50
|
end
|
47
51
|
|
48
|
-
def
|
52
|
+
def record_attributes_hash
|
49
53
|
not_implemented_exception(__method__)
|
50
54
|
end
|
51
55
|
|
52
|
-
def
|
56
|
+
def record_attributes_whitelist
|
53
57
|
not_implemented_exception(__method__)
|
54
58
|
end
|
55
59
|
|
56
|
-
def
|
57
|
-
filter_hash(
|
60
|
+
def record_allowed_attributes
|
61
|
+
filter_hash(record_attributes_hash, record_attributes_whitelist)
|
58
62
|
end
|
59
63
|
|
60
|
-
alias :
|
61
|
-
alias :record_safe_params :record_allowed_params
|
64
|
+
alias :record_safe_attributes :record_allowed_attributes
|
62
65
|
|
63
66
|
private
|
64
67
|
def array_values_from_hash(options, key, root = nil)
|
@@ -77,16 +80,20 @@ module NiftyServices
|
|
77
80
|
array_values_from_string(values)
|
78
81
|
end
|
79
82
|
|
83
|
+
def invalid_user_error_key
|
84
|
+
%s(users.not_found)
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_user?
|
88
|
+
true
|
89
|
+
end
|
90
|
+
|
80
91
|
alias :array_values_from_params :array_values_from_hash
|
81
92
|
|
82
93
|
def array_values_from_string(string)
|
83
94
|
string.to_s.split(/\,/).map(&:squish)
|
84
95
|
end
|
85
96
|
|
86
|
-
def record_params
|
87
|
-
not_implemented_exception(__method__)
|
88
|
-
end
|
89
|
-
|
90
97
|
def record_error_key
|
91
98
|
record_type.to_s.pluralize.underscore
|
92
99
|
end
|
@@ -20,31 +20,38 @@ module NiftyServices
|
|
20
20
|
@record.try(:destroy) || @record.try(:delete)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
23
|
+
def can_execute?
|
24
24
|
unless valid_record?
|
25
25
|
return not_found_error!("#{record_error_key}.not_found")
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
return not_found_error!(
|
28
|
+
if validate_user? && !valid_user?
|
29
|
+
return not_found_error!(invalid_user_error_key)
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
|
35
|
+
def can_delete_record?
|
36
|
+
unless user_can_delete_record?
|
37
|
+
return (valid? ? forbidden_error!(user_can_delete_error_key) : false)
|
34
38
|
end
|
35
39
|
|
36
40
|
return true
|
37
41
|
end
|
38
42
|
|
39
|
-
def
|
40
|
-
return
|
41
|
-
return false unless valid_record?
|
42
|
-
|
43
|
-
return user_can_delete_record?
|
43
|
+
def can_execute_action?
|
44
|
+
return can_delete_record?
|
44
45
|
end
|
45
46
|
|
46
47
|
def user_can_delete_record?
|
48
|
+
return not_implemented_exception(__method__) unless @record.respond_to?(:user_can_delete?)
|
49
|
+
|
47
50
|
@record.user_can_delete?(@user)
|
48
51
|
end
|
52
|
+
|
53
|
+
def user_cant_delete_error_key
|
54
|
+
"#{record_error_key}.user_cant_delete"
|
55
|
+
end
|
49
56
|
end
|
50
57
|
end
|
@@ -26,7 +26,7 @@ module NiftyServices
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def initialize(options = {}, initial_response_status = 400)
|
29
|
-
@options = options.to_options!
|
29
|
+
@options = default_options.to_options!.merge(options).to_options!
|
30
30
|
@errors = []
|
31
31
|
@logger = options[:logger] || default_logger
|
32
32
|
@executed = false
|
@@ -36,6 +36,10 @@ module NiftyServices
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
def execute
|
40
|
+
not_implemented_exception(__method__)
|
41
|
+
end
|
42
|
+
|
39
43
|
def valid?
|
40
44
|
return @errors.blank?
|
41
45
|
end
|
@@ -52,14 +56,6 @@ module NiftyServices
|
|
52
56
|
@response_status ||= :bad_request
|
53
57
|
end
|
54
58
|
|
55
|
-
def changed_attributes
|
56
|
-
[]
|
57
|
-
end
|
58
|
-
|
59
|
-
def changed?
|
60
|
-
changed_attributes.any?
|
61
|
-
end
|
62
|
-
|
63
59
|
def valid_user?
|
64
60
|
user_class = NiftyServices.config.user_class
|
65
61
|
|
@@ -98,20 +94,28 @@ module NiftyServices
|
|
98
94
|
alias :runned? :executed?
|
99
95
|
|
100
96
|
private
|
97
|
+
def default_options
|
98
|
+
{}
|
99
|
+
end
|
100
|
+
|
101
101
|
def can_execute?
|
102
102
|
not_implemented_exception(__method__)
|
103
103
|
end
|
104
104
|
|
105
105
|
def execute_action(&block)
|
106
|
-
|
106
|
+
begin
|
107
|
+
return nil if executed?
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
with_before_and_after_callbacks(:execute) do
|
110
|
+
if can_execute?
|
111
|
+
yield(block) if block_given?
|
112
|
+
end
|
111
113
|
end
|
112
|
-
end
|
113
114
|
|
114
|
-
|
115
|
+
@executed = true
|
116
|
+
rescue Exception => e
|
117
|
+
add_error(e)
|
118
|
+
end
|
115
119
|
|
116
120
|
self # allow chaining
|
117
121
|
end
|
@@ -203,7 +207,7 @@ module NiftyServices
|
|
203
207
|
changes << attribute if (old_attributes[attribute] != value)
|
204
208
|
end
|
205
209
|
|
206
|
-
changes
|
210
|
+
changes.map(&:to_sym)
|
207
211
|
end
|
208
212
|
|
209
213
|
def i18n_namespace
|
@@ -5,8 +5,9 @@ module NiftyServices
|
|
5
5
|
execute_action do
|
6
6
|
with_before_and_after_callbacks(:update) do
|
7
7
|
if can_execute_action?
|
8
|
-
|
9
|
-
|
8
|
+
duplicate_records_before_update
|
9
|
+
|
10
|
+
@record = update_record
|
10
11
|
|
11
12
|
if success_updated?
|
12
13
|
success_response
|
@@ -21,58 +22,68 @@ module NiftyServices
|
|
21
22
|
|
22
23
|
def changed_attributes
|
23
24
|
return [] if fail?
|
24
|
-
@changed_attributes ||= changes(@
|
25
|
+
@changed_attributes ||= changes(@last_record, @record, changed_attributes_array)
|
25
26
|
end
|
26
27
|
|
27
28
|
private
|
28
29
|
|
29
30
|
def changed_attributes_array
|
30
|
-
|
31
|
+
record_allowed_attributes.keys
|
31
32
|
end
|
32
33
|
|
33
34
|
def success_updated?
|
34
|
-
@
|
35
|
+
@record.valid?
|
35
36
|
end
|
36
37
|
|
37
38
|
def update_errors
|
38
|
-
@
|
39
|
+
@record.errors
|
39
40
|
end
|
40
41
|
|
41
42
|
def update_record
|
42
|
-
@record.class.send(:update, @record.id,
|
43
|
+
@record.class.send(:update, @record.id, record_allowed_attributes)
|
43
44
|
end
|
44
45
|
|
45
|
-
def
|
46
|
-
|
46
|
+
def can_execute?
|
47
47
|
unless valid_record?
|
48
|
-
return not_found_error!(
|
48
|
+
return not_found_error!(invalid_record_error_key)
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
return not_found_error!(
|
51
|
+
if validate_user? && !valid_user?
|
52
|
+
return not_found_error!(invalid_user_error_key)
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
|
-
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
|
58
|
+
def can_update_record?
|
59
|
+
unless user_can_update_record?
|
60
|
+
return (valid? ? forbidden_error!(user_cant_update_error_key) : false)
|
57
61
|
end
|
58
62
|
|
59
63
|
return true
|
60
64
|
end
|
61
65
|
|
62
|
-
def
|
63
|
-
return
|
64
|
-
return false unless valid_record?
|
65
|
-
|
66
|
-
return user_can_update_record?
|
66
|
+
def can_execute_action?
|
67
|
+
return can_update_record?
|
67
68
|
end
|
68
69
|
|
69
70
|
def user_can_update_record?
|
71
|
+
return not_implemented_exception(__method__) unless @record.respond_to?(:user_can_update?)
|
72
|
+
|
70
73
|
@record.user_can_update?(@user)
|
71
74
|
end
|
72
75
|
|
73
|
-
def
|
74
|
-
@
|
75
|
-
|
76
|
+
def duplicate_records_before_update
|
77
|
+
@last_record = @record.dup
|
78
|
+
end
|
79
|
+
|
80
|
+
def invalid_record_error_key
|
81
|
+
"#{record_error_key}.not_found"
|
76
82
|
end
|
83
|
+
|
84
|
+
def user_cant_update_error_key
|
85
|
+
"#{record_error_key}.user_cant_update"
|
86
|
+
end
|
87
|
+
|
77
88
|
end
|
78
89
|
end
|
@@ -31,9 +31,9 @@ module NiftyServices
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
attr_reader :
|
34
|
+
attr_reader :options
|
35
35
|
|
36
|
-
attr_accessor :user_class, :service_concerns_namespace
|
36
|
+
attr_accessor :logger, :i18n_namespace, :user_class, :service_concerns_namespace
|
37
37
|
|
38
38
|
def initialize(options = {})
|
39
39
|
@options = options
|
data/nifty_services.gemspec
CHANGED
@@ -20,10 +20,9 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.
|
24
|
-
|
25
|
-
spec.add_development_dependency "
|
26
|
-
spec.add_development_dependency "
|
27
|
-
spec.
|
28
|
-
spec.add_development_dependency "pry"
|
23
|
+
spec.add_development_dependency "bundler"
|
24
|
+
spec.add_development_dependency "rake", '~> 10.5.0'
|
25
|
+
spec.add_development_dependency "rspec", '~> 3.5.0'
|
26
|
+
spec.add_development_dependency "pry", '~> 0'
|
27
|
+
spec.add_runtime_dependency 'activesupport', '>= 4.2.2'
|
29
28
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nifty_services
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafael Fidelis
|
@@ -11,75 +11,75 @@ cert_chain: []
|
|
11
11
|
date: 2016-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 10.5.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 10.5.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 3.5.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 3.5.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: pry
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: activesupport
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
76
|
-
type: :
|
75
|
+
version: 4.2.2
|
76
|
+
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 4.2.2
|
83
83
|
description: The dead simple services object oriented layer for Ruby applications
|
84
84
|
to give robustness and cohesion back to your code.
|
85
85
|
email:
|
@@ -99,7 +99,6 @@ files:
|
|
99
99
|
- Rakefile
|
100
100
|
- bin/console
|
101
101
|
- bin/setup
|
102
|
-
- daily_news.log
|
103
102
|
- lib/nifty_services.rb
|
104
103
|
- lib/nifty_services/base_action_service.rb
|
105
104
|
- lib/nifty_services/base_create_service.rb
|
@@ -113,7 +112,6 @@ files:
|
|
113
112
|
- lib/nifty_services/util.rb
|
114
113
|
- lib/nifty_services/version.rb
|
115
114
|
- nifty_services.gemspec
|
116
|
-
- test.rb
|
117
115
|
homepage: https://github.com/fidelisrafael/nifty_services
|
118
116
|
licenses:
|
119
117
|
- MIT
|
data/daily_news.log
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
# Logfile created on 2016-07-15 17:46:01 -0300 by logger.rb/53141
|
2
|
-
I, [2016-07-15T17:46:01.453040 #30030] INFO -- : Routine Details: Send daily news email to user Rafael Fidelis(rafa_fidelis@yahoo.com.br)
|
3
|
-
I, [2016-07-15T17:46:01.453179 #30030] INFO -- : Routine started at: 2016-07-15 17:46:01 -0300
|
4
|
-
W, [2016-07-15T17:46:01.453464 #30030] WARN -- : Something went wrong
|
5
|
-
E, [2016-07-15T17:46:01.484243 #30030] ERROR -- : Error sending email to user. See details below :(
|
6
|
-
E, [2016-07-15T17:46:01.484330 #30030] ERROR -- : ["translation missing: en.nifty_services.errors.users.yet_received_daily_news_mail"]
|
7
|
-
I, [2016-07-15T17:46:01.484470 #30030] INFO -- : Routine ended at: 2016-07-15 17:46:01 -0300
|
data/test.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
class DailyNewsMailSendService < NiftyServices::BaseService
|
2
|
-
|
3
|
-
before_execute do
|
4
|
-
log.info('Routine started at: %s' % Time.now)
|
5
|
-
end
|
6
|
-
|
7
|
-
after_execute do
|
8
|
-
log.info('Routine ended at: %s' % Time.now)
|
9
|
-
end
|
10
|
-
|
11
|
-
after_initialize do
|
12
|
-
user_data = [@user.name, @user.email]
|
13
|
-
log.info('Routine Details: Send daily news email to user %s(%s)' % user_data)
|
14
|
-
end
|
15
|
-
|
16
|
-
after_success do
|
17
|
-
log.info('Success sent daily news feed email to user')
|
18
|
-
end
|
19
|
-
|
20
|
-
before_error do
|
21
|
-
log.warn('Something went wrong')
|
22
|
-
end
|
23
|
-
|
24
|
-
after_error do
|
25
|
-
log.error('Error sending email to user. See details below :(')
|
26
|
-
log.error(errors)
|
27
|
-
end
|
28
|
-
|
29
|
-
attr_reader :user
|
30
|
-
|
31
|
-
def initialize(user, options = {})
|
32
|
-
@user = user
|
33
|
-
super(options)
|
34
|
-
end
|
35
|
-
|
36
|
-
def execute
|
37
|
-
execute_action do
|
38
|
-
if can_execute?
|
39
|
-
success_response if send_mail_to_user
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
def send_mail_to_user
|
46
|
-
# just to fake, a real implementation could be something like:
|
47
|
-
# @user.send_daily_news_mail!
|
48
|
-
return true
|
49
|
-
end
|
50
|
-
|
51
|
-
def can_execute?
|
52
|
-
unless valid_user?
|
53
|
-
# returns false
|
54
|
-
return not_found_error!('users.not_found')
|
55
|
-
end
|
56
|
-
|
57
|
-
unless @user.abble_to_receive_daily_news_mail?
|
58
|
-
# returns false
|
59
|
-
return forbidden_error!('users.yet_received_daily_news_mail')
|
60
|
-
end
|
61
|
-
|
62
|
-
return true
|
63
|
-
end
|
64
|
-
|
65
|
-
def valid_user?
|
66
|
-
# check if object is valid and is a User class type
|
67
|
-
valid_object?(@user, User)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
class User < Struct.new(:name, :email)
|
72
|
-
# just to play around with results
|
73
|
-
def abble_to_receive_daily_news_mail?
|
74
|
-
rand(10) < 5
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
user = User.new('Rafael Fidelis', 'rafa_fidelis@yahoo.com.br')
|
79
|
-
|
80
|
-
# Default logger is NiftyService.config.logger # Logger.new('/dev/null')
|
81
|
-
service = DailyNewsMailSendService.new(user, logger: Logger.new('daily_news.log'))
|
82
|
-
service.execute
|