static-record 1.0.0.pre → 1.0.0.pre.1

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: a8eb89ed57ec1a0a6fbc6574e1c1614cda528447
4
- data.tar.gz: ffffe730a97c3953064f7e2f517d840852ecf48e
3
+ metadata.gz: a561fe2ae524c134408db76ff95bad7e8b5f11c9
4
+ data.tar.gz: c0a00cf2f7342dfd97d5ebe4e18c650ba50abc81
5
5
  SHA512:
6
- metadata.gz: 0d93d7d7ebcc4b347ccad1863e4ce43d3a51688022b7e4b2292820292a3ff0eafa49f1713c1f12058da444517d6c1605ff7d0db57da3401bd630e1bab0efb731
7
- data.tar.gz: 40483219ffbe67bd87118e3d9175b5be8c7b681a6f8909b9188f1efc887f5fedc05c6a7594bdde42714fb5140d67b6be56dc099d50cfdb8bd5116330f7901b53
6
+ metadata.gz: 5f9aaf4e4bdeb208ea94137af0d1a2f0833792636c05d01aff82ccfb070e61e162e43decf9836bd1bc89e6c1b01b589b6eab058d8a74c2deb1837b506e4048f2
7
+ data.tar.gz: 9e62c0b5d76b45aec821bc2d588256bd49bf3cece1d322185c9eafb769263234b2a5a90abcdc14ba2f890f00d955d9e340579dc64dca91ff6f15fb067f4343d3
data/README.rdoc CHANGED
@@ -10,10 +10,13 @@ You can use it when you need several files inheriting a base class.
10
10
 
11
11
  Add this to your Gemfile:
12
12
 
13
- gem 'static-record'
13
+ gem 'static_record', require: 'static_record'
14
14
 
15
15
  and run the bundle install command.
16
16
 
17
+ The 'require' part is important so that Rails autoloads the library correctly.
18
+
19
+
17
20
  == Getting Started
18
21
 
19
22
  === Base class
data/lib/static_record.rb CHANGED
@@ -1,5 +1,13 @@
1
1
  require 'static_record/engine'
2
2
  require 'static_record/exceptions'
3
3
 
4
+ require 'static_record/concerns/query_building_concern'
5
+ require 'static_record/concerns/sqlite_storing_concern'
6
+
7
+ require 'static_record/models/predicates'
8
+ require 'static_record/models/querying'
9
+ require 'static_record/models/relation'
10
+ require 'static_record/models/base'
11
+
4
12
  module StaticRecord
5
13
  end
