backframe 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6893ca50993e2054bfa00298833e7d1d95762c6b
4
- data.tar.gz: fcaf54876f10f59cc5e9a8c4306caccfc8e9b5ff
3
+ metadata.gz: b82eb2645a15741b2dfda3c0fea9ae60c1d90ed8
4
+ data.tar.gz: 32f108b39fe6a99f90b936e4d47964cf9b25f2b2
5
5
  SHA512:
6
- metadata.gz: 1b3d72462843957ff8c6c5b8380f7e29d0b7133d99e79bc737527f56e9dbe985d42818c3dfd13fb2304a3bf028da1085ad7ecfe2dcab9fb33259b5e60bcd6e09
7
- data.tar.gz: 68ebc292ef2ea169459348d7c31955976bcdd8432afb30b066ee7d88da46ca9270cb037bfa816ad4997ce7287b52e096772230ee61357bbcb5b2dd752e541743
6
+ metadata.gz: e6176bfbbef7a17bdf19d1cefb6bd55f7b015a7b8dba667b2d89a85677612795c99c63503443f7a9874a2a2a3bc141990fa199d5d7a5db49e4623d47527142aa
7
+ data.tar.gz: 02130ecd29e535126f3714f75d43b78bf6ccd204399fd80c928b56a874f072c793b06bb1a854cdae6e12065cfb5467b22daf393f5dcc4cf14d5944b6243106ef
data/Gemfile CHANGED
@@ -3,7 +3,9 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development, :test do
6
- gem 'active_model_serializers', '0.10.0.rc4'
6
+ gem 'write_xlsx'
7
+ gem 'active_model_serializers'
8
+ gem 'activerecord'
7
9
  gem 'factory_girl'
8
10
  gem 'faker'
9
11
  gem 'kaminari'
data/backframe.gemspec CHANGED
@@ -16,6 +16,8 @@ Gem::Specification.new do |gem|
16
16
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
17
  gem.require_paths = ["lib"]
18
18
 
19
+ gem.add_runtime_dependency 'write_xlsx', '~> 0.83.0'
20
+ gem.add_runtime_dependency 'activerecord', '~> 4.0'
19
21
  gem.add_runtime_dependency 'activesupport', '~> 4.0'
20
22
  gem.add_runtime_dependency 'active_model_serializers', '>= 0.10.0.rc4'
21
23
  gem.add_runtime_dependency 'kaminari', '~> 0.16'
