bomdb 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ require 'json'
2
+
3
+ module BomDB
4
+ module Import
5
+ class Editions < Import::Base
6
+ tables :editions
7
+
8
+ # Expected data format is:
9
+ # [
10
+ # [edition_year:Integer, edition_name:String],
11
+ # ...
12
+ # ]
13
+ def import_json(data, **args)
14
+ data.each do |year, name|
15
+ @db[:editions].insert(
16
+ edition_year: year,
17
+ edition_name: name
18
+ )
19
+ end
20
+ Import::Result.new(success: true)
21
+ rescue Sequel::UniqueConstraintViolation => e
22
+ Import::Result.new(success: false, error: e)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,65 @@
1
+ require 'json'
2
+
3
+ module BomDB
4
+ module Import
5
+ class Refs < Import::Base
6
+ tables :refs
7
+
8
+ # Expected data format is:
9
+ # {
10
+ # (ref_name:String): [
11
+ # {
12
+ # "book":String,"chapter":Int,"verse":Int,
13
+ # "ref_book":String,"ref_chapter":Int,"ref_verse":Int,
14
+ # "is_parallel":Bool,"is_quotation":Bool
15
+ # }
16
+ # ...
17
+ # ]
18
+ # }
19
+ def import_json(data, **args)
20
+ data.each_pair do |ref_name, rows|
21
+ rows.each do |r|
22
+ verse = @db[:verses].
23
+ join(:books, :book_id => :book_id).
24
+ where(
25
+ book_name: r['book'],
26
+ verse_chapter: r['chapter'],
27
+ verse_number: r['verse'],
28
+ verse_heading: nil).
29
+ first
30
+ if verse.nil?
31
+ return Import::Result.new(
32
+ success: false,
33
+ error: "Unable to find verse #{r['book']} #{r['chapter']}:#{r['verse']}"
34
+ )
35
+ end
36
+
37
+ @db[:refs].insert(
38
+ verse_id: verse[:verse_id],
39
+ ref_name: ref_name,
40
+ ref_book: r['ref_book'],
41
+ ref_chapter: r['ref_chapter'],
42
+ ref_verse: r['ref_verse'],
43
+ ref_is_parallel: r['is_parallel'],
44
+ ref_is_quotation: r['is_quotation']
45
+ )
46
+ end
47
+ end
48
+ Import::Result.new(success: true)
49
+ rescue Sequel::UniqueConstraintViolation => e
50
+ Import::Result.new(success: false, error: e)
51
+ end
52
+
53
+ # def list
54
+ # @db[
55
+ # "SELECT book_name, verse_chapter, verse_number, ref_name, ref_book, ref_chapter, ref_verse " +
56
+ # "FROM `verses` v " +
57
+ # "JOIN `books` b ON b.book_id = v.book_id " +
58
+ # "JOIN `refs` r ON r.verse_id = v.verse_id " +
59
+ # "ORDER BY ref_book, ref_chapter, ref_verse"
60
+ # ].map(&:inspect).join("\n")
61
+ # end
62
+
63
+ end
64
+ end
65
+ end
@@ -1,62 +1,43 @@
1
+ require 'json'
2
+ require 'bomdb/models/verse'
3
+
1
4
  module BomDB
2
5
  module Import
3
6
  class Verses < Import::Base
4
- TABLES = [:books, :verses, :versions, :contents]
5
-
6
- def reset
7
- schema.reset(*(TABLES - [:books]))
8
- end
9
-
10
- def json(data)
11
- if schema.has_tables?(*TABLES)
12
- ensure_parsed_json(data).each_pair do |book_name, year_versions|
13
- year_versions.each do |year_version|
14
- year_version.each_pair do |year, d|
15
- m = d["meta"]
16
-
17
- book = @db[:books].where(:book_name => book_name).first
18
- if book.nil?
19
- return Import::Result.new(success: false, error: "Unable to find book '#{book_name}'")
20
- end
7
+ tables :books, :verses
21
8
 
