#!/usr/bin/env ruby # Copyright 2013 Dafydd Crosby (dafydd@dafyddcrosby.com) # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'optparse' require 'optparse/date' require 'ostruct' require 'rubygems' require 'active_record' require 'yaml' require 'pathname' require 'booklist' require 'date' module Booklist options = OpenStruct.new options.act_num = 0 usage = nil OptionParser.new do |opts| opts.banner = "Usage: booklist [options]" opts.separator "Actions:" opts.on("-a", "--add", "Add a book record", "(--title is required)") do options.act_num += 1 options.action = :add end opts.on("-e", "--edit [ID]", Integer, "Edit a book record") do |id| options.act_num += 1 options.id = id if id options.action = :edit end opts.on("-d", "--delete [ID]", Integer, "Delete a book record") do |id| options.act_num += 1 options.id = id if id options.action = :delete end opts.on("-s", "--search", "Search for a book") do options.act_num += 1 options.action = :search end opts.on("-r", "--read [ID]", Integer, "Show a book record's details") do |id| options.act_num += 1 options.id = id if id options.action = :read end opts.on("--list", "List all books in the database") do options.act_num += 1 options.action = :list end opts.separator "" opts.separator "Book details:" # Book details opts.on("--title TITLE", "Book title") do |title| options.title = title end opts.on("--state STATE", "What state the book is in (read, to-read, reading, abandoned)") do |state| options.state = state end opts.on("--author AUTHOR", "Book author") do |author| options.author = author end opts.on("--addn_authors ADDN_AUTHORS", "Additional authors") do |aa| options.addn_authors = aa end opts.on("--tags X,Y,Z", Array, "List of tags") do |tags| options.tags = tags end opts.on("--date_read DATE", Date, "Date read (eg 2014-02-14)") do |dr| options.date_read = dr end opts.on("--id ID", Integer, "Book ID number") do |id| options.id = id end opts.separator "" opts.separator "Common options:" # TODO - configurable booklist path #opts.on("-c", "--config FILE", "Use configuration file") do |file| # options.config_file = file #end opts.on("--debug", "Debug mode") do options.debug = true end opts.on("--updatedb", "Update the book database schema") do options.update_schema = true end opts.on_tail("--version", "Get the booklist version") do puts Booklist::VERSION exit end opts.on_tail("-h", "--help", "Show this message") do puts opts exit end usage = opts end.parse! if options.act_num > 1 puts "Please only use one action." puts usage exit end # TODO Create configuration directory if it doesn't exist # mkdir ~/.booklist # TODO configurable booklist path booklist_db_path = File.join(Dir.home, '.booklist', 'booklist.db') ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => booklist_db_path.to_s) ActiveRecord::Base.logger = Logger.new(STDERR) if options.debug if options.update_schema || !File.exist?(booklist_db_path) ActiveRecord::Migrator.migrate('db/migrate') end if options.act_num = 1 if options.action == :add if !options.title || options.title == "" puts "Please add a --title with the book name" puts usage exit end book = Book.new do |b| b.title = options.title b.author = options.author if options.author b.addn_authors = options.addn_authors if options.addn_authors b.state = options.state if options.state b.date_read = options.date_read if options.date_read b.tag_list = options.tags if options.tags end book.save book.cli_display elsif options.action == :edit book = Book.find_by(id: options.id) if book book.title = options.title if options.title book.author = options.author if options.author book.addn_authors = options.addn_authors if options.addn_authors book.state = options.state if options.state book.date_read = options.date_read if options.date_read book.tag_list = options.tags if options.tags book.save book.cli_display else puts "No book with ID of #{options.id} was found" end elsif options.action == :delete book = Book.find_by(id: options.id) book.destroy elsif options.action == :read book = Book.find_by(id: options.id) if book book.cli_display else puts "No book with ID of #{options.id} was found" end elsif options.action == :search books = [] books += Book.where(["title LIKE ?", "%#{options.title}%"]).to_a if options.title books += Book.where(["author LIKE ? or addn_authors LIKE ?", "%#{options.author}%", "%#{options.author}%"]).to_a if options.author books += Book.where(["author LIKE ? or addn_authors LIKE ?", "%#{options.addn_authors}%", "%#{options.addn_authors}%"]).to_a if options.addn_authors books += Book.where(["state = ?", "%#{options.state}%"]).to_a if options.state books.uniq! books.sort!{ |a, b| a.id <=> b.id} books.select!{ |b| b.state == options.state} if options.state books.each { |b| b.cli_display } elsif options.action == :list books = Book.all books.each{ |b| b.cli_display } end elsif options.act_num > 1 puts "Please only use one action." puts usage exit end end