nifty_services 0.0.4 → 0.0.5
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 +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
|