backframe 0.0.49 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +16 -0
  3. data/.gitignore +2 -2
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +1156 -0
  6. data/Gemfile +9 -13
  7. data/README.md +133 -4
  8. data/Rakefile +3 -7
  9. data/backframe.gemspec +10 -11
  10. data/circle.yml +5 -2
  11. data/lib/backframe.rb +21 -34
  12. data/lib/backframe/mime.rb +4 -0
  13. data/lib/backframe/query.rb +48 -0
  14. data/lib/backframe/query/sort.rb +29 -0
  15. data/lib/backframe/railtie.rb +1 -16
  16. data/lib/backframe/response.rb +60 -0
  17. data/lib/backframe/response/adapter/csv.rb +39 -0
  18. data/lib/backframe/response/adapter/json.rb +53 -0
  19. data/lib/backframe/response/adapter/xlsx.rb +41 -0
  20. data/lib/backframe/response/adapter/xml.rb +37 -0
  21. data/lib/backframe/response/collection.rb +43 -0
  22. data/lib/backframe/response/fields.rb +62 -0
  23. data/lib/backframe/response/record.rb +38 -0
  24. data/lib/backframe/service.rb +60 -0
  25. data/lib/backframe/service/result/base.rb +24 -0
  26. data/lib/backframe/service/result/failure.rb +21 -0
  27. data/lib/backframe/service/result/success.rb +21 -0
  28. data/lib/backframe/version.rb +1 -1
  29. data/spec/fixtures/active_record.rb +22 -0
  30. data/spec/fixtures/models.rb +25 -0
  31. data/spec/fixtures/queries.rb +28 -0
  32. data/spec/fixtures/seeds.rb +12 -0
  33. data/spec/fixtures/serializers.rb +23 -0
  34. data/spec/fixtures/services.rb +26 -0
  35. data/spec/query/sort_spec.rb +47 -0
  36. data/spec/query_spec.rb +63 -0
  37. data/spec/response/adapter/csv_spec.rb +47 -0
  38. data/spec/response/adapter/json_spec.rb +66 -0
  39. data/spec/response/adapter/xlsx_spec.rb +59 -0
  40. data/spec/response/adapter/xml_spec.rb +63 -0
  41. data/spec/response/fields_spec.rb +45 -0
  42. data/spec/response/record_spec.rb +45 -0
  43. data/spec/response_spec.rb +153 -0
  44. data/spec/service/result/failure_spec.rb +16 -0
  45. data/spec/service/result/sucess_spec.rb +17 -0
  46. data/spec/service_spec.rb +16 -0
  47. data/spec/spec_helper.rb +15 -52
  48. metadata +78 -81
  49. data/lib/backframe/actioncontroller/acts_as_activation.rb +0 -70
  50. data/lib/backframe/actioncontroller/acts_as_api.rb +0 -39
  51. data/lib/backframe/actioncontroller/acts_as_api/adapter.rb +0 -53
  52. data/lib/backframe/actioncontroller/acts_as_api/errors.rb +0 -48
  53. data/lib/backframe/actioncontroller/acts_as_api/headers.rb +0 -11
  54. data/lib/backframe/actioncontroller/acts_as_api/page.rb +0 -181
  55. data/lib/backframe/actioncontroller/acts_as_reset.rb +0 -86
  56. data/lib/backframe/actioncontroller/acts_as_resource.rb +0 -92
  57. data/lib/backframe/actioncontroller/acts_as_resource/actions.rb +0 -100
  58. data/lib/backframe/actioncontroller/acts_as_session.rb +0 -80
  59. data/lib/backframe/activerecord/acts_as_activable.rb +0 -50
  60. data/lib/backframe/activerecord/acts_as_distinct.rb +0 -49
  61. data/lib/backframe/activerecord/acts_as_enum.rb +0 -62
  62. data/lib/backframe/activerecord/acts_as_orderable.rb +0 -40
  63. data/lib/backframe/activerecord/acts_as_percent.rb +0 -46
  64. data/lib/backframe/activerecord/acts_as_phone.rb +0 -59
  65. data/lib/backframe/activerecord/acts_as_user.rb +0 -101
  66. data/lib/backframe/activerecord/default_values.rb +0 -32
  67. data/lib/backframe/activerecord/filter_sort.rb +0 -79
  68. data/lib/backframe/activerecord/migration.rb +0 -25
  69. data/lib/backframe/image_cache/image_cache.rb +0 -45
  70. data/lib/backframe/image_cache/lib/asset.rb +0 -109
  71. data/lib/backframe/image_cache/lib/cache.rb +0 -67
  72. data/lib/backframe/image_cache/lib/conversions.rb +0 -132
  73. data/lib/backframe/models/activation.rb +0 -60
  74. data/lib/backframe/models/activity.rb +0 -40
  75. data/lib/backframe/models/reset.rb +0 -59
  76. data/lib/backframe/models/story.rb +0 -9
  77. data/lib/backframe/serializers/activity_serializer.rb +0 -44
  78. data/spec/backframe/acts_as_api_spec.rb +0 -225
  79. data/spec/backframe/acts_as_resource_spec.rb +0 -178
  80. data/spec/support/example_factory.rb +0 -9
  81. data/spec/support/example_serializer.rb +0 -3
  82. data/spec/support/schema.rb +0 -8
