ordlite 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6051393488775c98fdee4716e6c49b5cd89c6cd404a45f48024a47dea633acfb
4
- data.tar.gz: d43e1d73f1b49b27ae35e745eaa8e13be394635d2367233bc6c341fd1aa54933
3
+ metadata.gz: 6f1f6f768a785a0badc768db45c1c8ca831958f983b673fe48990846f3d4260e
4
+ data.tar.gz: 234d31cabdc7ed109144487792da9f77c39821f935e3d7d91a151b91e817d511
5
5
  SHA512:
6
- metadata.gz: 05e95871ce3a85dd31557e38a4247d5cd38e25406e2ac535a1254e6952e68b8054e8c1a06378b4620ce8168c67d1e4cb7eac50305da9e7e59e2f10152a4aa971
7
- data.tar.gz: 3fe7780c583d525dd60170f4ec0e996f430722d53899e3edb321d9af67425024c262a253e1cf718ab0b7316f9fbb3ae0a6903b3a82debf3860511a167872a1ab
6
+ metadata.gz: 403e1addf0b974af179de293a26c5f1f47da8d0f665da1ca1a44a89cbcfb025a642a04930f49f6df35681527b2cbcaae855f87de4b7ce09e6cd88b4cffab1472
7
+ data.tar.gz: ab359d39d1dcdf307e8b3239ed61e2f10f8fc6bfc4316c3f9f5554a9fbc2d88b0d1c24f120afcab9b035c675d82d22e0292c6d1202db7219d64f5e8f2c214b54
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 0.2.0 / 2023-07-28
1
+ ### 0.2.1
2
2
  ### 0.0.1 / 2023-07-01
3
3
 
4
4
  * Everything is new. First release
data/Manifest.txt CHANGED
@@ -5,6 +5,7 @@ Rakefile
5
5
  lib/ordlite.rb
6
6
  lib/ordlite/base.rb
7
7
  lib/ordlite/cache.rb
8
+ lib/ordlite/factory.rb
8
9
  lib/ordlite/importer.rb
9
10
  lib/ordlite/models/blob.rb
10
11
  lib/ordlite/models/collection.rb
data/README.md CHANGED
@@ -13,7 +13,7 @@ ordlite - ordinals inscription (on bitcoin & co) database let's you query via sq
13
13
 
14
14
  ## SQL Database Model
15
15
 
16
- Inscribes • Blobs • Collections • Generatives
16
+ Inscribes • Blobs • Collections • Factories • Generatives
17
17
 
18
18
 
19
19
  Table Inscribes
@@ -63,6 +63,7 @@ puts
63
63
  puts " #{Inscribe.count} inscribe(s)"
64
64
  puts " #{Blob.count} blob(s)"
65
65
  puts " #{Collection.count} collection(s)"
66
+ puts " #{Factory.count} factories"
66
67
  puts " #{Generative.count} generative(s)"
67
68
 
68
69
  #=> 0 inscribe(s)
@@ -74,68 +75,134 @@ puts " #{Generative.count} generative(s)"
74
75
 
75
76
 
76
77
 
77
- ### Example No 1 - Query Ordgen Deploy / Mint Inscriptions
78
+ ### Example No 1 - Auto-Add (Via Ordinals.com) First Thousand Inscriptions (Sub 1k)
78
79
 
79
80
  ``` ruby
80
81
  require 'ordlite'
81
82
 
82
83
 
83
- OrdDb.connect( adapter: 'sqlite3',
84
- database: './ord.db' )
84
+ OrdDb.open( './ord.db' )
85
85
 
86
86
 
87
- ####################
88
- ## query for deploy candidates
89
- ##
90
- ## e.g. sql where clause like
91
- ## content LIKE '%deploy%'
92
- ## AND ( content LIKE '%orc-721%'
93
- ## OR content LIKE '%og%')
94
- ##
87
+ 1000.times do |num| # auto-add inscription 0-999
88
+ OrdDb.import( num )
89
+ end
90
+
91
+ puts
92
+ puts " #{Inscribe.count} inscribe(s)"
93
+ puts " #{Blob.count} blob(s)"
94
+ #=> 1000 inscribe(s)
95
+ #=> 1000 blob(s)
96
+ ```
95
97
 