@@ -0,0 +1,105 @@
1
+ module StaticRecord
2
+ # Helps building SQL queries
3
+ module QueryBuildingConcern
4
+ extend ActiveSupport::Concern
5
+
6
+ def build_query
7
+ sql = sql_select_from
8
+ sql += sql_where unless @where_clauses.empty?
9
+ sql += sql_order unless @order_by.empty?
10
+ sql += sql_limit_offset if @sql_limit
11
+ sql
12
+ end
13
+
14
+ private
15
+
16
+ def sql_select_from
17
+ sql = "SELECT #{@columns} FROM #{@table}"
18
+ end
19
+
20
+ def sql_where
21
+ " WHERE #{where_clause_builder}"
22
+ end
23
+
24
+ def sql_order
25
+ ord_sql = ''
26
+ @order_by.each do |ord|
27
+ ord_sql += ord_sql.empty? ? ' ORDER BY' : ', '
28
+ case ord.class.name
29
+ when Hash.name
30
+ ord_sql += ord.map { |k, v| " #{@table}.#{k.to_s} #{v.to_s.upcase}" }.join(',')
31
+ when Array.name
32
+ ord_sql += ord.map { |sym| " #{@table}.#{sym.to_s} ASC" }.join(',')
33
+ when Symbol.name
34
+ ord_sql += " #{@table}.#{ord.to_s} ASC"
35
+ when String.name
36
+ ord_sql += " #{ord}"
37
+ end
38
+ end
39
+ ord_sql
40
+ end
41
+
42
+ def sql_limit_offset
43
+ sql = " LIMIT #{@sql_limit}"
44
+ sql += " OFFSET #{@sql_offset}" if @sql_offset
45
+ sql
46
+ end
47
+
48
+ def where_clause_builder
49
+ params = []
50
+ @where_clauses.map do |clause|
51
+ subquery = clause[:q]
52
+ if subquery.is_a?(Hash)
53
+ params << where_clause_from_hash(clause, subquery)
54
+ elsif subquery.is_a?(String)
55
+ params << where_clause_from_string(clause, subquery)
56
+ end
57
+
58
+ if params.size > 1
59
+ joint = clause[:chain] == :or ? 'OR' : 'AND'
60
+ params = [params.join(" #{joint} ")]
61
+ end
62
+ end
63
+
64
+ params.first
65
+ end
66
+
67
+ def where_clause_from_hash(clause, subquery)
68
+ parts = subquery.keys.map do |key|
69
+ value = subquery[key]
70
+ part = ''
71
+ if value.is_a?(Array)
72
+ # ex: where(name: ['John', 'Jack'])
73
+ # use IN operator
74
+ value.map! { |v| v =~ /^\d+$/ ? v : "\"#{v}\"" }
75
+ inverse = 'NOT ' if clause[:operator] == :not_eq
76
+ part = "#{key.to_s} #{inverse}IN (#{value.join(',')})"
77
+ else
78
+ # ex: where(name: 'John')
79
+ # use = operator
80
+ inverse = '!' if clause[:operator] == :not_eq
81
+ part = "#{key.to_s} #{inverse}= '#{value}'"
82
+ end
83
+ end
84
+ parts.join(' AND ')
85
+ end
86
+
87
+ def where_clause_from_string(clause, subquery)
88
+ final_string = subquery
89
+ if clause[:parameters].is_a?(Array)
90
+ # Anon parameters
91
+ # ex: where("name = ? OR name = ?", 'John', 'Jack')
92
+ clause[:parameters].each do |param|
93
+ final_string.sub!(/\?/, "\"#{param}\"")
94
+ end
95
+ elsif clause[:parameters].is_a?(Hash)
96
+ # Named parameters (placeholder condition)
97
+ # ex: where("name = :one OR name = :two", one: 'John', two: 'Smith')
98
+ clause[:parameters].each do |key, value|
99
+ final_string.sub!(":#{key}", "\"#{value}\"")
100
+ end
101
+ end
102
+ final_string
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,63 @@
1
+ module StaticRecord
2
+ # Reads ruby files whose path matches path pattern and store them
3
+ # as records in an SQLite3 database
4
+ module SqliteStoringConcern
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods # :nodoc:
8
+ def create_store
9
+ columns = class_variable_get(:@@_columns)
10
+ begin
11
+ dbname = Rails.root.join('db', "static_#{store}.sqlite3").to_s
12
+ SQLite3::Database.new(dbname)
13
+ db = SQLite3::Database.open(dbname)
14
+ db.execute("DROP TABLE IF EXISTS #{store}")
15
+ create_table(db, columns)
16
+ load_records.each_with_index do |record, index|
17
+ insert_into_database(db, record, index, columns)
18
+ end
19
+ rescue SQLite3::Exception => e
20
+ puts 'Exception occurred', e
21
+ ensure
22
+ db.close if db
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def create_table(db, columns)
29
+ cols = columns.map { |c| c.to_s + ' TEXT' }.join(', ')
30
+ sql = "CREATE TABLE #{store}(id INTEGER PRIMARY KEY, klass TEXT, #{cols})"
31
+ db.execute(sql)
32
+ end
33
+
34
+ def insert_into_database(db, record, index, columns)
35
+ attrs = record.constantize.new.attributes
36
+ sqlized = [index.to_s, "'#{record}'"] # id, klass
37
+ sqlized += columns.map { |c| "'#{attrs[c]}'" } # model's attributes
38
+ db.execute("INSERT INTO #{store} VALUES(#{sqlized.join(', ')})")
39
+ end
40
+
41
+ def load_records
42
+ records = []
43
+ Dir.glob(path_pattern) do |filepath|
44
+ klass = get_class_from_file(filepath)
45
+ if klass
46
+ require filepath
47
+ records << klass
48
+ end
49
+ end
50
+ records
51
+ end
52
+
53
+ def get_class_from_file(filepath)
54
+ klass = nil
55
+ File.open(filepath) do |file|
56
+ match = file.grep(/class\s+([a-zA-Z0-9_]+)/)
57
+ klass = match.first.chomp.gsub(/class\s+/, '').split(' ')[0] if match
58
+ end
59
+ klass
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,3 +1,3 @@
1
1
  module StaticRecord