@@ -0,0 +1,38 @@
1
+ module Backframe
2
+ module ActsAsOrderable
3
+ extend ActiveSupport::Concern
4
+
5
+ def self.included(base)
6
+ base.send :extend, ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def acts_as_orderable(field, args = {})
12
+
13
+ class_eval <<-EOV
14
+ validates_presence_of :#{field}
15
+
16
+ before_validation :set_#{field}, :on => :create
17
+ after_destroy :reorder_#{field}
18
+
19
+ default_scope -> { order(:#{field} => :asc) }
20
+
21
+ def set_#{field}
22
+ self.#{field} ||= (self.#{args[:on]}.#{self.name.tableize}.any?) ? self.#{args[:on]}.#{self.name.tableize}.maximum(:#{field}) + 1 : 0
23
+ end
24
+
25
+ def reorder_#{field}
26
+ self.#{args[:on]}.#{self.name.tableize}.order(:#{field} => :asc).each_with_index do |item, index|
27
+ item.update_column(:#{field}, index)
28
+ end
29
+ end
30
+
31
+ EOV
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,52 @@
1
+ module Backframe
2
+ module ActsAsStatus
3
+ extend ActiveSupport::Concern
4
+
5
+ def self.included(base)
6
+ base.send :extend, ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def acts_as_status(*args)
12
+
13
+ field = args[0]
14
+ arguments = args[1]
15
+
16
+ if arguments.key?(:default)
17
+ after_initialize :init_status, :if => Proc.new { |d| d.new_record? }
18
+ end
19
+
20
+ if arguments.key?(:required)
21
+ validates_presence_of field
22
+ end
23
+
24
+ if arguments.key?(:in)
25
+ validates_inclusion_of field, :in => arguments[:in]
26
+ end
27
+
28
+ if arguments.key?(:in)
29
+ arguments[:in].each do |status|
30
+ class_eval <<-EOV
31
+ scope :#{status}, -> { where(:status => '#{status}') }
32
+
33
+ def #{status}?
34
+ self.#{field} == '#{status}'
35
+ end
36
+ EOV
37
+ end
38
+ end
39
+
40
+ if arguments.key?(:default)
41
+ class_eval <<-EOV
42
+ def init_status
43
+ self.#{field} ||= '#{arguments[:default]}'
44
+ end
45
+ EOV
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,101 @@
1
+ module Backframe
2
+ module ActsAsUser
3
+ extend ActiveSupport::Concern
4
+
5
+ def self.included(base)
6
+ base.send :extend, ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def acts_as_user
12
+
13
+ attr_accessor :password, :change_password, :set_password, :old_password, :new_password, :confirm_password, :confirm_email
14
+
15
+ has_many :activations, :dependent => :destroy
16
+ has_many :resets, :dependent => :destroy
17
+
18
+ after_validation :set_new_password, :if => Proc.new { |u| u.new_password.present? }
19
+ after_create :activate
20
+ after_save :update_activities, :if => Proc.new { |u| u.first_name_changed? || u.last_name_changed? }
21
+
22
+ validates_presence_of :first_name, :last_name, :email
23
+ validates_uniqueness_of :email
24
+ validate :validate_password, :if => Proc.new { |u| u.change_password.present? || u.set_password.present? }
25
+
26
+ class_eval <<-EOV
27
+ def full_name
28
+ self.first_name+' '+self.last_name
29
+ end
30
+
31
+ def rfc822
32
+ self.full_name+' <'+self.email+'>'
33
+ end
34
+
35
+ def locked_out?
36
+ self.signin_locked_at.present? && self.signin_locked_at > Time.now.ago(5.minutes)
37
+ end
38
+
39
+ def signin(status)
40
+ if status == :success
41
+ self.signin_locked_at = nil
42
+ self.signin_attempts = 0
43
+ elsif status == :failed
44
+ self.signin_attempts += 1
45
+ if self.signin_attempts >= 5
46
+ self.signin_attempts = 0
47
+ self.signin_locked_at = Time.now
48
+ end
49
+ end
50
+ self.save
51
+ end
52
+
53
+ def authenticate(password)
54
+ self.password_hash == BCrypt::Engine.hash_secret(password, self.password_salt)
55
+ end
56
+
57
+ def reset
58
+ self.resets.create
59
+ end
60
+
61
+ def activate
62
+ self.activations.create
63
+ end
64
+
65
+ def password=(password)
66
+ @password = password
67
+ self.password_salt = BCrypt::Engine.generate_salt
68
+ self.password_hash = BCrypt::Engine.hash_secret(password, self.password_salt)
69
+ end
70
+
71
+ def password
72
+ @password
73
+ end
74
+
75
+ def validate_password
76
+ if self.change_password && self.old_password.blank?
77
+ return self.errors.add(:old_password, I18n.t('activerecord.errors.messages.blank'))
78
+ elsif self.change_password && !authenticate(self.old_password)
79
+ return self.errors.add(:old_password, I18n.t(:user_invalid_old_password))
80
+ elsif self.new_password.blank? || self.confirm_password.blank?
81
+ return self.errors.add(:new_password, I18n.t(:user_unconfirmed_password))
82
+ elsif self.confirm_password != self.new_password
83
+ return self.errors.add(:new_password, I18n.t(:user_unmatching_passwords))
84
+ end
85
+ end
86
+
87
+ def set_new_password
88
+ self.password = self.new_password
89
+ end
90
+
91
+ def update_activities
92
+ Activity.where(:#{self.name.downcase}_id => self.id).update_all(:updated_at => Time.zone.now)
93
+ end
94
+
95
+ EOV
96
+
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -104,49 +104,44 @@ module Backframe
104
104
  end
105
105
 
106
106
  def collection_to_xls(collection, serializer, fields)
107
- rows = []
108
- rows << '<?xml version="1.0"?>'
109
- rows << '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">'
110
- rows << '<Worksheet ss:Name="Sheet1">'
111
- rows << '<Table>'
112
- line = []
113
- fields.each do |key|
114
- line << '<Cell><Data ss:Type="String">'+key+'</Data></Cell>'
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)
115
114
  end
116
- rows << "<Row>"+line.join+"</Row>"
117
- collection.all.each do |record|
118
- line = []
119
- serialized = serializer.new(record)
120
- fields.each do |fullkey|
115
+ collection.all.each_with_index do |record, index|
116
+ row = index + 1
117
+ serialized = serializer.new(record).attributes
118
+ fields.each_with_index do |fullkey, col|
121
119
  value = serialized
122
120
  fullkey.to_s.split(".").each do |key|
123
- if value.respond_to?(key)
124
- value = value.send(key)
125
- if value.is_a?(Hash)
126
- value = OpenStruct.new(value)
127
- end
121
+ key = key.to_sym
122
+ if value.is_a?(Hash) && value.key?(key)
123
+ value = value[key]
128
124
  else
129
125
  value = nil
130
126
  end
131
127
  end
132
- if value.is_a?(Numeric)
133
- line << '<Cell><Data ss:Type="Number">'+value+'</Data></Cell>'
134
- elsif value.is_a?(Time)
135
- line << '<Cell><Data ss:Type="String">'+value.strftime("%F %T")+'</Data></Cell>'
128
+ if value.is_a?(Time)
129
+ value = value.strftime("%F %T")
136
130
  elsif value.is_a?(Date)
137
- line << '<Cell><Data ss:Type="String">'+value.strftime("%F")+'</Data></Cell>'
138
- elsif value.is_a?(String)
139
- line << '<Cell><Data ss:Type="String">'+value+'</Data></Cell>'
140
- else
141
- line << '<Cell><Data ss:Type="String"></Data></Cell>'
131
+ value = value.strftime("%F")
132
+ elsif value.is_a?(TrueClass)
133
+ value = 'true'
134
+ elsif value.is_a?(FalseClass)
135
+ value = 'false'
142
136
  end
137
+ value = (!value.is_a?(String)) ? '' : value
138
+ worksheet.write(row, col, value)
143
139
  end
144
- rows << "<Row>"+line.join+"</Row>"
145
140
  end
146
- rows << '</Table>'
147
- rows << '</Worksheet>'
148
- rows << '</Workbook>'
149
- rows.join("\n")
141
+ workbook.close
142
+ data = open(filename).read
143
+ File.unlink(filename)
144
+ data
150
145
  end
151
146
 
152
147
  def pagination_links(collection, per_page, page)
@@ -0,0 +1,56 @@
1
+ module Backframe
2
+ module FilterSort
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ def filter_query(relation, filters, fields)
7
+ if filters.key?(:q)
8
+ conditions = []
9
+ params = []
10
+ fields.each do |field|
11
+ conditions << "LOWER(#{field}::VARCHAR) LIKE ?"
12
+ params << '%'+filters[:q].downcase+'%'
13
+ end
14
+ args = params.unshift(conditions.join(' OR '))
15
+ relation = relation.where(args)
16
+ end
17
+ relation
18
+ end
19
+
20
+ def filter_range(relation, filters, start_date, end_date = nil)
21
+ end_date ||= start_date
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])
24
+ end
25
+ relation
26
+ end
27
+
28
+ def filter_boolean(relation, filters, field)
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
32
+ end
33
+ relation
34
+ end
35
+
36
+ def sort(relation, key = nil, order = nil)
37
+ self._sort(relation, key, order, 'created_at', 'desc', [self])
38
+ end
39
+
40
+ def _sort(relation, key, order, default_key = 'created_at', default_order = 'desc', included = nil)
41
+ sortfields = {}
42
+ included ||= [self]
43
+ included.each do |model|
44
+ model.columns.each do |column|
45
+ sortkey = (model == self) ? column.name : "#{model.table_name.singularize}.#{column.name}"
46
+ sortfields[sortkey] = "\"#{model.table_name}\".\"#{column.name}\""
47
+ end
48
+ end
49
+
50
+ key = (key.present? && sortfields.has_key?(key)) ? key : default_key
51
+ order = (order.present?) ? order : default_order
52
+ relation.order("#{sortfields[key]} #{order}")
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ module Backframe
2
+ module Migration
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+
7
+ def add_foreign_key_index(from, to, column)
8
+ add_foreign_key(from, to, :column => column)
9
+ add_index(from, column)
10
+ end
11
+
12
+ def remove_foreign_key_index(from, column)
13
+ add_index(from, column)
14
+ add_foreign_key(from, :column => column)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module Backframe
2
+ class Railtie < ::Rails::Railtie
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)
7
+ ActiveRecord::Base.send(:include, Backframe::ActsAsOrderable)
8
+ ActiveRecord::Base.send(:include, Backframe::ActsAsUser)
9
+ ActiveRecord::Base.send(:include, Backframe::ActsAsStatus)
10
+ ActiveRecord::Migration.send(:include, Backframe::Migration)
11
+ Backframe::Mime.register_types
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Backframe
2
- VERSION = '0.0.0'
2
+ VERSION = '0.0.1'
3
3
  end
