backframe 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b82eb2645a15741b2dfda3c0fea9ae60c1d90ed8
4
- data.tar.gz: 32f108b39fe6a99f90b936e4d47964cf9b25f2b2
3
+ metadata.gz: c790128270ae83c43af08ac36a24e55aa5241b8b
4
+ data.tar.gz: 221387ef8f5007debad90f610d3dd2567019995f
5
5
  SHA512:
6
- metadata.gz: e6176bfbbef7a17bdf19d1cefb6bd55f7b015a7b8dba667b2d89a85677612795c99c63503443f7a9874a2a2a3bc141990fa199d5d7a5db49e4623d47527142aa
7
- data.tar.gz: 02130ecd29e535126f3714f75d43b78bf6ccd204399fd80c928b56a874f072c793b06bb1a854cdae6e12065cfb5467b22daf393f5dcc4cf14d5944b6243106ef
6
+ metadata.gz: b712a396fbf157b3b0fb6b3bd796d0711044e3d4c1814709577c9357c7bd04cf3763507b056f6e8937095d4a8e7e4370f626a6519b5b4523f29cb95b05e40afd
7
+ data.tar.gz: 966fe448084e3ea8841b444680f6aaa08639587ca4f6af1a87e3a6a2898750a2b6b2adc3dfa0d877e19f7305fac04b79381f33248522b0014bec85be1ba79dbe
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Backframe
2
2
 
3
+ Backframe is a library of server side bindings for building Rails backends for Reframe apps
4
+
3
5
  ## Development
4
6
 
5
7
  bundle install
6
8
  bundle exec rake spec
9
+
10
+
@@ -1,6 +1,7 @@
1
1
  module Backframe
2
- module API
2
+ module ActsAsAPI
3
3
  class Adapter < ActiveModel::Serializer::Adapter::Attributes
4
+
4
5
  attr_reader :fields, :links
5
6
 
6
7
  def initialize(serializer, options = {})
@@ -23,27 +24,28 @@ module Backframe
23
24
 
24
25
  private
25
26
 
26
- def with_pagination_metadata(records)
27
- {
28
- records: records.map(&method(:select_fields)),
29
- total_records: paginated.total_count,
30
- total_pages: paginated.total_pages,
31
- current_page: paginated.current_page,
32
- links: links
33
- }
34
- end
27
+ def with_pagination_metadata(records)
28
+ {
29
+ records: records.map(&method(:select_fields)),
30
+ total_records: paginated.total_count,
31
+ total_pages: paginated.total_pages,
32
+ current_page: paginated.current_page,
33
+ links: links
34
+ }
35
+ end
35
36
 
36
- def paginated
37
- serializer.object
38
- end
37
+ def paginated
38
+ serializer.object
39
+ end
39
40
 
40
- def select_fields(object)
41
- if fields.present?
42
- object.select { |key, val| fields.include?(key) }
43
- else
44
- object
41
+ def select_fields(object)
42
+ if fields.present?
43
+ object.select { |key, val| fields.include?(key) }
44
+ else
45
+ object
46
+ end
45
47
  end
46
- end
48
+
47
49
  end
48
50
  end
49
51
  end
@@ -1,5 +1,5 @@
1
1
  module Backframe
2
- module API
2
+ module ActsAsAPI
3
3
  module Errors
4
4
  def unauthenticated_request
5
5
  error_response(:unauthenticated, 401)
@@ -24,7 +24,7 @@ module Backframe
24
24
 
25
25
  result = {
26
26
  error: {
27
- message: I18n.t("backframe.api.#{code}", method: request.method),
27
+ message: I18n.t("backframe.acts_as_api.#{code}", method: request.method),
28
28
  status: status
29
29
  }
30
30
  }
@@ -34,7 +34,7 @@ module Backframe
34
34
 
35
35
  def resource_error_response(resource, status = 500)