2
- VERSION = '1.0.0.pre'.freeze
2
+ VERSION = '1.0.0.pre.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: static-record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre
4
+ version: 1.0.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hugo Chevalier
@@ -99,17 +99,17 @@ files:
99
99
  - app/assets/stylesheets/static_record/application.css
100
100
  - app/controllers/static_record/application_controller.rb
101
101
  - app/helpers/static_record/application_helper.rb
102
- - app/models/concerns/query_building_concern.rb
103
- - app/models/concerns/sqlite_storing_concern.rb
104
- - app/models/static_record/base.rb
105
- - app/models/static_record/predicates.rb
106
- - app/models/static_record/querying.rb
107
- - app/models/static_record/relation.rb
108
102
  - app/views/layouts/static_record/application.html.erb
109
103
  - config/routes.rb
110
104
  - lib/static_record.rb
105
+ - lib/static_record/concerns/query_building_concern.rb
106
+ - lib/static_record/concerns/sqlite_storing_concern.rb
111
107
  - lib/static_record/engine.rb
112
108
  - lib/static_record/exceptions.rb
109
+ - lib/static_record/models/base.rb
110
+ - lib/static_record/models/predicates.rb
111
+ - lib/static_record/models/querying.rb
112
+ - lib/static_record/models/relation.rb
113
113
  - lib/static_record/version.rb
114
114
  - lib/tasks/static_record_tasks.rake
115
115
  - spec/models/static_record/base_spec.rb
