Module: StickyFlag::Database

Included in:
ThorApp
Defined in:
lib/stickyflag/database.rb

Instance Method Summary collapse

Instance Method Details

#clear_database_tags(file_name) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/stickyflag/database.rb', line 108

def clear_database_tags(file_name)
  file_id = get_file_id file_name
  @database[:tagged_files].where(:file => file_id).delete

  # That operation might have removed the last instance of a tag, clean up
  # the tag list
  @database[:tag_list].each do |row|
    raise Thor::Error.new("INTERNAL ERROR: Database row error in tag_list") unless row.include? :id
    tag_id = row[:id]
    
    if @database[:tagged_files].where(:tag => tag_id).empty?
      @database[:tag_list].where(:id => tag_id).delete
    end
  end
end

#create_tablesObject



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/stickyflag/database.rb', line 26

def create_tables
  @database.create_table?(:tag_list) do
    primary_key :id, :type => Bignum
    String :tag_name, :text => true
  end
  @database.create_table?(:file_list) do
    primary_key :id, :type => Bignum
    String :file_name, :text => true
  end
  @database.create_table?(:tagged_files) do
    primary_key :id
    Bignum :file
    Bignum :tag
  end
end

#drop_tablesObject



42
43
44
# File 'lib/stickyflag/database.rb', line 42

def drop_tables
  @database.drop_table(:tag_list, :file_list, :tagged_files)
end

#files_for_tags(tags) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/stickyflag/database.rb', line 124

def files_for_tags(tags)
  # Map tags to tag IDs, but don't add any missing tags
  bad_tag = false
  tag_ids = []
  tags.each do |tag|
    tag_id = @database[:tag_list].where(:tag_name => tag).get(:id)
    unless tag_id
      say_status :warning, "Tag '#{tag}' is not present in the database (try `stickyflag update`)", :yellow unless options.quiet?
      bad_tag = true
      next
    end
  
    tag_ids << tag_id
  end
  return [] if bad_tag

  file_rows = @database[:tagged_files].where(:tag => tag_ids).group_by(:file).having{[[count(:*){}, tag_ids.count]]}
  if file_rows.empty?
    say_status :warning, "Requested combination of tags not found", :yellow unless options.quiet?
    return []
  end

  files = []
  file_rows.each do |row|
    file_id = row[:file]
    file = @database[:file_list].where(:id => file_id).get(:file_name)
    raise Thor::Error.new("ERROR: Could not get file_name for id saved in database (re-run `stickyflag update`)") unless file
  
    files << file
  end

  files
end

#get_file_id(file_name) ⇒ Object



55
56
57
58
59
60
61
62
# File 'lib/stickyflag/database.rb', line 55

def get_file_id(file_name)
  file_id = @database[:file_list].where(:file_name => file_name).get(:id)
  unless file_id
    file_id = @database[:file_list].insert(:file_name => file_name)
  end

  file_id
end

#get_tag_id(tag) ⇒ Object



46
47
48
49
50
51
52
53
# File 'lib/stickyflag/database.rb', line 46

def get_tag_id(tag)
  tag_id = @database[:tag_list].where(:tag_name => tag).get(:id)
  unless tag_id
    tag_id = @database[:tag_list].insert(:tag_name => tag)
  end
  
  tag_id
end

#load_databaseObject

Raises:

  • (Thor::Error)


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/stickyflag/database.rb', line 7

def load_database
  @database.disconnect if @database
  
  if RUBY_PLATFORM == 'java'
    @database = Sequel.connect("jdbc:sqlite:#{database_path}")
  else
    @database = Sequel.sqlite(:database => database_path)
  end
  raise Thor::Error.new("ERROR: Could not create database at '#{database_path}'") if @database.nil?
  
  create_tables
  
  # Do not do automatic cleanup from the RSpec test suite; this registers
  # dozens of at_exit hooks and crashes Ruby
  unless ENV['RSPEC_TESTING']
    at_exit { @database.disconnect }
  end
end

#set_database_tag(file_name, tag) ⇒ Object



88
89
90
91
92
93
94
95
# File 'lib/stickyflag/database.rb', line 88

def set_database_tag(file_name, tag)
  # Don't put in multiple entries for the same tag
  file_id = get_file_id file_name
  tag_id = get_tag_id tag
  
  return unless @database[:tagged_files].where(:file => file_id).and(:tag => tag_id).empty?
  @database[:tagged_files].insert(:file => file_id, :tag => tag_id)
end

#tag_listObject



158
159
160
# File 'lib/stickyflag/database.rb', line 158

def tag_list
  @database[:tag_list].map { |r| r[:tag_name] }
end

#unset_database_tag(file_name, tag) ⇒ Object



97
98
99
100
101
102
103
104
105
106
# File 'lib/stickyflag/database.rb', line 97

def unset_database_tag(file_name, tag)
  file_id = get_file_id file_name
  tag_id = get_tag_id tag
  @database[:tagged_files].where(:file => file_id).and(:tag => tag_id).delete

  # See if that was the last file with this tag, and delete it if so
  if @database[:tagged_files].where(:tag => tag_id).empty?
    @database[:tag_list].where(:id => tag_id).delete
  end
end

#update_database_from_files(directory = '.') ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/stickyflag/database.rb', line 64

def update_database_from_files(directory = '.')
  drop_tables
  create_tables

  Dir.glob(File.join(directory, '**', "*{#{available_tagging_extensions.join(',')}}")).each do |file|
    begin
      tags = get_tags_for file
    rescue Thor::Error
      # Just skip this file, then, don't error out entirely
      say_status :warning, "Could not read tags from '#{file}', despite a valid extension", :yellow
      next
    end
    
    # Don't record files in the DB that have no tags
    next if tags.nil? || tags.empty?
  
    file_id = get_file_id file      
    tags.each do |tag|
      tag_id = get_tag_id tag
      @database[:tagged_files].insert(:file => file_id, :tag => tag_id)
    end
  end
end