Skip to content

Commit

Permalink
Merge pull request #3 from masa21kik/refact-0607
Browse files Browse the repository at this point in the history
[WIP] Refactor 0607
  • Loading branch information
masa21kik committed Jun 9, 2014
2 parents 0873698 + 7f47db4 commit 4b1a13e
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 148 deletions.
58 changes: 1 addition & 57 deletions bin/json_cli
Original file line number Diff line number Diff line change
@@ -1,60 +1,4 @@
#!/usr/bin/env ruby
require 'json_cli'
require 'thor'

module JsonCli
class CLI < Thor
desc "left_join RIGHT_FILE [LEFT_FILE]", "left outer join of json files"
option :key, :required => true, :aliases => :k
def left_join(right_file, left_file = nil)
left_io = left_file.nil? ? STDIN : File.open(left_file, 'r')
right_io = File.open(right_file, 'r')
JsonCli::JoinJson.left_join(left_io, right_io, options[:key])
left_io.close
right_io.close
end

desc "right_join RIGHT_FILE [LEFT_FILE]", "right outer join of json files"
option :key, :required => true, :aliases => :k
def right_join(right_file, left_file = nil)
left_io = left_file.nil? ? STDIN : File.open(left_file, 'r')
right_io = File.open(right_file, 'r')
JsonCli::JoinJson.right_join(left_io, right_io, options[:key])
left_io.close
right_io.close
end

desc "inner_join RIGHT_FILE [LEFT_FILE]", "inner join of json files"
option :key, :required => true, :aliases => :k
def inner_join(right_file, left_file = nil)
left_io = left_file.nil? ? STDIN : File.open(left_file, 'r')
right_io = File.open(right_file, 'r')
JsonCli::JoinJson.inner_join(left_io, right_io, options[:key])
left_io.close
right_io.close
end

desc "unwind_array [JSON_FILE]", "unwind array of json file"
option :key, :required => true, :aliases => :k
def unwind_array(json_file = nil)
io = json_file.nil? ? STDIN : File.open(json_file, 'r')
JsonCli::UnwindJson.unwind_array(io, options[:key])
io.close
end

desc "unwind_hash [JSON_FILE]", "unwind hash of json file"
option :key, :required => true, :aliases => :k
option :flatten, :type => :boolean, :aliases => :f
option :key_label
option :value_label
def unwind_hash(json_file = nil)
io = json_file.nil? ? STDIN : File.open(json_file, 'r')
opt = {}
options.select{|k,v| k != :key}.each{|k,v| opt[k.to_sym] = v}
JsonCli::UnwindJson.unwind_hash(io, options[:key], opt)
io.close
end
end
end

require 'json_cli'
JsonCli::CLI.start(ARGV)
6 changes: 4 additions & 2 deletions lib/json_cli.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require 'json_cli/version'
require 'json_cli/cli'
require 'json_cli/command/base'
require 'json_cli/command/join'
require 'json_cli/command/unwind'

# Base module
module JsonCli
require 'json_cli/join'
require 'json_cli/unwind'
end
70 changes: 70 additions & 0 deletions lib/json_cli/cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require 'thor'

module JsonCli
# CLI class
class CLI < Thor
class_option :output, aliases: :o, default: '/dev/stdout'

desc 'left_join', 'left outer join of json files'
option :join_key, required: true, aliases: :k
option :join_file, required: true, aliases: :j
option :base_file, aliases: :b, default: '/dev/stdin'
def left_join
join_common(__method__)
end

desc 'right_join', 'right outer join of json files'
option :join_key, required: true, aliases: :k
option :join_file, required: true, aliases: :j
option :base_file, aliases: :b, default: '/dev/stdin'
def right_join
join_common(__method__)
end

desc 'inner_join', 'inner join of json files'
option :join_key, required: true, aliases: :k
option :join_file, required: true, aliases: :j
option :base_file, aliases: :b, default: '/dev/stdin'
def inner_join
join_common(__method__)
end

desc 'unwind_array [JSON_FILE]', 'unwind array of json file'
option :unwind_key, required: true, aliases: :k
def unwind_array(json_file = '/dev/stdin')
unwind_common(__method__, json_file)
end