96
- deploys = Inscribe.deploys
97
- puts " #{deploys.size} deploy candidate(s)"
98
+ Let's query for the ten biggest (by bytes) inscriptions
99
+ (and pretty print the result):
98
100
 
99
- deploys.each_with_index do |rec,i|
100
- puts "==> deploy #{i} - num #{rec.num} - #{rec.bytes} bytes - #{rec.date}"
101
- puts rec.content
101
+ ```ruby
102
+ Inscribe.biggest.limit(10).each do |rec|
103
+ print "#{number_to_human_size(rec.bytes)} (#{rec.bytes} bytes) - "
104
+ print "Inscribe №#{rec.num} (#{rec.content_type}) - "
105
+ print "#{rec.date} - #{rec.fee} fee in sats"
106
+ print "\n"
102
107
  end
108
+ ```
103
109
 
110
+ resulting in:
104
111
 
105
- punks_deploys = Inscribe.deploys_by( slug: 'diypunks')
106
- puts " #{punks_deploys.size} deploy candidate(s)"
112
+ ```
113
+ 3.73 MB (3915537 bytes) - Inscribe №652 (image/jpeg) - 2023-02-01 20:38:33 - 0 fee in sats
114
+ 385 KB (394718 bytes) - Inscribe №978 (application/epub+zip) - 2023-02-02 06:46:04 - 109325 fee in sats
115
+ 385 KB (394479 bytes) - Inscribe №546 (image/gif) - 2023-02-01 10:41:50 - 1489860 fee in sats
116
+ 385 KB (394440 bytes) - Inscribe №833 (image/png) - 2023-02-02 01:13:51 - 99314 fee in sats
117
+ 381 KB (389858 bytes) - Inscribe №388 (image/jpeg) - 2023-01-31 14:01:38 - 981620 fee in sats
118
+ 379 KB (388417 bytes) - Inscribe №291 (image/gif) - 2023-01-30 17:58:54 - 586794 fee in sats
119
+ 378 KB (386858 bytes) - Inscribe №857 (image/png) - 2023-02-02 01:17:54 - 97407 fee in sats
120
+ 374 KB (383322 bytes) - Inscribe №538 (image/jpeg) - 2023-02-01 10:20:28 - 96519 fee in sats
121
+ 367 KB (375414 bytes) - Inscribe №378 (image/gif) - 2023-01-31 09:47:55 - 945300 fee in sats
122
+ 365 KB (373504 bytes) - Inscribe №288 (image/jpeg) - 2023-01-30 16:51:46 - 94050 fee in sats
123
+ ```
107
124
 
108
125
 
126
+ Let's query for all inscriptions grouped by date (day) and dump the results:
109
127
 
110
- #######################
111
- ## query for mint candidates
112
- ##
113
- ## e.g. sql where clause like
114
- ## content LIKE '%mint%'
115
- ## AND ( content LIKE '%orc-721%'
116
- ## OR content LIKE '%og%')
128
+ ```ruby
129
+ pp Inscribe.counts_by_date ## or count_by_day
130
+ ```
117
131
 
118
- mints = Inscribe.mints
119
- puts " #{mints.size} mint candidate(s)"
132
+ resulting in:
120
133
 
121
- ## print last hundred mint candidates
122
- mints[-100,100].each_with_index do |rec,i|
123
- puts "==> mint #{i} - num #{rec.num} - #{rec.bytes} bytes - #{rec.date}"
124
- puts rec.content
125
- end
134
+ ```
135
+ {"2022-12-14" => 1,
136
+ "2022-12-17" => 1,
137
+ "2022-12-19" => 1,
138
+ "2023-01-05" => 1,
139
+ "2023-01-10" => 1,
140
+ "2023-01-12" => 1,
141
+ "2023-01-13" => 2,
142
+ "2023-01-15" => 1,
143
+ "2023-01-16" => 1,
144
+ "2023-01-19" => 5,
145
+ "2023-01-20" => 3,
146
+ "2023-01-21" => 5,
147
+ "2023-01-22" => 34,
148
+ "2023-01-23" => 23,
149
+ "2023-01-24" => 4,
150
+ "2023-01-25" => 9,
151
+ "2023-01-26" => 12,
152
+ "2023-01-27" => 19,
153
+ "2023-01-28" => 16,
154
+ "2023-01-29" => 128,
155
+ "2023-01-30" => 82,
156
+ "2023-01-31" => 98,
157
+ "2023-02-01" => 220,
158
+ "2023-02-02" => 332}
159
+ ```
126
160
 
