yose 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: de20f89269c68a14ab49bf3d36616ec838bb78ee53474f170c497defeed781c1
4
+ data.tar.gz: 5d509316146b1e8e572a189dcc4d1e9b5e6d82fb398c5a28f8e59a36635a10b4
5
+ SHA512:
6
+ metadata.gz: 3afe45de85b82de653d23395fc5dd774999f9ed3388dd2d86d7674b89ec5bfbdfa902ae1119c3ff435b6a35451b5e2e7a31dfa07c10ac9d48f9ac325bcc7a19b
7
+ data.tar.gz: 2e6be48bc2f4cd50c1fbe32393d6075862dfeb93f32ac1f14becce5de402cc4b9e87bd4fb7f7d91daf603719b5ae615b9dfa95b092f82586fa80e90862878121
data/.gitignore ADDED
@@ -0,0 +1,56 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
+ # .rubocop-https?--*
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in yose.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Masatoshi SEKI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # Yose
2
+ Simple JSON DB using psql, jsonb, ruby
3
+
4
+ # setup PG
5
+
6
+ create database 'yose'
7
+
8
+ ```
9
+ % createdb yose
10
+ ```
11
+
12
+ or use existing database,
13
+
14
+ ```
15
+ % export YOSE_DATABASE_URL=existing_database
16
+ ```
17
+ ```
18
+ % export DATABASE_URL=existing_database
19
+ ```
20
+
21
+ searching order:
22
+ ```
23
+ url = ENV['YOSE_DATABASE_URL'] || ENV['DATABASE_URL'] || 'postgres:///yose'
24
+ ```
25
+
26
+ # usage
27
+
28
+ ## create_table, drop_table
29
+
30
+ default table name is 'world'.
31
+
32
+ ```
33
+ irb(main):001:0> Yose::create_table
34
+ irb(main):002:0> Yose::create_table('world')
35
+ ...
36
+ PG::DuplicateTable (ERROR: relation "world" already exists)
37
+ irb(main):003:0> Yose::drop_table('world')
38
+ irb(main):004:0> Yose::create_table('world')
39
+ ```
40
+
41
+ ```
42
+ irb(main):007:0> Yose::create_table('another')
43
+ irb(main):008:0> Yose::drop_table('another')
44
+ ```
45
+
46
+ ## alloc jsonb object
47
+
48
+ alloc, and free. alloc retruns the UID.
49
+
50
+ ```
51
+ % irb -r yose --simple-prompt
52
+ >> root = Yose::Store.new
53
+ >> it
54
+ => "f51a923e-99aa-41f0-9b9f-e3b596b66aa9"
55
+ >> it = root.alloc({'foo' => 'bar', 'ary' => [1, 2, 3]}.to_json)
56
+ >> root[it]
57
+ => {"ary"=>[1, 2, 3], "foo"=>"bar"}
58
+ >> root.free(it)
59
+ => {"ary"=>[1, 2, 3], "foo"=>"bar"}
60
+ >> root[it]
61
+ => nil
62
+ ```
63
+
64
+ for Hash, obj.to_json automatically.
65
+
66
+ ```
67
+ >> it = root.alloc({'foo' => 'bar', 'ary' => [1, 2, 3]})
68
+ >> root[it]
69
+ => {"ary"=>[1, 2, 3], "foo"=>"bar"}
70
+ ```
71
+
72
+ alloc! checks for uniqueness. (using @> op.)
73
+
74
+ ```
75
+ >> root.alloc!({'type' => 'employee', 'name' => '@m_seki'})
76
+ => "ed98d46c-673a-4dd2-838f-194e42291f2f"
77
+ >> root.alloc!({'type' => 'employee', 'name' => '@m_seki'})
78
+ ...
79
+ RuntimeError (already exist {"type":"employee","name":"@m_seki"})
80
+ >> root.alloc!({'type' => 'employee', 'name' => '@awazeki'})
81
+ => "39bfdf2b-4fa1-4320-9cff-efbce77b6cea"
82
+ >> root.alloc!({'type' => 'employee'})
83
+ ...
84
+ RuntimeError (already exist {"type":"employee"})
85
+ >> root.alloc!({'type' => 'author', 'name' => '@m_seki'})
86
+ => "2d0b596d-bc09-4687-a9d5-9dec087ad9df"
87
+ ```
88
+
89
+ ## search
90
+
91
+ ```
92
+ >> pp root.search({'type' => 'employee'})
93
+ [{"uid"=>"ed98d46c-673a-4dd2-838f-194e42291f2f",
94
+ "obj"=>{"name"=>"@m_seki", "type"=>"employee"},
95
+ "mtime"=>2021-02-18 18:37:30.220031 +0900},
96
+ {"uid"=>"39bfdf2b-4fa1-4320-9cff-efbce77b6cea",
97
+ "obj"=>{"name"=>"@awazeki", "type"=>"employee"},
98
+ "mtime"=>2021-02-18 18:37:42.337694 +0900}]
99
+ >> pp root.search({'name' => '@m_seki'})
100
+ [{"uid"=>"ed98d46c-673a-4dd2-838f-194e42291f2f",
101
+ "obj"=>{"name"=>"@m_seki", "type"=>"employee"},
102
+ "mtime"=>2021-02-18 18:37:30.220031 +0900},
103
+ {"uid"=>"2d0b596d-bc09-4687-a9d5-9dec087ad9df",
104
+ "obj"=>{"name"=>"@m_seki", "type"=>"author"},
105
+ "mtime"=>2021-02-18 18:37:56.323186 +0900}]
106
+ >> pp root.search({'name' => '@m_seki', 'type' => 'author'})
107
+ [{"uid"=>"2d0b596d-bc09-4687-a9d5-9dec087ad9df",
108
+ "obj"=>{"name"=>"@m_seki", "type"=>"author"},
109
+ "mtime"=>2021-02-18 18:37:56.323186 +0900}]
110
+ ```
111
+
112
+ ## merge (update), delete
113
+
114
+ update merges jsonb object. (using || op.)
115
+
116
+ delete delets jsonb object. (using - op.)
117
+
118
+ ```
119
+ >> root[it].update({'ary' => 'not ary'})
120
+ => {"ary"=>"no ary", "foo"=>"bar"}
121
+ >> root[it]
122
+ => {"ary"=>[1, 2, 3], "foo"=>"bar"}
123
+ >> root.update(it, {'ary' => 'not ary'})
124
+ => {"ary"=>"not ary", "foo"=>"bar"}
125
+ >> root[it]
126
+ => {"ary"=>"not ary", "foo"=>"bar"}
127
+ >> root.delete(it, 'ary')
128
+ => {"foo"=>"bar"}
129
+ >> root[it]
130
+ => {"foo"=>"bar"}
131
+ >> root.merge(it, {'hash' => {'foo' => 'bar', 'bar' => 'baz'}})
132
+ => {"foo"=>"bar", "hash"=>{"bar"=>"baz", "foo"=>"bar"}}
133
+ >> root[it]
134
+ => {"foo"=>"bar", "hash"=>{"bar"=>"baz", "foo"=>"bar"}}
135
+ ```
136
+
137
+ ## mtime and recent changes
138
+
139
+ ```
140
+ >> he = root.search({'type' => 'employee', 'name' => '@awazeki'}).dig(0, 'uid')
141
+ >> root[he]
142
+ => {"name"=>"@awazeki", "type"=>"employee"}
143
+ >> root.mtime(he)
144
+ => 2021-02-18 18:37:42.337694 +0900
145
+ ```
146
+
147
+ ```
148
+ >> pp root.recent(root.mtime(he))
149
+ [{"uid"=>"3e13e180-e5fc-4179-9f4c-d8fbb5fe9bf4",
150
+ "obj"=>{"foo"=>"bar", "hash"=>{"bar"=>"baz", "foo"=>"bar"}},
151
+ "mtime"=>2021-02-18 18:42:42.658912 +0900},
152
+ {"uid"=>"2d0b596d-bc09-4687-a9d5-9dec087ad9df",
153
+ "obj"=>{"name"=>"@m_seki", "type"=>"author"},
154
+ "mtime"=>2021-02-18 18:37:56.323186 +0900}]
155
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "yose"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/yose.rb ADDED
@@ -0,0 +1,212 @@
1
+ require "pg"
2
+ require "monitor"
3
+ require "pp"
4
+ require "json"
5
+ require "securerandom"
6
+
7
+ module Yose
8
+ module_function
9
+ =begin
10
+ create extension moddatetime;
11
+
12
+ create table world (
13
+ uid uuid
14
+ , obj jsonb
15
+ , mtime timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL
16
+ , primary key(uid));
17
+
18
+ CREATE TRIGGER world_moddatetime
19
+ BEFORE UPDATE ON world
20
+ FOR EACH ROW
21
+ EXECUTE PROCEDURE moddatetime (mtime);
22
+
23
+ CREATE INDEX world_idxgin ON world USING GIN (obj jsonb_path_ops);
24
+ =end
25
+ def create_table(name="world")
26
+ db = Yose::DB.instance
27
+ db.conn.exec("create extension moddatetime;") rescue nil
28
+ db.transaction do |c|
29
+ c.exec("create table #{name} (
30
+ uid uuid
31
+ , obj jsonb
32
+ , mtime timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL
33
+ , primary key(uid));")
34
+ c.exec("CREATE TRIGGER #{name}_moddatetime
35
+ BEFORE UPDATE ON #{name}
36
+ FOR EACH ROW
37
+ EXECUTE PROCEDURE moddatetime (mtime);")
38
+ c.exec("CREATE INDEX #{name}_idxgin
39
+ ON #{name} USING GIN (obj jsonb_path_ops);")
40
+ end
41
+ end
42
+
43
+ def drop_table(name)
44
+ db = Yose::DB.instance
45
+ db.conn.exec("drop INDEX #{name}_idxgin") rescue nil
46
+ db.conn.exec("drop TRIGGER #{name}_moddatetime on #{name}") rescue nil
47
+ db.conn.exec("drop table #{name}") rescue nil
48
+ end
49
+
50
+ class DB
51
+ include MonitorMixin
52
+ def self.instance
53
+ @instance = self.new unless @instance
54
+ @instance.synchronize do
55
+ @instance = self.new unless @instance.ping
56
+ end
57
+ return @instance
58
+ rescue
59
+ nil
60
+ end
61
+
62
+ def initialize
63
+ super()
64
+ url = ENV['YOSE_DATABASE_URL'] || ENV['DATABASE_URL'] || 'postgres:///yose'
65
+ @conn = PG.connect(url)
66
+ @conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
67
+ end
68
+ attr :conn
69
+
70
+ def ping
71
+ @conn.exec("select 1")
72
+ true
73
+ rescue
74
+ false
75
+ end
76
+
77
+ def transaction
78
+ #FIXME
79
+ synchronize do
80
+ @conn.transaction do |c|
81
+ yield(c)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ class Store
88
+ def initialize(name='world')
89
+ @name = name
90
+ end
91
+
92
+ def as_json(json)
93
+ (Hash === json) ? json.to_json : json
94
+ end
95
+
96
+ def as_pg_time(time)
97
+ time.strftime("%F %T.%6N")
98
+ end
99
+
100
+ def transaction(&proc)
101
+ DB.instance.transaction(&proc)
102
+ end
103
+
104
+ def alloc(json)
105
+ sql =<<EOQ
106
+ insert into #{@name}
107
+ (uid, obj)
108
+ values
109
+ ($1, $2)
110
+ returning uid::text;
111
+ EOQ
112
+ transaction do |c|
113
+ c.exec_params(sql, [SecureRandom.uuid, as_json(json)]).first['uid']
114
+ end
115
+ end
116
+
117
+ def alloc!(json)
118
+ sql =<<EOQ
119
+ insert into #{@name}
120
+ (uid, obj)
121
+ values
122
+ ($1, $2)
123
+ returning uid::text;
124
+ EOQ
125
+ transaction do |c|
126
+ json = as_json(json)
127
+ sz = c.exec_params("select count(*) from #{@name} where obj @> $1",
128
+ [json]).first['count']
129
+ raise "already exist #{json}" if sz > 0
130
+ c.exec_params(sql, [SecureRandom.uuid, json]).first['uid']
131
+ end
132
+ end
133
+
134
+ def free(uid)
135
+ sql =<<EOQ
136
+ delete from #{@name} where uid = $1 returning obj;
137
+ EOQ
138
+ transaction do |c|
139
+ c.exec_params(sql, [uid]).to_a.dig(0, 'obj')
140
+ end
141
+ end
142
+ alias forget free
143
+
144
+ def [](uid)
145
+ sql =<<EOQ
146
+ select obj from #{@name} where uid = $1 limit 1;
147
+ EOQ
148
+ transaction do |c|
149
+ c.exec_params(sql, [uid]).to_a.dig(0, 'obj')
150
+ end
151
+ end
152
+
153
+ def mtime(uid)
154
+ sql =<<EOQ
155
+ select mtime from #{@name} where uid = $1 limit 1;
156
+ EOQ
157
+ transaction do |c|
158
+ c.exec_params(sql, [uid]).to_a.dig(0, 'mtime')
159
+ end
160
+ end
161
+
162
+ def search(json)
163
+ sql =<<EOQ
164
+ select uid::text, obj, mtime from #{@name} where obj @> $1::jsonb;
165
+ EOQ
166
+ transaction do |c|
167
+ c.exec_params(sql, [as_json(json)]).to_a
168
+ end
169
+ end
170
+
171
+ def update(uid, json)
172
+ sql =<<EOQ
173
+ update #{@name} set obj = obj || $2::jsonb where uid = $1 returning obj;
174
+ EOQ
175
+ transaction do |c|
176
+ c.exec_params(sql, [uid, as_json(json)]).to_a.to_a.dig(0, 'obj')
177
+ end
178
+ end
179
+ alias merge update
180
+
181
+ def replace(uid, json)
182
+ sql =<<EOQ
183
+ update #{@name} set obj = $2::jsonb where uid = $1 returning obj;
184
+ EOQ
185
+ transaction do |c|
186
+ c.exec_params(sql, [uid, as_json(json)]).to_a.dig(0, 'obj')
187
+ end
188
+ end
189
+
190
+ def delete(uid, key)
191
+ sql =<<EOQ
192
+ update #{@name} set obj = obj - $2 where uid = $1 returning obj;
193
+ EOQ
194
+ transaction do |c|
195
+ c.exec_params(sql, [uid, key]).to_a.dig(0, 'obj')
196
+ end
197
+ end
198
+
199
+ def recent(since)
200
+ sql =<<EOQ
201
+ select uid::text, obj, mtime from #{@name} where mtime > $1 order by mtime desc;
202
+ EOQ
203
+ transaction do |c|
204
+ c.exec_params(sql, [as_pg_time(since)]).to_a
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ if __FILE__ == $0
211
+ Yose::create_table
212
+ end
@@ -0,0 +1,3 @@
1
+ module Yose
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,92 @@
1
+ require_relative '../lib/yose'
2
+ require 'date'
3
+
4
+ class ShiftStore
5
+ def initialize
6
+ @db = Yose::Store.new
7
+ end
8
+ attr_reader :db
9
+
10
+ def add_employee(name)
11
+ user = {
12
+ 'type' => '従業員',
13
+ 'name' => name
14
+ }
15
+ @db.alloc!(user.to_json)
16
+ end
17
+
18
+ def all_employee
19
+ @db.search({'type' => '従業員'})
20
+ end
21
+
22
+ def employee_by_name(name)
23
+ @db.search({'type' => '従業員', 'name' => name})
24
+ end
25
+
26
+ def employee_by_store(store)
27
+ @db.search({'type' => '従業員', '店' => [store]})
28
+ end
29
+
30
+ def add_plan(employee_uid, store, y, m, d, hhmm, hours)
31
+ plan = {
32
+ 'type' => '予定',
33
+ '従業員' => employee_uid,
34
+ '店' => store,
35
+ 'y' => y,
36
+ 'm' => m,
37
+ 'd' => d,
38
+ 'start' => hhmm,
39
+ 'hours' => hours
40
+ }
41
+ @db.alloc!(plan) rescue nil
42
+ end
43
+ end
44
+
45
+ if __FILE__ == $0
46
+ app = ShiftStore.new
47
+
48
+ seki = app.add_employee('関将俊') rescue app.employee_by_name('関将俊').first['uid']
49
+ ikezawa = app.add_employee('池澤一廣') rescue app.employee_by_name('池澤一廣').first['uid']
50
+ pp app.all_employee
51
+ seki = app.employee_by_name('関将俊').first['uid']
52
+ pp app.db[seki]
53
+ app.db.update(seki, {'店' => %w(矢板 西那須野 大田原)})
54
+ pp app.db[seki]
55
+ pp app.employee_by_name('関将俊')
56
+ pp app.employee_by_name('池澤一廣')
57
+ app.db.merge(ikezawa, {'店' => %w(矢板)})
58
+ miwa = app.add_employee('深谷美和') rescue nil
59
+ if miwa
60
+ app.db.merge(miwa, {'店' => %w(大田原 矢板)})
61
+ end
62
+ puts '矢板'
63
+ pp app.employee_by_store('矢板').map{|x| x['obj']}
64
+ puts '大田原'
65
+ pp app.employee_by_store('大田原').map{|x| x['obj']}
66
+ puts '西那須野'
67
+ pp app.employee_by_store('西那須野').map{|x| x['obj']}
68
+
69
+
70
+ s = Date.parse('2021-01-01')
71
+ (s ... (s >> 2)).each do |d|
72
+ app.add_plan(ikezawa, '矢板', d.year, d.month, d.day, '8:00', 4)
73
+ app.add_plan(ikezawa, '矢板', d.year, d.month, d.day, '13:00', 4)
74
+ app.add_plan(miwa, '大田原', d.year, d.month, d.day, '13:00', 4)
75
+ app.add_plan(seki, '大田原', d.year, d.month, d.day, '8:00', 4)
76
+ app.add_plan(seki, '西那須野', d.year, d.month, d.day, '13:00', 4)
77
+ end
78
+
79
+ employee = Hash.new do |h, k|
80
+ h[k] = app.db[k].dig("name") rescue nil
81
+ end
82
+ pp app.db.search({"type" => "予定", "店" => "大田原", "y" => 2021, "m" => 2}).map {|x|
83
+ it = x['obj']
84
+ [employee[it['従業員']]] + it.values_at(* %w(y m d start hours))
85
+ }
86
+
87
+ pp app.db.search({"type" => "予定", "店" => "矢板", "y" => 2021, "m" => 2}).map {|x|
88
+ it = x['obj']
89
+ [employee[it['従業員']]] + it.values_at(* %w(y m d start hours))
90
+ }
91
+ end
92
+
data/yose.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ require_relative 'lib/yose/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "yose"
5
+ spec.version = Yose::VERSION
6
+ spec.authors = ["Masatoshi SEKI"]
7
+ spec.email = ["seki@ruby-lang.org"]
8
+
9
+ spec.summary = %q{simple json storage using psql, jsonb.}
10
+ spec.description = %q{simple json storage using psql, jsonb.}
11
+ spec.homepage = "https://github.com/seki/Yose"
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
13
+
14
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/seki/Yose"
18
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_dependency "pg"
30
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yose
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Masatoshi SEKI
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pg
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: simple json storage using psql, jsonb.
28
+ email:
29
+ - seki@ruby-lang.org
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - Gemfile
36
+ - LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - bin/console
40
+ - bin/setup
41
+ - lib/yose.rb
42
+ - lib/yose/version.rb
43
+ - sample/shift_table.rb
44
+ - yose.gemspec
45
+ homepage: https://github.com/seki/Yose
46
+ licenses: []
47
+ metadata:
48
+ homepage_uri: https://github.com/seki/Yose
49
+ source_code_uri: https://github.com/seki/Yose
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 2.3.0
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.1.2
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: simple json storage using psql, jsonb.
69
+ test_files: []