desc 'unwind_hash [JSON_FILE]', 'unwind hash of json file'
option :unwind_key, required: true, aliases: :k
option :flatten, type: :boolean, aliases: :f
option :key_label
option :value_label
def unwind_hash(json_file = '/dev/stdin')
unwind_common(__method__, json_file)
end

private

def join_common(command)
left_io = File.open(options[:base_file], 'r')
right_io = File.open(options[:join_file], 'r')
JsonCli::Command::Join.new(left_io, right_io, opts).send(command)
[left_io, right_io, opts[:out]].each(&:close)
end

def unwind_common(command, json_file)
io = File.open(json_file, 'r')
JsonCli::Command::Unwind.new(io, opts).send(command)
[io, opts[:out]].each(&:close)
end

def opts
@opts ||= { out: File.open(options[:output], 'w') }
.merge(options.select { |key, _| key != :output })
.each_with_object({}) do |(key, val), hash|
hash[key.to_sym] = val
end
end
end
end
12 changes: 12 additions & 0 deletions lib/json_cli/command/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# -*- mode: ruby; coding: utf-8 -*-

module JsonCli
module Command
# Base command class
class Base
def initialize(options)
@output = options[:out]
end
end
end
end
52 changes: 52 additions & 0 deletions lib/json_cli/command/join.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- mode: ruby; coding: utf-8 -*-
require 'multi_json'

module JsonCli
module Command
# Join JSON class
class Join < Base
def initialize(left_io, right_io, options)
super(options)
@left_io = left_io
@right_io = right_io
@join_key = options[:join_key]
end

def left_join
join(@left_io, @right_io)
end

def right_join
join(@right_io, @left_io)
end

def inner_join
right = io2hash(@right_io)
@left_io.each do |line|
obj = MultiJson.load(line.chomp)
next if !obj.key?(@join_key) ||
!right.key?((jk_val = obj[@join_key]))
@output.puts MultiJson.dump(obj.merge(right[jk_val]))
end
end

private

def io2hash(io)
io.each_with_object({}) do |line, hash|
obj = MultiJson.load(line.chomp)
hash[obj.delete(@join_key)] = obj if obj.key?(@join_key)
end
end

def join(left_io, right_io)
right = io2hash(right_io)
left_io.each do |line|
obj = MultiJson.load(line.chomp)
obj.merge!(right[obj[@join_key]] || {}) if obj.key?(@join_key)
@output.puts MultiJson.dump(obj)
end
end
end
end
end
68 changes: 68 additions & 0 deletions lib/json_cli/command/unwind.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# -*- mode: ruby; coding: utf-8 -*-
require 'multi_json'

module JsonCli
module Command
# Unwind JSON class
class Unwind < Base
def initialize(io, options)
super(options)
@io = io
@unwind_key = options[:unwind_key]
@flatten = options[:flatten]
@key_label = options[:key_label] || 'key'
@value_label = options[:value_label] || 'value'
end

def unwind_array
@io.each do |line|
obj = MultiJson.load(line.chomp)
if !obj.key?(@unwind_key) || !obj[@unwind_key].is_a?(Array)
@output.puts MultiJson.dump(obj)
else
unwind_array_obj(obj)
end
end
end

def unwind_hash
@io.each do |line|
obj = MultiJson.load(line.chomp)
if !obj.key?(@unwind_key) || !obj[@unwind_key].is_a?(Hash)
@output.puts MultiJson.dump(obj)
elsif @flatten
unwind_hash_obj_flatten(obj)
else
unwind_hash_obj(obj)
end
end
end

private

def unwind_array_obj(obj)
obj[@unwind_key].each do |val|
@output.puts MultiJson.dump(obj.merge(@unwind_key => val))
end
end

def unwind_hash_obj(obj)
obj[@unwind_key].each do |key, val|
jj = obj.merge(@unwind_key => { key => val })
@output.puts MultiJson.dump(jj)
end
end

def unwind_hash_obj_flatten(obj)
base = obj.select { |key, _| key != @unwind_key }
obj[@unwind_key].each do |key, val|
jj = base.merge(
@key_label => key,
@value_label => val
)
@output.puts MultiJson.dump(jj)
end
end
end
end
end
41 changes: 0 additions & 41 deletions lib/json_cli/join.rb

This file was deleted.

43 changes: 0 additions & 43 deletions lib/json_cli/unwind.rb

This file was deleted.

Loading

0 comments on commit 4b1a13e

Please sign in to comment.