161
+ Let's query for all inscriptions grouped by month and dump the results:
162
+
163
+ ```ruby
164
+ pp Inscribe.counts_by_month
165
+ ```
166
+
167
+ resulting in:
168
+
169
+ ```
170
+ {"2022-12" => 3,
171
+ "2023-01" => 445,
172
+ "2023-02" => 552}
173
+ ```
127
174
 
128
- phunks_mints = Inscribe.mints_by( slug: 'diyphunks')
129
- puts " #{phunks_mints.size} mint candidate(s)"
130
175
 
176
+ Let's query for all content types and group by count (descending) and dump the results:
131
177
 
132
- puts " #{deploys.size} deploy candidate(s)"
133
- puts " #{mints.size} mint candidate(s)"
134
178
 
135
- #=> 123 deploy candidate(s)
136
- #=> 7453 mint candidate(s)
179
+ ```ruby
180
+ pp Inscribe.counts_by_content_type
137
181
  ```
138
182
 
183
+ resulting in:
184
+
185
+ ```
186
+ {"image/png" => 475,
187
+ "image/jpeg" => 188,
188
+ "image/webp" => 117,
189
+ "text/plain;charset=utf-8" => 112,
190
+ "image/svg+xml" => 62,
191
+ "text/html;charset=utf-8" => 18,
192
+ "image/gif" => 11,
193
+ "audio/mpeg" => 6,
194
+ "application/pdf" => 2,
195
+ "image/avif" => 2,
196
+ "video/webm" => 2,
197
+ "application/epub+zip" => 1,
198
+ "application/pgp-signature" => 1,
199
+ "audio/midi" => 1,
200
+ "audio/mod" => 1,
201
+ "video/mp4" => 1}
202
+ ```
203
+
204
+ and so on.
205
+
139
206
 
140
207
 
141
208
 