36
36
  result = {
37
- message: I18n.t('backframe.api.resource_error', request: request),
37
+ message: I18n.t('backframe.acts_as_api.resource_error', request: request),
38
38
  errors: resource.errors,
39
39
  status: status
40
40
  }
@@ -1,5 +1,5 @@
1
1
  module Backframe
2
- module API
2
+ module ActsAsAPI
3
3
  module Headers
4
4
  def set_expiration_header
5
5
  headers['Last-Modified'] = Time.now.httpdate
@@ -1,5 +1,5 @@
1
1
  module Backframe
2
- module API
2
+ module ActsAsAPI
3
3
  module Page
4
4
  DEFAULT_PAGE = 1
5
5
  DEFAULT_PER_PAGE = 100
@@ -35,85 +35,67 @@ module Backframe
35
35
  args[:page] ||= DEFAULT_PAGE
36
36
  args[:per_page] ||= DEFAULT_PER_PAGE
37
37
 
38
-
39
- collection = collection.page(args[:page]).per(args[:per_page])
40
- fields = (args.key?(:fields)) ? args[:fields].split(',').map(&:to_sym) : serializer._attributes
38
+ collection = (params[:format] == 'json') ? collection.page(args[:page]).per(args[:per_page]) : collection.all
41
39
 
42
40
  respond_to do |format|
43
41
  format.json {
42
+ fields = (args.key?(:fields)) ? args[:fields].split(',').map(&:to_sym) : serializer._attributes
44
43
  render json: collection,
45
44
  content_type: 'application/json',
46
- adapter: Backframe::API::Adapter,
45
+ adapter: Backframe::ActsAsAPI::Adapter,
47
46
  fields: fields,
48
- links: pagination_links(collection, args[:per_page], args[:page])
47
+ links: pagination_links(collection, args[:per_page], args[:page]),
48
+ status: 200
49
49
  }
50
50
  format.csv {
51
- content_type = (args.key?(:plain)) ? 'text/plain' : 'text/csv'
51
+ fields = expand_fields(collection, serializer, fields)
52
+ content_type = (args.key?(:download) && args[:download] == 'false') ? 'text/plain' : 'text/csv'
52
53
  render :text => collection_to_csv(collection, serializer, fields, ","), :content_type => content_type, :status => 200
53
54
  }
54
55
  format.tsv {
55
- content_type = (args.key?(:plain)) ? 'text/plain' : 'text/tab-separated-values'
56
+ fields = expand_fields(collection, serializer, fields)
57
+ content_type = (args.key?(:download) && args[:download] == 'false') ? 'text/plain' : 'text/tab-separated-values'
56
58
  render :text => collection_to_csv(collection, serializer, fields, "\t"), :content_type => content_type, :status => 200
57
59
  }
58
- format.xls {
59
- content_type = (args.key?(:plain)) ? 'text/xml' : 'application/xls'
60
- render :text => collection_to_xls(collection, serializer, fields), :content_type => content_type, :status => 200
61
- }
62
60
  format.xlsx {
63
- content_type = (args.key?(:plain)) ? 'text/xml' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
64
- render :text => collection_to_xls(collection, serializer, fields), :content_type => content_type, :status => 200
61
+ fields = expand_fields(collection, serializer, fields)
62
+ render :text => collection_to_xls(collection, serializer, fields), :content_type => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', :status => 200
65
63
  }
66
64
  end
67
65
  end
68
66
 