22
- verse = @db[:verses].where(
23
- :book_id => book[:book_id],
24
- :verse_chapter => m["chapter"],
25
- :verse_number => m["verse"],
26
- :verse_heading => m["heading"] ? 0 : nil
27
- ).first
28
- verse_id = (verse && verse[:verse_id]) || @db[:verses].insert(
29
- book_id: book[:book_id],
30
- verse_chapter: m["chapter"],
31
- verse_number: m["verse"],
32
- verse_heading: m["heading"] ? 0 : nil
33
- )
34
-
35
- version = @db[:versions].where(:version_year => year).first
36
- version_id = (version && version[:version_id]) || @db[:versions].insert(
37
- version_name: year.to_s,
38
- version_year: year
39
- )
9
+ # Expected data format is:
10
+ # [
11
+ # {
12
+ # "book": String,
13
+ # "chapter": Int,
14
+ # "verses": Int
15
+ # },
16
+ # ...
17
+ # ]
18
+ def import_json(data, **args)
19
+ data.each do |r|
20
+ # Create a heading per chapter
21
+ Models::Verse.new(@db).find_or_create(
22
+ chapter: r['chapter'],
23
+ verse: nil,
24
+ book_name: r['book'],
25
+ heading: true
26
+ )
40
27
 
41
- @db[:contents].insert(
42
- version_id: version_id,
43
- verse_id: verse_id,
44
- content_body: d["content"]
45
- )
46
- end
47
- end
28
+ # Create as many verses as is called for per chapter
29
+ (1..r['verses']).each do |verse_number|
30
+ Models::Verse.new(@db).find_or_create(
31
+ chapter: r['chapter'],
32
+ verse: verse_number,
33
+ book_name: r['book']
34
+ )
48
35
  end
49
- Import::Result.new(success: true)
50
- else
51
- Import::Result.new(
52
- success: false,
53
- error: "Database tables #{TABLES.join(', ')} not ready. Try again with --reset."
54
- )
55
36
  end
37
+ Import::Result.new(success: true)
56
38
  rescue Sequel::UniqueConstraintViolation => e
57
39
  Import::Result.new(success: false, error: e)
58
40
  end
59
-
60
41
  end
61
42
  end
62
- end
43
+ end
@@ -0,0 +1,27 @@
1
+ module BomDB
2
+ module Models
3
+ class Edition
4
+ def initialize(db)
5
+ @db = db
6
+ end
7
+
8
+ # Find an edition and return a hash, or nil if not found
9
+ def find(edition_name_prefix)
10
+ @db[:editions].
11
+ where(Sequel.like(:edition_name, "#{edition_name_prefix}%")).
12
+ or(:edition_year => edition_name_prefix).
13
+ first
14
+ end
15
+
16
+ # Returns an edition_id, either found in the db, or created as necessary
17
+ def find_or_create(year, name)
18
+ found = @db[:editions].where(edition_year: year, edition_name: name).first
19
+ return found[:edition_id] if found
20
+ @db[:editions].insert(
21
+ edition_year: year,
22
+ edition_name: name
23
+ )
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,47 @@
1
+ module BomDB
2
+ module Models
3
+ class Verse
4
+ def initialize(db)
5
+ @db = db
6
+ end
7
+
8
+ # Find a verse and return a hash, or nil if not found
9
+ def find(chapter:, verse:, book_name: nil, book_id: nil, heading: false)
10
+ @db[:verses].where(
11
+ book_id: book_by_name_or_id(book_name, book_id),
12
+ verse_chapter: chapter,
13
+ verse_number: verse,
14
+ verse_heading: heading ? 0 : nil
15
+ ).first
16
+ end
17
+
18
+ # Create a verse and return its verse_id
19
+ def create(chapter:, verse:, book_name: nil, book_id: nil, heading: false)
20
+ @db[:verses].insert(
21
+ book_id: book_by_name_or_id(book_name, book_id),
22
+ verse_chapter: chapter,
23
+ verse_number: verse,
24
+ verse_heading: heading ? 0 : nil
25
+ )
26
+ end
27
+
28
+ # Returns a verse_id after finding or creating the verse
29
+ def find_or_create(**args)
30
+ verse = find(**args)
31
+ (verse && verse[:verse_id]) || create(**args)
32
+ end
33
+
34
+ protected
35
+
36
+ def book_by_name_or_id(book_name, book_id)
37
+ if book_id.nil? and book_name.nil?
38
+ raise ArgumentError, "book_name or book_id is required"
39
+ elsif book_id.nil?
40
+ @db[:books].where(book_name: book_name).first[:book_id]
41
+ else
42
+ book_id
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
data/lib/bomdb/query.rb CHANGED
@@ -1,40 +1,51 @@
1
+ require 'bomdb/models/edition'
2
+
1
3
  module BomDB