@@ -150,13 +217,10 @@ into an (sql) database e.g. `ord.db`:
150
217
  ``` ruby
151
218
  require 'ordlite'
152
219
 
153
- OrdDb.connect( adapter: 'sqlite3',
154
- database: './ord.db' )
155
-
156
- OrdDb.create_all # build table schema
220
+ OrdDb.open( './ord.db' )
157
221
 
158
222
  cache_dir = './ordinals.cache/inscription'
159
- cache = OrdDb::Cache.new( cache_dir )
223
+ cache = Ordinals::Cache.new( cache_dir )
160
224
  cache.import_all
161
225
 
162
226
 
data/Rakefile CHANGED
@@ -27,6 +27,7 @@ Hoe.spec 'ordlite' do
27
27
  ['props'],
28
28
  ['props-activerecord'],
29
29
  ['sqlite3'],
30
+ ['pixelart'], ## required for factory (ordgen/orc-721) support for now
30
31
  ]
31
32
 
32
33
  self.licenses = ['Public Domain']
data/lib/ordlite/base.rb CHANGED
@@ -134,5 +134,13 @@ module OrdDb
134
134
  end # module OrdDb
135
135
 
136
136
 
137
+
138
+ ####
139
+ # add factory (ordgen/orc-721) support here for now - why? why not?
140
+ require 'pixelart'
141
+ require_relative 'factory'
142
+
143
+
144
+
137
145
  # say hello
138
146
  puts Ordlite.banner ## if defined?($RUBYCOCOS_DEBUG) && $RUBCOCOS_DEBUG
@@ -0,0 +1,132 @@
1
+
2
+
3
+ class FactorySpritesheet ## check - rename to catalog or atlas NOT spritesheet - why? why not?
4
+ def self.read_inscribes( *inscribes, width:,
5
+ height: )
6
+ ## map inscribes to images
7
+ images = inscribes.map {|inscribe| Pixelart::Image.blob( inscribe.content ) }
8
+ ## puts " #{images.size} image(s)"
9
+
10
+ new( *images, width: width,
11
+ height: height)
12
+ end
13
+
14
+ def initialize( *images, width:,
15
+ height: )
16
+ @tile_width = width
17
+ @tile_height = height
18
+ @tiles = []
19
+ images.each {|img| add(img) }
20
+ end
21
+
22
+ def count() @tiles.size; end
23
+ alias_method :size, :count
24
+ alias_method :tile_count, :count ## add tile_count - why? why not?
25
+ def tile_width() @tile_width; end ## use width - why? why not?
26
+ def tile_height() @tile_height; end ## use height - why? why not?
27
+
28
+ def tile( index ) @tiles[ index ]; end
29
+ alias_method :[], :tile
30
+
31
+ def add_inscribe( inscribe ) _add( Pixelart::Image.blob( inscribe.content )); end
32
+ def add( img )
33
+ ## 1:1 tile; use as is
34
+ if img.width == @tile_width && img.height == @tile_height
35
+ @tiles << img
36
+ else ## assume spritesheet??
37
+ ## wrap into composite image
38
+ composite = Pixelart::ImageComposite.new( img.image, width: @tile_width,
39
+ height: @tile_height )
40
+ cols = img.width / composite.tile_width
41
+ rows = img.height / composite.tile_height
42
+ puts " #{composite.count} tile(s) in #{cols}x#{rows} grid"
43
+ composite.each {|tile| @tiles << tile }
44
+ end
45
+ end
46
+ alias_method :<<, :add
47
+ end ## class Spritesheet
48
+
49
+
50
+ class FactoryGenerator
51
+ ###################
52
+ ## convenience setup helper(s)
53
+ def self.read_inscribes( *inscribes, width:,
54
+ height: )
55
+ new( FactorySpritesheet.read_inscribes( *inscribes,
56
+ width: width,
57
+ height: height ))
58
+ end
59
+
60
+ def initialize( spritesheet )
61
+ @spritesheet = spritesheet
62
+ end
63
+
64
+ def _parse( spec )
65
+ ## for delimiter allow for now: - why? why not?
66
+ ## (multiple) space ( )
67
+ ## command or semicolon
68
+ spec.strip.split( %r{[ ,;/_-]+} ).map {|v| v.to_i(10) }
69
+ end
70
+
71
+ def parse( spec )
72
+ ## convenience helper
73
+ ## parses g spec in various (delimited) formats
74
+ g = _parse( spec )
75
+ generate( *g )
76
+ end
77
+
78
+ def generate( *attributes )
79
+ img = Pixelart::Image.new( width, height )
80
+ attributes.each do |num|
81
+ img.compose!( @spritesheet[ num ] )
82
+ end
83
+ img
84
+ end
85
+ alias_method :g, :generate
86
+
87
+ def width() @spritesheet.tile_width; end
88
+ def height() @spritesheet.tile_height; end
89
+ def count() @spritesheet.count; end
90
+ end # class FactoryGenerator
91
+
92
+
93
+
94
+ module OrdDb
95
+ module Model
96
+
97
+ class Factory
98
+
99
+ ## use id/slug to cache generators / spritesheets - why? why not?
100
+ def self.generators
101
+ @generators ||= {}
102
+ end
103
+
104
+ def generator
105
+ generators = self.class.generators
106
+ if generators.has_key?( id )
107
+ generators[ id ]
108
+ else
109
+ ## auto-add generator on first-time/hit/demand
110
+ width, height = _parse_dimension( dim )
111
+ inscribes = layers.to_a ## get layer inscribe records
112
+ generator = FactoryGenerator.read_inscribes( *inscribes,
113
+ width: width,
114
+ height: height )
115
+ generators[ id ] = generator
116
+ generator
117
+ end
118
+ end
119
+
120
+ def generate( *attributes ) ## add g shortcut alias - why? why not?
121
+ generator.generate( *attributes )
122
+ end
123
+
124
+
125
+ ## e.g. convert dimension (width x height) "24x24" or "24 x 24" to [24,24]
126
+ def _parse_dimension( str )
127
+ str.split( /x/i ).map { |str| str.strip.to_i(10) }
128
+ end
129
+
130
+ end # class Factory
131
+ end # module Model
132
+ end # module OrdDb
@@ -1,8 +1,82 @@
1
+ module OrdDb
1
2
 
3
+ class Importer
4
+ Inscribe = Model::Inscribe
5
+ Blob = Model::Blob
6
+ Collection = Model::Collection
2
7
 
3
- module OrdDb
4
8
 
5
- def self.import_collection( path, content: true )
9
+
10
+ def import_collection_csv( path,
11
+ name:,
12
+ content: true )
13
+ ## or use
14
+ ## import_collection( format: 'csv') - why? why not?
15
+ recs = read_csv( path )
16
+ puts " #{recs.size} inscribe id(s)"
17
+
18
+ col = Collection.find_by( name: name )
19
+ if col && col.items.count > 0
20
+ puts "!! WARN - collection already in db; delete first to reimport"
21
+ return
22
+ elsif col
23
+ ## do nothing; (re)use collection record; add items
24
+ else
25
+ col = Collection.create(
26
+ name: name
27
+ ## max: recs.size ## auto-add max - why? why not?
28
+ )
29
+ end
30
+
31
+ recs.each_with_index do |rec,i|
32
+ id = rec['id']
33
+ name = rec['name'] || rec['title']
34
+ puts "==> #{i+1}/#{recs.size} >#{name}< @ #{id}..."
35
+
36
+ col.items.create( pos: i,
37
+ inscribe_id: id,
38
+ name: name )
39
+
40
+ _import( id, content: content )
41
+ end
42
+ end
43
+
44
+
45
+ def import_collection_inscriptions( path,
46
+ name:,
47
+ content: true )
48
+ recs = read_json( path )
49
+ puts " #{recs.size} inscribe id(s)"
50
+
51
+ col = Collection.find_by( name: name )
52
+ if col && col.items.count > 0
53
+ puts "!! WARN - collection already in db; delete first to reimport"
54
+ return
55
+ elsif col
56
+ ## do nothing; (re)use collection record; add items
57
+ else
58
+ col = Model::Collection.create(
59
+ name: name
60
+ ## max: recs.size ## auto-add max - why? why not?
61
+ )
62
+ end
63
+
64
+ recs.each_with_index do |rec,i|
65
+ id = rec['id']
66
+ meta = rec['meta']
67
+ name = meta['name']
68
+ puts "==> #{i+1}/#{recs.size} >#{name}< @ #{id}..."
69
+
70
+ col.items.create( pos: i,
71
+ inscribe_id: id,
72
+ name: name )
73
+
74
+ _import( id, content: content )
75
+ end
76
+ end
77
+
78
+
79
+ def import_collection( path, content: true )
6
80
  data = read_json( path )
7
81
 
8
82
  meta = data['collection']
@@ -10,13 +84,13 @@ def self.import_collection( path, content: true )
10
84
 
11
85
  name = meta['name']
12
86
 
13
- col = Model::Collection.find_by( name: name )
87
+ col = Collection.find_by( name: name )
14
88
  if col
15
89
  puts "!! WARN - collection already in db; delete first to reimport"
16
90
  return
17
91
  end
18
92
 
19
- col = Model::Collection.create(
93
+ col = Collection.create(
20
94
  name: name,
21
95
  desc: meta['description'],
22
96
  max: meta['max_supply']
@@ -33,35 +107,12 @@ def self.import_collection( path, content: true )
33
107
  inscribe_id: id,
34
108
  name: name )
35
109
 
36
- ## check if inscription / inscribe is already in db?
37
- inscribe = Model::Inscribe.find_by( id: id )
38
- if inscribe ## already in db; dump record
39
- ## pp inscribe
40
- else ## fetch via ordinals.com api and update db
41
- data = Ordinals.inscription( id )
42
- pp data
43
- Model::Inscribe.create_from_api( data )
44
- sleep( 1 ) ## delay in seconds (before next request)
45
- end
46
-
47
- if content
48
- ## check if (content) blob is already in db?
49
- blob = Model::Blob.find_by( id: id )
50
- if blob ## already in db; do nothing
51
- else ## fetch via ordinals.com api and update db
52
- content = Ordinals.content( id )
53
- puts " content-type: #{content.type}"
54
- puts " content-length: #{content.length}"
55
-
56
- Model::Blob.create( id: id, content: content.data )
57
- sleep( 1 ) ## delay in seconds (before next request)
58
- end
59
- end
110
+ _import( id, content: content )
60
111
  end
61
112
  end
62
113
 
63
114
 
64
- def self.import_csv( path, content: true )
115
+ def import_csv( path, content: true )
65
116
  recs = read_csv( path )
66
117
  puts " #{recs.size} inscribe id(s)"
67
118
  #=> 1000 inscribe id(s)
@@ -70,30 +121,98 @@ def self.import_csv( path, content: true )
70
121
  id = rec['id']
71
122
  puts "==> #{i+1}/#{rec.size} @ #{id}..."
72
123
 
73
- ## check if inscription / inscribe is already in db?
74
- inscribe = Model::Inscribe.find_by( id: id )
75
- if inscribe ## already in db; dump record
76
- ## pp inscribe
77
- else ## fetch via ordinals.com api and update db
78
- data = Ordinals.inscription( id )
79
- pp data
80
- Model::Inscribe.create_from_api( data )
81
- sleep( 1 ) ## delay in seconds (before next request)
82
- end
124
+ _import( id, content: content )
125
+ end
126
+ end # method import_csv
83
127
 
84
- if content
85
- ## check if (content) blob is already in db?
86
- blob = Model::Blob.find_by( id: id )
87
- if blob ## already in db; do nothing
88
- else ## fetch via ordinals.com api and update db
89
- content = Ordinals.content( id )
90
- puts " content-type: #{content.type}"
91
- puts " content-length: #{content.length}"
92
-
93
- Model::Blob.create( id: id, content: content.data )
94
- sleep( 1 ) ## delay in seconds (before next request)
95
- end
128
+ def import( id_or_ids, content: true )
129
+ if id_or_ids.is_a?( String )
130
+ id = id_or_ids
131
+ _import( id, content: content )
132
+ else ## assume array
133
+ ids = id_or_ids
134
+ ids.each do |id|
135
+ _import( id, content: content )
96
136
  end
97
- end
98
- end # method self.import_csv
137
+ end
138
+ end
139
+
140
+ def _import( id, content: true )
141
+ ## check if inscription / inscribe is already in db?
142
+ inscribe = Inscribe.find_by( id: id )
143
+ if inscribe ## already in db; dump record
144
+ ## pp inscribe
145
+ else ## fetch via ordinals.com api and update db
146
+ data = Ordinals.inscription( id )
147
+
148
+ pp data
149
+ Inscribe.create_from_api( data )
150
+ end
151
+
152
+ if content
153
+ ## check if (content) blob is already in db?
154
+ blob = Blob.find_by( id: id )
155
+ if blob ## already in db; do nothing
156
+ else ## fetch via ordinals.com api and update db
157
+ content = Ordinals.content( id )
158
+
159
+ puts " content-type: #{content.type}"
160
+ puts " content-length: #{content.length}"
161
+
162
+ Blob.create( id: id, content: content.data )
163
+ end
164
+ end
165
+ end
166
+
167
+ end # class Importer
168
+
169
+
170
+
171
+ ###
172
+ ## convenience helpers
173
+
174
+ def self.importer ## "default" importer
175
+ @importer ||= Importer.new
176
+ end
177
+
178
+ def self.import( id_or_ids, content: true )
179
+ importer.import( id_or_ids, content: content )
180
+ end
181
+
182
+
183
+ def self.import_csv( path, content: true )
184
+ importer.import_csv( path, content: content )
185
+ end
186
+
187
+
188
+ def self.import_collection( path, content: true )
189
+ importer.import_collection( path, content: content )
190
+ end
191
+
192
+ def self.import_collection_inscriptions( path,
193
+ name:,
194
+ content: true )
195
+ importer.import_collection_inscriptions( path,
196
+ name: name,
197
+ content: content )
198
+ end
199
+
200
+ def self.import_collection_csv( path,
201
+ name:,
202
+ content: true )
203
+ importer.import_collection_csv( path,
204
+ name: name,
205
+ content: content )
206
+ end
207
+
208
+
209
+ module Model
210
+ class Inscribe
211
+ def self.import( id_or_ids, content: true )
212
+ OrdDb.importer.import( id_or_ids, content: content )
213
+ end
214
+ end # class Inscribe
215
+ end # module Model
216
+
217
+
99
218
  end # module OrdDb
@@ -2,7 +2,11 @@ module OrdDb
2
2
  module Model
3
3
 
4
4
  class Collection < ActiveRecord::Base
5
- has_many :items, -> { order('pos') }
5
+ has_many :items
6
+ ## -> { order('pos') }
7
+ ## note: default_scope (order)
8
+ ## will break all count queries and more
9
+ ## thus - no "magic" - always sort if pos order required!!!
6
10
  has_many :inscribes, :through => :items
7
11
  end # class Collection
8
12
 
@@ -7,7 +7,12 @@ module OrdDb
7
7
 
8
8
  belongs_to :inscribe
9
9
 
10
- has_many :inscriberefs, -> { order('pos') } ## join table (use habtm - why? why not?)
10
+ has_many :inscriberefs ## join table (use habtm - why? why not?)
11
+ ## -> { order('pos') }
12
+ ## note: default_scope (order)
13
+ ## will break all count queries and more
14
+ ## thus - no "magic" - always sort if pos order required!!!
15
+
11
16
  has_many :layers, :through => :inscriberefs,
12
17
  :source => :inscribe
13
18
 
@@ -66,29 +66,40 @@ SQL
66
66
  def self.sub20k() where( 'num < 20000' ); end
67
67
  def self.sub100k() where( 'num < 100000' ); end
68
68
  def self.sub1m() where( 'num < 1000000' ); end
69
+ def self.sub2m() where( 'num < 2000000' ); end
70
+ def self.sub10m() where( 'num < 10000000' ); end
71
+ def self.sub20m() where( 'num < 20000000' ); end
72
+ def self.sub21m() where( 'num < 21000000' ); end
69
73
 
70
74
 
71
75
  def self.largest
72
76
  order( 'bytes DESC' )
73
77
  end
74
78
 
79
+ def self.address_counts
80
+ group( 'address' )
81
+ .order( Arel.sql( 'COUNT(*) DESC')).count
82
+ end
83
+
75
84
  def self.block_counts
76
- group( 'block' ).count
85
+ group( 'block' )
86
+ .order( 'block').count
77
87
  end
78
88
 
79
89
  def self.block_with_timestamp_counts
80
- group( Arel.sql( "block || ' @ ' || date" )).count
90
+ group( Arel.sql( "block || ' @ ' || date" ))
91
+ .order( Arel.sql( "block || ' @ ' || date" ) ).count
81
92
  end
82
93
 
83
94
  def self.content_type_counts
84
- group( 'content_type' )
95
+ group( 'content_type' )
85
96
  .order( Arel.sql( 'COUNT(*) DESC, content_type')).count
86
97
  end
87
98
 
88
99
 
89
100
  def self.date_counts
90
101
  ## note: strftime is SQLite specific/only!!!
91
- group( Arel.sql("strftime('%Y-%m-%d', date)"))
102
+ group( Arel.sql("strftime('%Y-%m-%d', date)"))
92
103
  .order( Arel.sql("strftime('%Y-%m-%d', date)")).count
93
104
  end
94
105
 
@@ -100,13 +111,14 @@ SQL
100
111
 
101
112
  def self.hour_counts
102
113
  ## note: strftime is SQLite specific/only!!!
103
- group( Arel.sql("strftime('%Y-%m-%d %Hh', date)"))
114
+ group( Arel.sql("strftime('%Y-%m-%d %Hh', date)"))
104
115
  .order( Arel.sql("strftime('%Y-%m-%d %Hh', date)")).count
105
116
  end
106
117
 
107
118
 
108
119
  class << self
109
120
  alias_method :biggest, :largest
121
+ alias_method :counts_by_address, :address_counts
110
122
  alias_method :counts_by_content_type, :content_type_counts
111
123
  alias_method :counts_by_date, :date_counts
112
124
  alias_method :counts_by_day, :date_counts
@@ -4,7 +4,7 @@ module Ordlite
4
4
  # sync version w/ sport.db n friends - why? why not?
5
5
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
6
6
  MINOR = 2
7
- PATCH = 0
7
+ PATCH = 1
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ordlite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-28 00:00:00.000000000 Z
11
+ date: 2023-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ordinals
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pixelart
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: rdoc
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -173,6 +187,7 @@ files:
173
187
  - lib/ordlite.rb
174
188
  - lib/ordlite/base.rb
175
189
  - lib/ordlite/cache.rb
190
+ - lib/ordlite/factory.rb
176
191
  - lib/ordlite/importer.rb
177
192
  - lib/ordlite/models/blob.rb
178
193
  - lib/ordlite/models/collection.rb