69
- def collection_to_csv(collection, serializer, fields, separator)
70
- rows = []
71
- line = []
72
- headers = []
73
- collection.each do |record|
74
- headers = []
75
- line = []
76
- serialized = OpenStruct.new(ActiveModel::SerializableResource.new(record).as_json)
77
- fields.each do |fullkey|
78
- value = serialized
79
- fullkey.to_s.split(".").each do |key|
80
- if value.respond_to?(key)
81
- value = value.send(key)
82
- if value.is_a?(Time)
83
- value = value.strftime("%F %T")
84
- elsif value.is_a?(Date)
85
- value = value.strftime("%F")
86
- elsif value.is_a?(Hash)
87
- value = OpenStruct.new(value)
88
- else
89
- value = value.to_s
90
- end
91
- else
92
- value = nil
93
- end
94
- end
95
- if !value.is_a?(OpenStruct)
96
- headers << fullkey
97
- line << value
98
- end
67
+ def expand_fields(collection, serializer, fields)
68
+ if fields.present?
69
+ fields.split(',').map(&:to_s)
70
+ else
71
+ serialized = serializer.new(collection.first).attributes
72
+ flatten_hash_keys(serialized)
73
+ end
74
+ end
75
+
76
+ def flatten_hash_keys(hash, prefix = '')
77
+ keys = []
78
+ hash.each do |key, value|
79
+ fullkey = (!prefix.empty?) ? "#{prefix}.#{key}" : key
80
+ if value.is_a?(Hash)
81
+ keys.concat(flatten_hash_keys(value, fullkey))
82
+ else
83
+ keys << fullkey.to_s
99
84
  end
100
- rows << line.join(separator)
101
85
  end
102
- rows.unshift(headers.join(separator))
103
- rows.join("\n")
86
+ keys
104
87
  end
105
88
 
106
- def collection_to_xls(collection, serializer, fields)
107
- filename = SecureRandom.hex(32).to_s.upcase[0,16]
108
- workbook = WriteXLSX.new(filename)
109
- worksheet = workbook.add_worksheet
110
- row = 0
111
- col = 0
112
- fields.each_with_index do |key, col|
113
- worksheet.write(row, col, key)
89
+ def collection_to_array(collection, serializer, fields)
90
+ rows = []
91
+ cols = []
92
+ row = []
93
+ fields.each do |key|
94
+ row << key
114
95
  end
115
- collection.all.each_with_index do |record, index|
116
- row = index + 1
96
+ rows << row
97
+ collection.all.each do |record|
98
+ row = []
117
99
  serialized = serializer.new(record).attributes
118
100
  fields.each_with_index do |fullkey, col|
119
101
  value = serialized
@@ -133,9 +115,33 @@ module Backframe
133
115
  value = 'true'
134
116
  elsif value.is_a?(FalseClass)
135
117
  value = 'false'
118
+ elsif value.is_a?(NilClass)
119
+ value = ''
136
120
  end
137
- value = (!value.is_a?(String)) ? '' : value
138
- worksheet.write(row, col, value)
121
+ row << "#{value}"
122
+ end
123
+ rows << row
124
+ end
125
+ rows
126
+ end
127
+
128
+ def collection_to_csv(collection, serializer, fields, separator)
129
+ output = []
130
+ rows = collection_to_array(collection, serializer, fields)
131
+ rows.each do |row|
132
+ output << row.join(separator)
133
+ end
134
+ output.join("\n")
135
+ end
136
+
137
+ def collection_to_xls(collection, serializer, fields)
138
+ filename = SecureRandom.hex(32).to_s.upcase[0,16]
139
+ workbook = WriteXLSX.new(filename)
140
+ worksheet = workbook.add_worksheet
141
+ rows = collection_to_array(collection, serializer, fields)
142
+ rows.each_with_index do |row, i|
143
+ row.each_with_index do |col, j|
144
+ worksheet.write(i, j, col)
139
145
  end
140
146
  end
141
147
  workbook.close
@@ -2,13 +2,13 @@ require 'active_support'
2
2
  require 'active_support/inflector'
3
3
  require 'active_model_serializers'
4
4
 
5
- require 'backframe/api/adapter'
6
- require 'backframe/api/errors'
7
- require 'backframe/api/headers'
8
- require 'backframe/api/page'
5
+ require 'backframe/acts_as_api/adapter'
6
+ require 'backframe/acts_as_api/errors'
7
+ require 'backframe/acts_as_api/headers'
8
+ require 'backframe/acts_as_api/page'
9
9
 
10
10
  module Backframe