2
4
  class Query
3
- def initialize(edition:, exclude: nil)
5
+ def initialize(edition:, exclude: nil, headings: false)
4
6
  @edition = edition
5
7
  @exclude = exclude
8
+ @headings = headings
6
9
  end
7
10
 
8
- def query(headings: false)
11
+ def query
9
12
  db = BomDB.db
13
+ edition_model = Models::Edition.new(db)
14
+ edition = edition_model.find(@edition)
15
+ if edition.nil?
16
+ raise "Unable to find edition: #{@edition}"
17
+ end
10
18
  q = db[:verses].
11
19
  join(:books, :book_id => :book_id).
12
- join(:versions).
13
- join(:contents, :version_id => :version_id, :verse_id => :verses__verse_id).
20
+ join(:editions).
21
+ join(:contents, :edition_id => :edition_id, :verse_id => :verses__verse_id).
14
22
  order(:book_sort, :verse_heading, :verse_chapter, :verse_number).
15
23
  select(:book_name, :verse_chapter, :verse_number, :content_body)
16
- q.where!(:version_name => @edition) if @edition
17
- q.where!(:verse_heading => nil) unless headings
24
+ q.where!(:editions__edition_id => edition[:edition_id]) if @edition
25
+ q.where!(:verse_heading => nil) unless @headings
18
26
  q.exclude!(:verses__verse_id => db[:refs].select(:verse_id).where(:ref_name => @exclude)) if @exclude
19
- # require 'byebug'; byebug
20
- # p q
21
27
  q
22
28
  end
23
29
 
24
- def print(book: true, chapter: true, verse: true, sep: ' ')
30
+ def each(&block)
31
+ query.each(&block)
32
+ end
33
+
34
+ def print(verse_format: nil, body_format: nil, sep: ' ', linesep: "\n", io: $stdout)
25
35
  shown = false
36
+ verse_format ||= lambda{ |book, chapter, verse| "#{book}#{sep}#{chapter}:#{verse}" }
37
+ body_format ||= lambda{ |body| body + linesep }
26
38
  query.each do |row|
27
39
  shown = true
28
- puts [
29
- book && row[:book_name] || nil,
30
- (chapter || verse) && [
31
- chapter && row[:verse_chapter] || nil,
32
- verse && row[:verse_number] || nil
33
- ].compact.join(":") || nil,
34
- row[:content_body]
35
- ].compact.join(sep)
40
+ io.print verse_format[
41
+ row[:book_name],
42
+ row[:verse_chapter],
43
+ row[:verse_number]
44
+ ]
45
+ io.print sep
46
+ io.print body_format[ row[:content_body] ]
36
47
  end
37
- puts "Nothing found" unless shown
48
+ io.puts "Nothing found" unless shown
38
49
  end
39
50
  end
40
51
  end
data/lib/bomdb/schema.rb CHANGED
@@ -1,62 +1,61 @@
1
1
  require 'set'