@@ -1,70 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'active_support'
4
- require 'active_support/inflector'
5
-
6
- module Backframe
7
- module ActsAsActivation
8
- extend ActiveSupport::Concern
9
-
10
- class_methods do
11
- def acts_as_activation(model, *args)
12
-
13
- arguments = args[0] || {}
14
-
15
- activation = arguments[:activation] || 'Backframe::Activation'
16
-
17
- class_eval <<-EOV
18
-
19
- layout 'signin'
20
- before_action :load_user, :except => :show
21
-
22
- def show
23
- @activation = #{activation}.find_by(:token => params[:token])
24
- if @activation.nil?
25
- flash[:error] = I18n.t(:activation_invalid)
26
- redirect_to account_signin_path
27
- elsif @activation.expired?
28
- flash[:error] = I18n.t(:activation_expired)
29
- redirect_to '#{arguments[:prefix]}/signin'
30
- else
31
- session.delete(:#{model.underscore}_id)
32
- session[:activation_id] = @activation.id
33
- flash[:success] = I18n.t(:activation_success)
34
- redirect_to '#{arguments[:prefix]}/activation/password'
35
- end
36
- end
37
-
38
- def password
39
- if request.patch?
40
- @user.set_password = true
41
- @user.attributes = params.require(:#{model.underscore}).permit([:new_password,:confirm_password])
42
- if @user.save
43
- session.delete(:activation_id)
44
- session[:#{model.underscore}_id] = @user.id
45
- @activation.claim
46
- redirect_to '#{arguments[:redirect]}'
47
- else
48
- flash[:error] = @user.errors[:new_password].first
49
- end
50
- end
51
- end
52
-
53
- private
54
-
55
- def load_user
56
- @activation = #{activation}.find_by(:id => session[:activation_id])
57
- @user = @activation.user
58
- if @user.nil?
59
- flash[:error] = I18n.t(:activation_invalid)
60
- redirect_to '#{arguments[:prefix]}/signin'
61
- end
62
- end
63
-
64
- EOV
65
-
66
- end
67
- end
68
-
69
- end
70
- end
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'write_xlsx'
4
-
5
- require 'active_support'
6
- require 'active_support/inflector'
7
- require 'active_model_serializers'
8
-
9
- require 'backframe/actioncontroller/acts_as_api/adapter'
10
- require 'backframe/actioncontroller/acts_as_api/errors'
11
- require 'backframe/actioncontroller/acts_as_api/headers'
12
- require 'backframe/actioncontroller/acts_as_api/page'
13
-
14
- module Backframe
15
- module ActsAsAPI
16
- extend ActiveSupport::Concern
17
-
18
- class_methods do
19
- def acts_as_api
20
- include Errors
21
- include Headers
22
- include Page
23
-
24
- before_action :set_expiration_header
25
-
26
- rescue_from Exceptions::Unauthenticated, :with => :unauthenticated_request
27
- rescue_from Exceptions::Unauthorized, :with => :unauthorized_request
28
- rescue_from 'ActiveRecord::RecordNotFound', :with => :resource_not_found
29
- rescue_from 'ActionController::RoutingError', :with => :route_not_found
30
- end
31
- end
32
-
33
- included do
34
- def base_api_url
35
- raise 'must be overridden'
36
- end
37
- end
38
- end
39
- end
@@ -1,53 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Backframe
4
- module ActsAsAPI
5
- class Adapter < ActiveModel::Serializer::Adapter::Attributes
6
-
7
- attr_reader :fields, :links
8
-
9
- def initialize(serializer, options = {})
10
- super
11
- @fields = options[:fields]
12
- @links = options[:links]
13
- end
14
-
15
- def serializable_hash(options = nil)
16
- if paginated?
17
- with_pagination_metadata(super)
18
- else
19
- select_fields(super)
20
- end
21
- end
22
-
23
- def paginated?
24
- serializer.respond_to?(:paginated?) && serializer.paginated?
25
- end
26
-
27
- private
28
-
29
- def with_pagination_metadata(records)
30
- {
31
- records: records.map(&method(:select_fields)),
32
- total_records: paginated.total_count,
33
- total_pages: paginated.total_pages,
34
- current_page: paginated.current_page,
35
- links: links
36
- }
37
- end
38
-
39
- def paginated
40
- serializer.object
41
- end
42
-
43
- def select_fields(object)
44
- if fields.present?
45
- object.select { |key, val| fields.include?(key) }
46
- else
47
- object
48
- end
49
- end
50
-
51
- end
52
- end
53
- end
@@ -1,48 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Backframe
4
- module ActsAsAPI
5
- module Errors
6
- def unauthenticated_request
7
- error_response(:unauthenticated, 401)
8
- end
9
-
10
- def unauthorized_request
11
- error_response(:unauthorized, 403)
12
- end
13
-
14
- def resource_not_found
15
- error_response(:resource_not_found, 404)
16
- end
17
-
18
- def route_not_found
19
- error_response(:route_not_found, 404)
20
- end
21
-
22
- private
23
-
24
- def error_response(code, status = 500)
25
- # TODO: Create generator for translations
26
-
27
- result = {
28
- error: {
29
- message: I18n.t("backframe.acts_as_api.#{code}", method: request.method),
30
- status: status
31
- }
32
- }
33
-
34
- render json: result, status: status
35
- end
36
-
37
- def resource_error_response(resource, status = 500)
38
- result = {
39
- message: I18n.t('backframe.acts_as_api.resource_error', request: request),
40
- errors: resource.errors,
41
- status: status
42
- }
43
-
44
- render json: result, status: status
45
- end
46
- end
47
- end
48
- end
@@ -1,11 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Backframe
4
- module ActsAsAPI
5
- module Headers
6
- def set_expiration_header
7
- headers['Last-Modified'] = Time.now.httpdate
8
- end
9
- end
10
- end
11
- end
@@ -1,181 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Backframe
4
- module ActsAsAPI
5
- module Page
6
- DEFAULT_PAGE = 1
7
- DEFAULT_PER_PAGE = 100
8
-
9
- def page(collection, serializer = nil)
10
- classname = collection.base_class.name+'Serializer'
11
- serializer ||= classname.constantize
12
- args = params.except(*request.path_parameters.keys)
13
- filters = args.except([:sort,:page,:per_page,:fields,:exclude_ids])
14
- model = (collection.respond_to?(:klass)) ? collection.klass.name.constantize : collection
15
- collection = model.filter(collection, filters) if collection.respond_to?(:filter)
16
-
17
- if args.key?(:sort)
18
- args[:sort].split(',').each do |sort|
19
- key = (sort[0] == '-') ? sort[1..-1] : sort
20
- order = (sort[0] == '-') ? 'desc' : 'asc'
21
- collection = model.sort(collection, key, order)
22
- end
23
- else
24
- collection = model.sort(collection)
25
- end
26
-
27
- if args.key?(:exclude_ids)
28
- ids = args[:exclude_ids].split(',')
29
- collection = collection.where('id NOT IN (?)', ids)
30
- end
31
-
32
- if args.key?(:all)
33
- args[:page] = 1
34
- args[:per_page] = 10000
35
- end
36
-
37
- args[:page] ||= DEFAULT_PAGE
38
- args[:per_page] ||= DEFAULT_PER_PAGE
39
-
40
- collection = (params[:format] == 'json') ? collection.page(args[:page]).per(args[:per_page]) : collection.all
41
-
42
- respond_to do |format|
43
- format.json {
44
- fields = (args.key?(:fields)) ? args[:fields].split(',').map(&:to_sym) : serializer._attributes
45
- render json: collection,
46
- each_serializer: serializer,
47
- content_type: 'application/json',
48
- adapter: Backframe::ActsAsAPI::Adapter,
49
- fields: fields,
50
- links: pagination_links(collection, args[:per_page], args[:page]),
51
- status: 200
52
- }
53
- format.csv {
54
- fields = expand_fields(collection, serializer, args[:fields])
55
- content_type = (args.key?(:download) && args[:download] == 'false') ? 'text/plain' : 'text/csv'
56
- render :text => collection_to_csv(collection, serializer, fields, ","), :content_type => content_type, :status => 200
57
- }
58
- format.tsv {
59
- fields = expand_fields(collection, serializer, args[:fields])
60
- content_type = (args.key?(:download) && args[:download] == 'false') ? 'text/plain' : 'text/tab-separated-values'
61
- render :text => collection_to_csv(collection, serializer, fields, "\t"), :content_type => content_type, :status => 200
62
- }
63
- format.xlsx {
64
- fields = expand_fields(collection, serializer, args[:fields])
65
- render :text => collection_to_xls(collection, serializer, fields), :content_type => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', :status => 200
66
- }
67
- end
68
- end
69
-
70
- def expand_fields(collection, serializer, fields)
71
- if fields.present?
72
- fields.split(',').map(&:to_s)
73
- else
74
- serialized = serializer.new(collection.first).attributes
75
- flatten_hash_keys(serialized)
76
- end
77
- end
78
-
79
- def flatten_hash_keys(hash, prefix = '')
80
- keys = []
81
- hash.each do |key, value|
82
- fullkey = (!prefix.empty?) ? "#{prefix}.#{key}" : key
83
- if value.is_a?(Hash)
84
- keys.concat(flatten_hash_keys(value, fullkey))
85
- else
86
- keys << fullkey.to_s
87
- end
88
- end
89
- keys
90
- end
91
-
92
- def collection_to_array(collection, serializer, fields)
93
- rows = []
94
- cols = []
95
- row = []
96
- fields.each do |key|
97
- row << key
98
- end
99
- rows << row
100
- collection.all.each do |record|
101
- row = []
102
- serialized = serializer.new(record).attributes
103
- fields.each_with_index do |fullkey, col|
104
- value = serialized
105
- fullkey.to_s.split(".").each do |key|
106
- key = key.to_sym
107
- if value.is_a?(Hash) && value.key?(key)
108
- value = value[key]
109
- else
110
- value = nil
111
- end
112
- end
113
- if value.is_a?(Time)
114
- value = value.strftime("%F %T")
115
- elsif value.is_a?(Date)
116
- value = value.strftime("%F")
117
- elsif value.is_a?(TrueClass)
118
- value = 'true'
119
- elsif value.is_a?(FalseClass)
120
- value = 'false'
121
- elsif value.is_a?(NilClass)
122
- value = ''
123
- end
124
- row << "#{value}"
125
- end
126
- rows << row
127
- end
128
- rows
129
- end
130
-
131
- def collection_to_csv(collection, serializer, fields, separator)
132
- output = []
133
- rows = collection_to_array(collection, serializer, fields)
134
- rows.each do |row|
135
- output << row.join(separator)
136
- end
137
- output.join("\n")
138
- end
139
-
140
- def collection_to_xls(collection, serializer, fields)
141
- filename = SecureRandom.hex(32).to_s.upcase[0,16]
142
- workbook = WriteXLSX.new(filename)
143
- worksheet = workbook.add_worksheet
144
- rows = collection_to_array(collection, serializer, fields)
145
- rows.each_with_index do |row, i|
146
- row.each_with_index do |col, j|
147
- worksheet.write_string(i, j, col)
148
- end
149
- end
150
- workbook.close
151
- data = open(filename).read
152
- File.unlink(filename)
153
- data
154
- end
155
-
156
- def pagination_links(collection, per_page, page)
157
- return {} if collection.total_count.zero?
158
- links = {}
159
- links[:self] = pagination_link(per_page, page)
160
- if collection.next_page.present?
161
- links[:next] = pagination_link(per_page, collection.next_page)
162
- end
163
- if page.to_i < collection.total_pages
164
- links[:last] = pagination_link(per_page, collection.total_pages)
165
- end
166
- if page.to_i > 1
167
- links[:first] = pagination_link(per_page, 1)
168
- end
169
- if collection.prev_page.present?
170
- links[:prev] = pagination_link(per_page, collection.prev_page)
171
- end
172
- links
173
- end
174
-
175
- def pagination_link(per_page, page)
176
- args = (per_page.to_i != DEFAULT_PER_PAGE) ? "per_page="+per_page.to_s+"&page="+page.to_s : "page="+page.to_s
177
- base_api_url+request.path+"?"+args
178
- end
179
- end
180
- end
181
- end
@@ -1,86 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'active_support'
4
- require 'active_support/inflector'
5
-
6
- module Backframe
7
- module ActsAsReset
8
- extend ActiveSupport::Concern
9
-
10
- class_methods do
11
- def acts_as_reset(model, *args)
12
-
13
- arguments = args[0] || {}
14
-
15
- reset = arguments[:reset] || 'Backframe::Reset'
16
-
17
- class_eval <<-EOV
18
-
19
- layout 'signin'
20
- before_action :redirect_if_signed_in
21
- before_action :load_user, :except => [:new,:show]
22
-
23
- def new
24
- if request.post?
25
- @user = #{model}.find_by_email(params[:#{model.underscore}][:email])
26
- if @user && @user.reset
27
- flash[:error] = I18n.t(:reset_request)
28
- redirect_to '#{arguments[:prefix]}/signin'
29
- else
30
- flash[:error] = I18n.t(:reset_not_found)
31
- redirect_to '#{arguments[:prefix]}/reset'
32
- end
33
- else
34
- @user = #{model}.new
35
- end
36
- end
37
-
38
- def show
39
- @reset = #{reset}.find_by(:token => params[:token])
40
- if @reset.nil?
41
- flash[:error] = I18n.t(:reset_invalid)
42
- redirect_to '#{arguments[:prefix]}/signin'
43
- elsif @reset.expired?
44
- flash[:error] = I18n.t(:reset_expired)
45
- redirect_to '#{arguments[:prefix]}/signin'
46
- else
47
- @reset.claim
48
- session[:reset_id] = @reset.id
49
- flash[:error] = I18n.t(:reset_password)
50
- redirect_to '#{arguments[:prefix]}/reset/password'
51
- end
52
- end
53
-
54
- def password
55
- if request.patch?
56
- @user.set_password = true
57
- @user.attributes = params.require(:#{model.underscore}).permit([:new_password,:confirm_password])
58
- if @user.save
59
- session.delete(:reset_id)
60
- session[:#{model.underscore}_id] = @user.id
61
- flash[:error] = I18n.t(:reset_success)
62
- redirect_to '#{arguments[:redirect]}'
63
- else
64
- flash[:error] = @user.errors[:new_password].first
65
- end
66
- end
67
- end
68
-
69
- private
70
-
71
- def load_user
72
- @reset = #{reset}.find_by(:id => session[:reset_id])
73
- @user = @reset.user
74
- if @user.nil?
75
- flash[:error] = I18n.t(:reset_invalid)
76
- redirect_to account_signin_path
77
- end
78
- end
79
-
80
- EOV
81
-
82
- end
83
- end
84
-
85
- end
86
- end