11
- module API
11
+ module ActsAsAPI
12
12
  extend ActiveSupport::Concern
13
13
 
14
14
  class_methods do
@@ -1,5 +1,5 @@
1
1
  module Backframe
2
- module Resource
2
+ module ActsAsResource
3
3
  module Actions
4
4
  module Index
5
5
  def index
@@ -15,7 +15,7 @@ module Backframe
15
15
  Activity.create!(subject: current_user, text: 'created {object1}', object1: @item)
16
16
  end
17
17
 
18
- render json: @item, status: 201, adapter: Backframe::API::Adapter
18
+ render json: @item, status: 201, adapter: Backframe::ActsAsAPI::Adapter
19
19
  else
20
20
  resource_error_response(@item, 422)
21
21
  end
@@ -24,7 +24,7 @@ module Backframe
24
24
 
25
25
  module Show
26
26
  def show
27
- render json: @item, adapter: Backframe::API::Adapter
27
+ render json: @item, adapter: Backframe::ActsAsAPI::Adapter
28
28
  end
29
29
  end
30
30
 
@@ -51,7 +51,7 @@ module Backframe
51
51
  Activity.create!(subject: current_user, text: 'updated {object1}', object1: @item)
52
52
  end
53
53
 
54
- render json: @item, adapter: Backframe::API::Adapter
54
+ render json: @item, adapter: Backframe::ActsAsAPI::Adapter
55
55
  else
56
56
  resource_error_response(@item, 422)
57
57
  end
@@ -66,7 +66,7 @@ module Backframe
66
66
  records = update_all_params.map(&method(:update_record))
67
67
  end
68
68
 
69
- render json: records, adapter: Backframe::API::Adapter
69
+ render json: records, adapter: Backframe::ActsAsAPI::Adapter
70
70
  end
71
71
 
72
72
  private
@@ -1,9 +1,9 @@
1
1
  require 'active_support'
2
2
 
3
- require 'backframe/resource/actions'
3
+ require 'backframe/acts_as_resource/actions'
4
4
 
5
5
  module Backframe
6
- module Resource
6
+ module ActsAsResource
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  class_methods do
@@ -13,19 +13,29 @@ module Backframe
13
13
  field = args[0]
14
14
  arguments = args[1]
15
15
 
16
- if arguments.key?(:default)
17
- after_initialize :init_status, :if => Proc.new { |d| d.new_record? }
18
- end
19
16
 
20
17
  if arguments.key?(:required)
18
+
21
19
  validates_presence_of field
20
+
22
21
  end
23
22
 
24
- if arguments.key?(:in)
25
- validates_inclusion_of field, :in => arguments[:in]
23
+ if arguments.key?(:default)
24
+
25
+ after_initialize "init_#{field}_status".to_sym, :if => Proc.new { |d| d.new_record? }
26
+
27
+ class_eval <<-EOV
28
+ def init_#{field}_status
29
+ self.#{field} ||= '#{arguments[:default]}'
30
+ end
31
+ EOV
32
+
26
33
  end
27
34
 
28
35
  if arguments.key?(:in)
36
+
37
+ validates_inclusion_of field, :in => arguments[:in]
38
+
29
39
  arguments[:in].each do |status|
30
40
  class_eval <<-EOV
31
41
  scope :#{status}, -> { where(:status => '#{status}') }
@@ -35,14 +45,7 @@ module Backframe
35
45
  end
36
46
  EOV
37
47
  end
38
- end
39
48
 
40
- if arguments.key?(:default)
41
- class_eval <<-EOV
42
- def init_status
43
- self.#{field} ||= '#{arguments[:default]}'
44
- end
45
- EOV
46
49
  end
47
50
 
48
51
  end
@@ -8,7 +8,7 @@ module Backframe
8
8
  conditions = []
9
9
  params = []
10
10
  fields.each do |field|
