backframe 0.0.49 → 1.0.0

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.
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