@@ -1,103 +0,0 @@
1
- # Helps building SQL queries
2
- module QueryBuildingConcern
3
- extend ActiveSupport::Concern
4
-
5
- def build_query
6
- sql = sql_select_from
7
- sql += sql_where unless @where_clauses.empty?
8
- sql += sql_order unless @order_by.empty?
9
- sql += sql_limit_offset if @sql_limit
10
- sql
11
- end
12
-
13
- private
14
-
15
- def sql_select_from
16
- sql = "SELECT #{@columns} FROM #{@table}"
17
- end
18
-
19
- def sql_where
20
- " WHERE #{where_clause_builder}"
21
- end
22
-
23
- def sql_order
24
- ord_sql = ''
25
- @order_by.each do |ord|
26
- ord_sql += ord_sql.empty? ? ' ORDER BY' : ', '
27
- case ord.class.name
28
- when Hash.name
29
- ord_sql += ord.map { |k, v| " #{@table}.#{k.to_s} #{v.to_s.upcase}" }.join(',')
30
- when Array.name
31
- ord_sql += ord.map { |sym| " #{@table}.#{sym.to_s} ASC" }.join(',')
32
- when Symbol.name
33
- ord_sql += " #{@table}.#{ord.to_s} ASC"
34
- when String.name
35
- ord_sql += " #{ord}"
36
- end
37
- end
38
- ord_sql
39
- end
40
-
41
- def sql_limit_offset
42
- sql = " LIMIT #{@sql_limit}"
43
- sql += " OFFSET #{@sql_offset}" if @sql_offset
44
- sql
45
- end
46
-
47
- def where_clause_builder
48
- params = []
49
- @where_clauses.map do |clause|
50
- subquery = clause[:q]
51
- if subquery.is_a?(Hash)
52
- params << where_clause_from_hash(clause, subquery)
53
- elsif subquery.is_a?(String)
54
- params << where_clause_from_string(clause, subquery)
55
- end
56
-
57
- if params.size > 1
58
- joint = clause[:chain] == :or ? 'OR' : 'AND'
59
- params = [params.join(" #{joint} ")]
60
- end
61
- end
62
-
63
- params.first
64
- end
65
-
66
- def where_clause_from_hash(clause, subquery)
67
- parts = subquery.keys.map do |key|
68
- value = subquery[key]
69
- part = ''
70
- if value.is_a?(Array)
71
- # ex: where(name: ['John', 'Jack'])
72
- # use IN operator
73
- value.map! { |v| v =~ /^\d+$/ ? v : "\"#{v}\"" }
74
- inverse = 'NOT ' if clause[:operator] == :not_eq
75
- part = "#{key.to_s} #{inverse}IN (#{value.join(',')})"
76
- else
77
- # ex: where(name: 'John')
78
- # use = operator
79
- inverse = '!' if clause[:operator] == :not_eq
80
- part = "#{key.to_s} #{inverse}= '#{value}'"
81
- end
82
- end
83
- parts.join(' AND ')
84
- end
85
-
86
- def where_clause_from_string(clause, subquery)
87
- final_string = subquery
88
- if clause[:parameters].is_a?(Array)
89
- # Anon parameters
90
- # ex: where("name = ? OR name = ?", 'John', 'Jack')
91
- clause[:parameters].each do |param|
92
- final_string.sub!(/\?/, "\"#{param}\"")
93
- end
94
- elsif clause[:parameters].is_a?(Hash)
95
- # Named parameters (placeholder condition)
96
- # ex: where("name = :one OR name = :two", one: 'John', two: 'Smith')
97
- clause[:parameters].each do |key, value|
98
- final_string.sub!(":#{key}", "\"#{value}\"")
99
- end
100
- end
101
- final_string
102
- end
103
- end
@@ -1,61 +0,0 @@
1
- # Reads ruby files whose path matches path pattern and store them
2
- # as records in an SQLite3 database
3
- module SqliteStoringConcern
4
- extend ActiveSupport::Concern
5
-
6
- module ClassMethods # :nodoc:
7
- def create_store
8
- columns = class_variable_get(:@@_columns)
9
- begin
10
- dbname = Rails.root.join('db', "static_#{store}.sqlite3").to_s
11
- SQLite3::Database.new(dbname)
12
- db = SQLite3::Database.open(dbname)
13
- db.execute("DROP TABLE IF EXISTS #{store}")
14
- create_table(db, columns)
15
- load_records.each_with_index do |record, index|
16
- insert_into_database(db, record, index, columns)
17
- end
18
- rescue SQLite3::Exception => e
19
- puts 'Exception occurred', e
20
- ensure
21
- db.close if db
22
- end
23
- end
24
-
25
- private
26
-
27
- def create_table(db, columns)
28
- cols = columns.map { |c| c.to_s + ' TEXT' }.join(', ')
29
- sql = "CREATE TABLE #{store}(id INTEGER PRIMARY KEY, klass TEXT, #{cols})"
30
- db.execute(sql)
31
- end
32
-
33
- def insert_into_database(db, record, index, columns)
34
- attrs = record.constantize.new.attributes
35
- sqlized = [index.to_s, "'#{record}'"] # id, klass
36
- sqlized += columns.map { |c| "'#{attrs[c]}'" } # model's attributes
37
- db.execute("INSERT INTO #{store} VALUES(#{sqlized.join(', ')})")
38
- end
39
-
40
- def load_records
41
- records = []
42
- Dir.glob(path_pattern) do |filepath|
43
- klass = get_class_from_file(filepath)
44
- if klass
45
- require filepath
46
- records << klass
47
- end
48
- end
49
- records
50
- end
51
-
52
- def get_class_from_file(filepath)
53
- klass = nil
54
- File.open(filepath) do |file|
55
- match = file.grep(/class\s+([a-zA-Z0-9_]+)/)
56
- klass = match.first.chomp.gsub(/class\s+/, '').split(' ')[0] if match
57
- end
58
- klass
59
- end
60
- end
61
- end