11
- conditions << "LOWER(#{field}::VARCHAR) LIKE ?"
11
+ conditions << "LOWER(\"#{self.table_name}\".\"#{field}\"::VARCHAR) LIKE ?"
12
12
  params << '%'+filters[:q].downcase+'%'
13
13
  end
14
14
  args = params.unshift(conditions.join(' OR '))
@@ -20,15 +20,23 @@ module Backframe
20
20
  def filter_range(relation, filters, start_date, end_date = nil)
21
21
  end_date ||= start_date
22
22
  if filters.key?(:start_date) && filters.key?(:end_date)
23
- relation = relation.where("#{self.table_name}.#{start_date} <= ? AND #{self.table_name}.#{end_date} >= ?", filters[:end_date], filters[:start_date])
23
+ relation = relation.where("\"#{self.table_name}\".\"#{start_date}\" <= ? AND \"#{self.table_name}\".\"#{end_date}\" >= ?", filters[:end_date], filters[:start_date])
24
24
  end
25
25
  relation
26
26
  end
27
27
 
28
28
  def filter_boolean(relation, filters, field)
29
29
  if filters.key?(field)
30
- relation = relation.where(:field => true) if filters[field] == 1
31
- relation = relation.where(:field => false) if filters[field] == 0
30
+ relation = relation.where("\"#{self.table_name}\".\"#{field}\" = ?", true) if ["1","true"].include?(filters[field].to_s)
31
+ relation = relation.where("\"#{self.table_name}\".\"#{field}\" = ?", false) if ["0","false"].include?(filters[field].to_s)
32
+ end
33
+ relation
34
+ end
35
+
36
+ def filter_status(relation, filters, field, value)
37
+ if filters.key?(value)
38
+ relation = relation.where("\"#{self.table_name}\".\"#{field}\" = ?", value) if ["1","true"].include?(filters[value].to_s)
39
+ relation = relation.where("\"#{self.table_name}\".\"#{field}\" = ?", value) if ["0","false"].include?(filters[value].to_s)
32
40
  end
33
41
  relation
34
42
  end
@@ -4,7 +4,6 @@ module Backframe
4
4
 
5
5
  def register_types
6
6
  ::Mime::Type.register('text/tab-separated-values', :tsv)
7
- ::Mime::Type.register('application/vnd.ms-excel', :xls)
8
7
  ::Mime::Type.register('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', :xlsx)
9
8
  end
10
9
  end
@@ -1,12 +1,12 @@
1
1
  module Backframe
2
2
  class Railtie < ::Rails::Railtie
3
3
  initializer 'backframe' do |_app|
4
- ActionController::Base.send(:include, Backframe::API)
5
- ActionController::Base.send(:include, Backframe::Resource)
6
- ActiveRecord::Base.send(:include, Backframe::FilterSort)
4
+ ActionController::Base.send(:include, Backframe::ActsAsAPI)
5
+ ActionController::Base.send(:include, Backframe::ActsAsResource)
7
6
  ActiveRecord::Base.send(:include, Backframe::ActsAsOrderable)
8
- ActiveRecord::Base.send(:include, Backframe::ActsAsUser)
9
7
  ActiveRecord::Base.send(:include, Backframe::ActsAsStatus)
8
+ ActiveRecord::Base.send(:include, Backframe::ActsAsUser)
9
+ ActiveRecord::Base.send(:include, Backframe::FilterSort)
10
10
  ActiveRecord::Migration.send(:include, Backframe::Migration)
11
11
  Backframe::Mime.register_types
12
12
  end
@@ -1,3 +1,3 @@
1
1
  module Backframe
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
data/lib/backframe.rb CHANGED
@@ -1,8 +1,9 @@
1
- require 'backframe/api'
2
1
  require 'backframe/mime'
3
- require 'backframe/resource'
2
+ require 'backframe/acts_as_resource'
4
3
  require 'backframe/filter_sort'
5
4
  require 'backframe/acts_as_orderable'
5
+ require 'backframe/acts_as_api'
6
+ require 'backframe/acts_as_resource'
6
7
  require 'backframe/acts_as_status'