data/lib/backframe.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  require 'backframe/api'
2
2
  require 'backframe/mime'
3
3
  require 'backframe/resource'
4
+ require 'backframe/filter_sort'
5
+ require 'backframe/acts_as_orderable'
6
+ require 'backframe/acts_as_status'
7
+ require 'backframe/acts_as_user'
8
+ require 'backframe/migration'
9
+ require 'write_xlsx'
4
10
 
5
11
  module Backframe
6
12
  module Exceptions
@@ -8,3 +14,7 @@ module Backframe
8
14
  class Unauthorized < StandardError; end
9
15
  end
10
16
  end
17
+
18
+ if defined? Rails
19
+ require 'backframe/railtie'
20
+ 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.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Kops
@@ -11,6 +11,34 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2016-04-28 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: write_xlsx
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 0.83.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 0.83.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: activerecord
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '4.0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '4.0'
14
42
  - !ruby/object:Gem::Dependency
15
43
  name: activesupport
16
44
  requirement: !ruby/object:Gem::Requirement
@@ -66,12 +94,18 @@ files:
66
94
  - Rakefile
67
95
  - backframe.gemspec
68
96
  - lib/backframe.rb
97
+ - lib/backframe/acts_as_orderable.rb
98
+ - lib/backframe/acts_as_status.rb
99
+ - lib/backframe/acts_as_user.rb
69
100
  - lib/backframe/api.rb
70
101
  - lib/backframe/api/adapter.rb
71
102
  - lib/backframe/api/errors.rb
72
103
  - lib/backframe/api/headers.rb
73
104
  - lib/backframe/api/page.rb
105
+ - lib/backframe/filter_sort.rb
106
+ - lib/backframe/migration.rb
74
107
  - lib/backframe/mime.rb
108
+ - lib/backframe/railtie.rb
75
109
  - lib/backframe/resource.rb
76
110
  - lib/backframe/resource/actions.rb
77
111
  - lib/backframe/version.rb