2
+ require 'sequel'
3
+ require 'fileutils'
2
4
 
3
5
  module BomDB
4
6
  class Schema
7
+ attr_reader :db
8
+
5
9
  def initialize(db)
6
10
  @db = db
7
11
  end
8
12
 
9
- def has_tables?(*table_names)
10
- Set.new(@db.tables) >= Set.new(table_names)
11
- end
12
-
13
- def reset(*table_names)
14
- drop_tables(table_names)
15
- create_tables(table_names)
13
+ # create a new database
14
+ def self.create(db_path, tables = :all)
15
+ FileUtils.rm(db_path) if File.exist?(db_path)
16
+ new(Sequel.sqlite(db_path)).create_tables(tables)
16
17
  end
17
18
 
18
- def drop_tables(table_names = nil)
19
- (table_names || @db.tables).each do |name|
20
- @db.drop_table(name) if @db.tables.include?(name)
21
- end
19
+ def has_tables?(tables)
20
+ Set.new(@db.tables) >= Set.new(tables)
22
21
  end
23
22
 
24
- def create_tables(table_names = nil)
23
+ def create_tables(tables = :all)
25
24
  @db.create_table(:books) do
26
25
  primary_key :book_id
27
26
 
28
27
  string :book_name, :unique => true
29
28
  string :book_group
30
29
  integer :book_sort
31
- end if include?(table_names, :books)
30
+ end if include?(tables, :books)
32
31
 
33
32
  @db.create_table(:verses) do
34
33
  primary_key :verse_id
35
34
  foreign_key :book_id, :books
36
35
 
37
36
  integer :verse_chapter, :null => true
38
- integer :verse_number, :null => true
37
+ integer :verse_number, :null => true
39
38
  integer :verse_heading, :null => true
40
39
 
41
40
  index [:book_id, :verse_chapter, :verse_number, :verse_heading], :unique => true
42
- end if include?(table_names, :verses)
41
+ end if include?(tables, :verses)
43
42
 
44
- @db.create_table(:versions) do
45
- primary_key :version_id
43
+ @db.create_table(:editions) do
44
+ primary_key :edition_id
46
45
 
47
- string :version_name
48
- integer :version_year
49
- end if include?(table_names, :versions)
46
+ integer :edition_year
47
+ string :edition_name, :unique => true
48
+ end if include?(tables, :editions)
50
49
 
51
50
  @db.create_table(:contents) do
52
51
  primary_key :content_id
53
- foreign_key :version_id, :versions
52
+ foreign_key :edition_id, :editions
54
53
  foreign_key :verse_id, :verses
55
54
 
56
55
  string :content_body
57
56
 
58
- index [:version_id, :verse_id], :unique => true
59
- end if include?(table_names, :contents)
57
+ index [:edition_id, :verse_id], :unique => true
58
+ end if include?(tables, :contents)
60
59
 
61
60
  @db.create_table(:refs) do
62
61
  primary_key :ref_id
@@ -71,7 +70,7 @@ module BomDB
71
70
  integer :ref_page_end
72
71
  boolean :ref_is_parallel
73
72
  boolean :ref_is_quotation
74
- end if include?(table_names, :refs)
73
+ end if include?(tables, :refs)
75
74
 
76
75
  @db.create_table(:notes) do
77
76
  primary_key :note_id
@@ -79,14 +78,15 @@ module BomDB
79
78
 
80
79
  string :note_highlight
81
80
  string :note_body
82
- end if include?(table_names, :notes)
81
+ end if include?(tables, :notes)
82
+
83
+ self
83
84
  end
84
85
 
85
86
  protected
86
87
 
87
- def include?(table_names, name)
88
- table_names.nil? ||
89
- table_names.map{ |n| n.to_sym }.include?(name.to_sym)
88
+ def include?(tables, name)
89
+ tables == :all || tables.map{ |n| n.to_sym }.include?(name.to_sym)
90
90
  end
91
91
  end
92
92
  end