7
8
  require 'backframe/acts_as_user'
8
9
  require 'backframe/migration'
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Backframe::API', type: :controller do
3
+ describe 'Backframe::ActsAsAPI', type: :controller do
4
4
  controller do
5
- include Backframe::API
5
+ include Backframe::ActsAsAPI
6
6
  acts_as_api
7
7
 
8
8
  def base_api_url
@@ -13,7 +13,7 @@ describe 'Backframe::API', type: :controller do
13
13
  describe 'error handlng' do
14
14
  before { get :index }
15
15
 
16
- context 'resource not found' do
16
+ context 'acts_as_resource not found' do
17
17
  controller do
18
18
  def index
19
19
  raise ActiveRecord::RecordNotFound
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Backframe::Resource', type: :controller do
3
+ describe 'Backframe::ActsAsResource', type: :controller do
4
4
  controller do
5
- include Backframe::API
6
- include Backframe::Resource
5
+ include Backframe::ActsAsAPI
6
+ include Backframe::ActsAsResource
7
7
 
8
8
  acts_as_api
9
9
  acts_as_resource 'Example', allowed: [:a, :b, :c]
data/spec/spec_helper.rb CHANGED
@@ -45,7 +45,7 @@ module Helpers
45
45
  end
46
46
 
47
47
  def serialize(value, opts = {})
48
- opts[:adapter] ||= Backframe::API::Adapter
48
+ opts[:adapter] ||= Backframe::ActsAsAPI::Adapter
49
49
  ActiveModel::SerializableResource.new(value, opts).as_json
50
50
  end
51
51
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backframe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Kops
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-28 00:00:00.000000000 Z
12
+ date: 2016-05-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: write_xlsx
@@ -94,23 +94,23 @@ files:
94
94
  - Rakefile
95
95
  - backframe.gemspec
96
96
  - lib/backframe.rb
97
+ - lib/backframe/acts_as_api.rb
98
+ - lib/backframe/acts_as_api/adapter.rb
99
+ - lib/backframe/acts_as_api/errors.rb
100
+ - lib/backframe/acts_as_api/headers.rb
101
+ - lib/backframe/acts_as_api/page.rb
97
102
  - lib/backframe/acts_as_orderable.rb
103
+ - lib/backframe/acts_as_resource.rb
104
+ - lib/backframe/acts_as_resource/actions.rb
98
105
  - lib/backframe/acts_as_status.rb
99
106
  - lib/backframe/acts_as_user.rb
100
- - lib/backframe/api.rb
101
- - lib/backframe/api/adapter.rb
102
- - lib/backframe/api/errors.rb
103
- - lib/backframe/api/headers.rb
104
- - lib/backframe/api/page.rb
105
107
  - lib/backframe/filter_sort.rb
106
108
  - lib/backframe/migration.rb
107
109
  - lib/backframe/mime.rb
108
110
  - lib/backframe/railtie.rb
109
- - lib/backframe/resource.rb
110
- - lib/backframe/resource/actions.rb
111
111
  - lib/backframe/version.rb
112
- - spec/backframe/api_spec.rb
113
- - spec/backframe/resource_spec.rb
112
+ - spec/backframe/acts_as_api_spec.rb
113
+ - spec/backframe/acts_as_resource_spec.rb
114
114
  - spec/spec_helper.rb
115
115
  - spec/support/example.rb
116
116
  - spec/support/example_factory.rb
@@ -140,8 +140,8 @@ signing_key:
140
140
  specification_version: 4
141
141
  summary: Backframe
142
142
  test_files:
143
- - spec/backframe/api_spec.rb
144
- - spec/backframe/resource_spec.rb
143
+ - spec/backframe/acts_as_api_spec.rb
144
+ - spec/backframe/acts_as_resource_spec.rb
145
145
  - spec/spec_helper.rb
146
146
  - spec/support/example.rb
147
147
  - spec/support/example_factory.rb