nazar 0.0.5 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/main.yml +5 -1
- data/README.md +148 -4
- data/lib/nazar/cell_formatter.rb +24 -5
- data/lib/nazar/formatter/active_record_collection.rb +6 -0
- data/lib/nazar/formatter/active_record_item.rb +4 -0
- data/lib/nazar/formatter/csv_table.rb +4 -0
- data/lib/nazar/formatter/generic.rb +55 -0
- data/lib/nazar/formatter/sequel_collection.rb +24 -0
- data/lib/nazar/formatter/sequel_interface.rb +33 -0
- data/lib/nazar/formatter/sequel_item.rb +25 -0
- data/lib/nazar/renderer.rb +9 -3
- data/lib/nazar/version.rb +1 -1
- data/lib/nazar/view.rb +10 -38
- data/lib/nazar.rb +98 -23
- data/nazar.gemspec +3 -1
- data.tar.gz.sig +0 -0
- metadata +38 -6
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3ea71c523b3f82b6882bdcb11b842e53b4f2283bc95d1ab5e8c0e17e2b1c9b6
|
4
|
+
data.tar.gz: 97017a09da4032dd35b90e34cd49cf92e96473f7c1f001a8f9ffab1c93ae6d2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb511b109dc83d28057e6454a5d438e799cfbb0a6eb64d2f0c55ae53dd8e92c19f0c78b4a361452307e41999738972260e2b5b4b6dc347c05ddaf81e49b452bd
|
7
|
+
data.tar.gz: 5c0f4e67fea1a380606dd75bac52de072ac9851f70b844ee8ba1464c73592e49cde3f0449fcb208cdb912b938e067fce4a8af0a7d5f7076e244e6b78d2cfa336
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/workflows/main.yml
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,154 @@
|
|
1
|
-
# Nazar [![Build Status](https://github.com/krzyzak/nazar/actions/workflows/main.yml/badge.svg)](https://github.com/krzyzak/nazar/actions) [![Code Climate](https://codeclimate.com/github/krzyzak/nazar/badges/gpa.svg)](https://codeclimate.com/github/krzyzak/nazar)
|
1
|
+
# Nazar [![Build Status](https://github.com/krzyzak/nazar/actions/workflows/main.yml/badge.svg)](https://github.com/krzyzak/nazar/actions) [![Gem Version](https://badge.fury.io/rb/nazar.svg)](https://badge.fury.io/rb/nazar) [![Code Climate](https://codeclimate.com/github/krzyzak/nazar/badges/gpa.svg)](https://codeclimate.com/github/krzyzak/nazar) [![Test Coverage](https://api.codeclimate.com/v1/badges/f89b8bfdf557900e1f9f/test_coverage)](https://codeclimate.com/github/krzyzak/nazar/test_coverage)
|
2
2
|
|
3
|
-
|
3
|
+
Turn this:
|
4
|
+
```ruby
|
5
|
+
>> User.all
|
6
|
+
User Load (0.4ms) SELECT "users".* FROM "users" /* loading for inspect */ LIMIT ? [["LIMIT", 11]]
|
7
|
+
=> #<ActiveRecord::Relation [#<User id: 1, email: "delma@goldner.co", name: "Mrs. Charis Brown", description: "Quasi atque ea. Beatae corporis quia. Eveniet veli...", created_at: "2021-09-01 05:42:24.341344000 +0000", updated_at: "2021-09-20 09:36:29.289078000 +0000", active: false, last_login_at: nil>, #<User id: 2, email: "markpfeffer@wunschbraun.info", name: "Ms. Sherice Champlin", description: "Omnis ut illum. Non velit mollitia. Expedita facil...", created_at: "2021-09-10 07:27:00.182298000 +0000", updated_at: "2021-09-20 09:36:29.292065000 +0000", active: true, last_login_at: "2021-09-19 16:25:32.094418000 +0000">, #<User id: 3, email: "nathansimonis@kunde.org", name: "Florentino Gleason", description: "Non recusandae eos. Et voluptates iusto. Commodi e...", created_at: "2021-09-07 18:24:45.608164000 +0000", updated_at: "2021-09-20 09:36:29.293572000 +0000", active: false, last_login_at: nil>, #<User id: 4, email: "edwardowilkinson@walkerschiller.info", name: "Judie Boehm", description: "Ut ea eum. Tempore voluptates praesentium. Animi s...", created_at: "2021-09-05 02:11:36.564693000 +0000", updated_at: "2021-09-20 09:36:29.295763000 +0000", active: true, last_login_at: "2021-09-19 20:17:24.074515000 +0000">, #<User id: 5, email: "isaiahebert@brauncarroll.net", name: "Mari Ullrich", description: "Aperiam quas voluptas. Autem alias quia. Aut persp...", created_at: "2021-09-09 05:23:03.229860000 +0000", updated_at: "2021-09-20 09:36:29.296928000 +0000", active: nil, last_login_at: nil>, #<User id: 6, email: "alexander@anderson.io", name: "Sam Larson DDS", description: "Sed velit consectetur. Quas cupiditate enim. Neque...", created_at: "2021-09-03 02:52:14.055696000 +0000", updated_at: "2021-09-20 09:36:29.299157000 +0000", active: true, last_login_at: "2021-09-20 05:01:39.019563000 +0000">, #<User id: 7, email: "chirunolfon@keler.io", name: "Ying Kub I", description: "Cupiditate ut consequatur. Eos ab laboriosam. Ipsa...", created_at: "2021-09-10 05:52:32.005877000 +0000", updated_at: "2021-09-20 09:36:29.301469000 +0000", active: true, last_login_at: "2021-09-19 21:30:48.854010000 +0000">, #<User id: 8, email: "johnny@anderson.net", name: "Johnie Corwin II", description: "Suscipit itaque adipisci. Assumenda ad error. Quas...", created_at: "2021-09-12 13:05:49.845361000 +0000", updated_at: "2021-09-20 09:36:29.302657000 +0000", active: nil, last_login_at: nil>, #<User id: 9, email: "yahairakuhn@schneider.com", name: "Sharie Weber", description: "Sapiente voluptatum mollitia. Dolores voluptatum a...", created_at: "2021-09-19 03:03:39.360526000 +0000", updated_at: "2021-09-20 09:36:29.304929000 +0000", active: true, last_login_at: "2021-09-20 06:46:05.846685000 +0000">, #<User id: 10, email: "tommye@schuppe.biz", name: "Yoshiko Mohr", description: "Similique laborum totam. Non cum atque. Placeat qu...", created_at: "2021-09-08 05:41:36.588541000 +0000", updated_at: "2021-09-20 09:36:29.306120000 +0000", active: nil, last_login_at: nil>, ...]>
|
8
|
+
```
|
9
|
+
Into this:
|
4
10
|
|
5
|
-
|
11
|
+
```ruby
|
12
|
+
>> User.all
|
13
|
+
(0.6ms) SELECT sqlite_version(*)
|
14
|
+
User Load (0.8ms) SELECT "users".* FROM "users"
|
15
|
+
┏━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
16
|
+
┃ id │ email │ name │ description │ created_at │ updated_at │ active │ last_login_at ┃
|
17
|
+
┣═══════╪══════════════════════════════════════╪═══════════════════════╪═════════════════════════════════════════════════════════════════════════════════════════╪═════════════════════════╪═════════════════════════╪════════╪═════════════════════════┫
|
18
|
+
┃ 1 │ delma@goldner.co │ Mrs. Charis Brown │ Quasi atque ea. Beatae corporis quia. Eveniet velit ad. │ 2021-09-01 05:42:24 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
19
|
+
┃ 2 │ markpfeffer@wunschbraun.info │ Ms. Sherice Champlin │ Omnis ut illum. Non velit mollitia. Expedita facilis dignissimos. │ 2021-09-10 07:27:00 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-19 16:25:32 UTC ┃
|
20
|
+
┃ 3 │ nathansimonis@kunde.org │ Florentino Gleason │ Non recusandae eos. Et voluptates iusto. Commodi est in. │ 2021-09-07 18:24:45 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
21
|
+
┃ 4 │ edwardowilkinson@walkerschiller.info │ Judie Boehm │ Ut ea eum. Tempore voluptates praesentium. Animi sapiente distinctio. │ 2021-09-05 02:11:36 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-19 20:17:24 UTC ┃
|
22
|
+
┃ 5 │ isaiahebert@brauncarroll.net │ Mari Ullrich │ Aperiam quas voluptas. Autem alias quia. Aut perspiciatis eos. │ 2021-09-09 05:23:03 UTC │ 2021-09-20 09:36:29 UTC │ ∅ │ ∅ ┃
|
23
|
+
┃ 6 │ alexander@anderson.io │ Sam Larson DDS │ Sed velit consectetur. Quas cupiditate enim. Neque facere harum. │ 2021-09-03 02:52:14 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-20 05:01:39 UTC ┃
|
24
|
+
┃ 7 │ chirunolfon@keler.io │ Ying Kub I │ Cupiditate ut consequatur. Eos ab laboriosam. Ipsam ut veritatis. │ 2021-09-10 05:52:32 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-19 21:30:48 UTC ┃
|
25
|
+
┃ 8 │ johnny@anderson.net │ Johnie Corwin II │ Suscipit itaque adipisci. Assumenda ad error. Quas enim beatae. │ 2021-09-12 13:05:49 UTC │ 2021-09-20 09:36:29 UTC │ ∅ │ ∅ ┃
|
26
|
+
┃ 9 │ yahairakuhn@schneider.com │ Sharie Weber │ Sapiente voluptatum mollitia. Dolores voluptatum accusamus. Veniam voluptatem deserunt. │ 2021-09-19 03:03:39 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-20 06:46:05 UTC ┃
|
27
|
+
┃ 10 │ tommye@schuppe.biz │ Yoshiko Mohr │ Similique laborum totam. Non cum atque. Placeat quia velit. │ 2021-09-08 05:41:36 UTC │ 2021-09-20 09:36:29 UTC │ ∅ │ ∅ ┃
|
28
|
+
┃ 11 │ derekbeier@hermankuhlman.co │ Lavern Feil │ Itaque molestias et. Iure tempora minus. Dolore autem omnis. │ 2021-09-05 04:04:51 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
29
|
+
┃ 12 │ lavernwillms@runolfsdottirbogan.org │ Marcy Gottlieb Sr. │ Mollitia quia dolor. Libero laborum aperiam. Velit est eum. │ 2021-09-08 19:22:49 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
30
|
+
┃ 13 │ earlhills@mclaughlingreenholt.info │ Adina Luettgen │ In qui rem. Illum itaque dignissimos. Enim vitae tenetur. │ 2021-09-08 10:16:12 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
31
|
+
┃ 14 │ larry@rice.com │ Carolina Kuhlman II │ Ipsum ut fuga. Sunt id a. Rerum nulla sint. │ 2021-09-03 23:11:42 UTC │ 2021-09-20 09:36:29 UTC │ ∅ │ ∅ ┃
|
32
|
+
┃ 15 │ randy@kuhicfritsch.name │ Harvey Runolfsdottir │ Dolorum officiis sed. Ut recusandae culpa. Odit aut nostrum. │ 2021-09-08 04:28:38 UTC │ 2021-09-20 09:36:29 UTC │ ∅ │ ∅ ┃
|
33
|
+
┃ 16 │ lashaun@mooreleannon.co │ Lucio Raynor │ Et expedita rerum. Autem nesciunt labore. Suscipit aut eum. │ 2021-09-06 20:47:51 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
34
|
+
┃ 17 │ omeryost@becker.com │ Rocky Hettinger │ Ut deleniti voluptas. Explicabo voluptas rerum. Illum sapiente quo. │ 2021-09-14 23:05:33 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-20 09:35:14 UTC ┃
|
35
|
+
┃ 18 │ nilsa@corwinkub.name │ Serena Brakus │ Qui non provident. Omnis excepturi quasi. Ratione suscipit dolor. │ 2021-09-14 01:06:02 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
36
|
+
┃ 19 │ berniebednar@spinkamiller.co │ Merlin Predovic │ Omnis et minus. Tempore in laboriosam. Molestiae aut eveniet. │ 2021-09-16 18:34:20 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-19 12:01:59 UTC ┃
|
37
|
+
┃ 20 │ claude@smithamhaley.io │ Claudette Thompson MD │ Aut consectetur soluta. Laborum quia qui. Vel incidunt minima. │ 2021-09-10 03:53:24 UTC │ 2021-09-20 09:36:29 UTC │ ∅ │ ∅ ┃
|
38
|
+
┃ 21 │ matilde@cormierstroman.name │ Dalton Witting │ Voluptatum provident earum. Ad esse odit. Quasi non ut. │ 2021-09-10 04:51:53 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
39
|
+
┃ 22 │ randistrosin@littel.io │ Miss Lucio Kub │ Ea quia sapiente. Reprehenderit esse ut. Veritatis magnam quia. │ 2021-08-31 18:33:02 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
40
|
+
┃ 23 │ noah@kuphal.co │ Alonzo Stroman │ Officia fugit eos. Qui quo et. Ducimus harum dignissimos. │ 2021-09-13 14:36:31 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
41
|
+
┃ 24 │ cristinaschneider@cole.biz │ Dr. Newton Ritchie │ Corporis suscipit recusandae. Voluptas voluptas quo. Non perferendis fugiat. │ 2021-09-02 20:54:38 UTC │ 2021-09-20 09:36:29 UTC │ ✓ │ 2021-09-20 02:35:39 UTC ┃
|
42
|
+
┃ 25 │ mirtha@spinkabayer.co │ Kory Cummings │ Aut ut aut. Quis voluptas sit. Consequatur quia voluptatibus. │ 2021-09-17 08:45:02 UTC │ 2021-09-20 09:36:29 UTC │ ✗ │ ∅ ┃
|
43
|
+
┠───────┼──────────────────────────────────────┴───────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────┴─────────────────────────┴────────┴─────────────────────────┨
|
44
|
+
┃ Total │ 25 ┃
|
45
|
+
┗━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
46
|
+
```
|
6
47
|
|
7
|
-
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
### Per-project installation
|
51
|
+
|
52
|
+
While nothing stops you from adding Nazar to each project separately, I find it cumbersome to add it to every project I'm working on - it also alters REPL behaviour for other teammates, which is another reason why personally I don't recommend that approach. Anyway, here's quick how-to:
|
53
|
+
|
54
|
+
Add `nazar` to Gemfile:
|
55
|
+
```ruby
|
56
|
+
group :development, :test do
|
57
|
+
gem 'nazar', require: false
|
58
|
+
end
|
59
|
+
```
|
60
|
+
Then, you have to call `Nazar.enable!`. If you're using Rails, you might want to add this snippet to `config/application.rb`:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
console do
|
64
|
+
require 'nazar'
|
65
|
+
|
66
|
+
Nazar.enable! # See configuration section for more options and
|
67
|
+
# Opt-in setup section if you don't want to enable it for every item
|
68
|
+
end
|
69
|
+
```
|
70
|
+
Otherwise, call it in `bin/console` or any other script that launches your REPL.
|
71
|
+
|
72
|
+
### Global installation
|
73
|
+
|
74
|
+
This is my recommended way to install this gem - that way it works automatically in all your projects, even in standalone `irb` or `pry` sessions.
|
75
|
+
|
76
|
+
- **Create global gems path**
|
77
|
+
|
78
|
+
`mkdir -p ~/.gem/ruby/global` - You're welcome to use any other path for your global gemset
|
79
|
+
- **Install nazar in your global gemset**
|
80
|
+
|
81
|
+
`gem install nazar -i ~/.gem/ruby/global`
|
82
|
+
- **Load Nazar in your REPL rc file**
|
83
|
+
Add following snippet to your `.irbrc` or `.pryrc`:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
global_gemset_path = File.expand_path('~/.gem/ruby/global/gems')
|
87
|
+
|
88
|
+
if Dir.exist?(global_gemset_path)
|
89
|
+
global_gems_path = Dir.glob("#{global_gemset_path}/*/lib")
|
90
|
+
|
91
|
+
$LOAD_PATH.unshift(*global_gems_path)
|
92
|
+
end
|
93
|
+
|
94
|
+
%w[nazar].each do |gem|
|
95
|
+
begin
|
96
|
+
require gem
|
97
|
+
rescue LoadError
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
Nazar.enable! if defined?(Nazar)
|
102
|
+
```
|
103
|
+
|
104
|
+
## Shorthand method
|
105
|
+
|
106
|
+
Nazar defines top level `__(data)` method, that can be useful for two things:
|
107
|
+
|
108
|
+
### Inspecting (array of) Hashes/Structs
|
109
|
+
|
110
|
+
Nazar by design won't enhance output for any collection that does not consist of supported (eg. ActiveRecord/Sequel) items. If you have a data that is structurally compatible (ie: all items consists of the same keys), and want to enahance the output, you can simply use `#__` method:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
__ [{foo: :bar, test: 123},{foo: :baz, test: 456}]
|
114
|
+
┏━━━━━━━┯━━━━━━┓
|
115
|
+
┃ foo │ test ┃
|
116
|
+
┣═══════╪══════┫
|
117
|
+
┃ :bar │ 123 ┃
|
118
|
+
┃ :baz │ 456 ┃
|
119
|
+
┠───────┼──────┨
|
120
|
+
┃ Total │ 2 ┃
|
121
|
+
┗━━━━━━━┷━━━━━━┛
|
122
|
+
```
|
123
|
+
|
124
|
+
It works with Structs and Hashes (or, more specifically - with any object that reponds to `#keys` and `#values`)
|
125
|
+
|
126
|
+
### Opt-in setup
|
127
|
+
|
128
|
+
If you use `Nazar.load!` instead of `Nazar.enable!`, it would not enhance output for every element in the console. Instead, you have to call `#__` for each item that you want to enhance output
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
|
132
|
+
Nazar.load!
|
133
|
+
User.all # Returns default output
|
134
|
+
__ User.all # Returns output enhanced by Nazar
|
135
|
+
```
|
136
|
+
|
137
|
+
|
138
|
+
## Configuration
|
139
|
+
|
140
|
+
By default, Nazar improves output for ActiveRecord (both collections and a single item) and for CSV Tables. You can configure that by calling `#enable!` with optional argument:
|
141
|
+
|
142
|
+
`Nazar.enable!(extensions: [:active_record, :csv, :sequel])` will enhance output for <a href="https://github.com/jeremyevans/sequel/">Sequel</a> as well.
|
143
|
+
|
144
|
+
You can also configure behaviour of Nazar:
|
145
|
+
|
146
|
+
| Config | Default | Description |
|
147
|
+
| ------ | ------- | ----------- |
|
148
|
+
| `Nazar.config.colors.enabled` | true | Determines whether the output should be colorised or not |
|
149
|
+
| `Nazar.config.formatter.nil` | `∅` | Sets character printed if the value was nil |
|
150
|
+
| `Nazar.config.formatter.boolean` | ['✓', '✗'] | First item in array is a character for `true`, second for `false` |
|
151
|
+
| `Nazar.config.enable_shorthand_method` | true | Determines if shorthand method should be defined. See <a href="#opt-in-setup">Opt-in setup</a> for more details |
|
8
152
|
|
9
153
|
## Contributing
|
10
154
|
|
data/lib/nazar/cell_formatter.rb
CHANGED
@@ -10,11 +10,11 @@ module Nazar
|
|
10
10
|
def format
|
11
11
|
case type
|
12
12
|
when :boolean
|
13
|
-
format_boolean
|
13
|
+
format_boolean
|
14
14
|
when :integer
|
15
|
-
|
15
|
+
format_number
|
16
16
|
else
|
17
|
-
value.nil? ? format_nil :
|
17
|
+
value.nil? ? format_nil : inteligent_format
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -22,7 +22,7 @@ module Nazar
|
|
22
22
|
|
23
23
|
attr_reader :value, :type
|
24
24
|
|
25
|
-
def format_boolean
|
25
|
+
def format_boolean
|
26
26
|
return format_nil if value.nil?
|
27
27
|
|
28
28
|
true_value, false_value = Nazar.config.formatter.boolean
|
@@ -30,7 +30,26 @@ module Nazar
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def format_nil
|
33
|
-
|
33
|
+
pastel.dim(Nazar.config.formatter.nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_number
|
37
|
+
pastel.bright_blue(value)
|
38
|
+
end
|
39
|
+
|
40
|
+
def inteligent_format
|
41
|
+
case value
|
42
|
+
when Symbol
|
43
|
+
pastel.magenta(":#{value}")
|
44
|
+
when Numeric
|
45
|
+
format_number
|
46
|
+
else
|
47
|
+
value.to_s
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def pastel
|
52
|
+
@pastel ||= Pastel.new(enabled: Nazar.config.colors.enabled)
|
34
53
|
end
|
35
54
|
end
|
36
55
|
end
|
@@ -15,6 +15,12 @@ module Nazar
|
|
15
15
|
@klass = collection.first&.class
|
16
16
|
end
|
17
17
|
|
18
|
+
def self.valid?(data)
|
19
|
+
data.is_a?(ActiveRecord::Associations::CollectionProxy) ||
|
20
|
+
data.is_a?(ActiveRecord::Relation) ||
|
21
|
+
(data.is_a?(Enumerable) && data.first.is_a?(ActiveRecord::Base))
|
22
|
+
end
|
23
|
+
|
18
24
|
def summary
|
19
25
|
collection.size
|
20
26
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nazar
|
4
|
+
module Formatter
|
5
|
+
class Generic
|
6
|
+
attr_reader :collection
|
7
|
+
|
8
|
+
def initialize(collection)
|
9
|
+
@collection = Array(collection)
|
10
|
+
@item = collection.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def headers
|
14
|
+
HeadersFormatter.new(raw_headers).format
|
15
|
+
end
|
16
|
+
|
17
|
+
def cells
|
18
|
+
@cells ||= collection.map do |item|
|
19
|
+
item.values.map do |value|
|
20
|
+
CellFormatter.new(value).format
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def summary
|
26
|
+
collection.size
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.valid?(data)
|
30
|
+
item = data.first
|
31
|
+
compatible = item.respond_to?(:keys) && item.respond_to?(:values)
|
32
|
+
|
33
|
+
data.is_a?(Enumerable) && (item.is_a?(Struct) || compatible)
|
34
|
+
end
|
35
|
+
|
36
|
+
def valid?
|
37
|
+
!!item && !raw_headers.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_reader :item
|
43
|
+
|
44
|
+
def raw_headers
|
45
|
+
@raw_headers ||= if item.is_a?(Struct)
|
46
|
+
item.members
|
47
|
+
elsif item.respond_to?(:keys)
|
48
|
+
item.keys
|
49
|
+
else
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nazar/formatter/sequel_interface'
|
4
|
+
|
5
|
+
module Nazar
|
6
|
+
module Formatter
|
7
|
+
class SequelCollection
|
8
|
+
include SequelInterface
|
9
|
+
|
10
|
+
def initialize(collection)
|
11
|
+
@collection = collection
|
12
|
+
@attributes = collection.first&.values
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.valid?(data)
|
16
|
+
(data.is_a?(Enumerable) && data.first.is_a?(Sequel::Model)) || data.is_a?(Sequel::Dataset)
|
17
|
+
end
|
18
|
+
|
19
|
+
def summary
|
20
|
+
collection.size
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nazar
|
4
|
+
module Formatter
|
5
|
+
module SequelInterface
|
6
|
+
attr_reader :collection, :klass, :attributes
|
7
|
+
|
8
|
+
def valid?
|
9
|
+
!!attributes
|
10
|
+
end
|
11
|
+
|
12
|
+
def headers
|
13
|
+
HeadersFormatter.new(attributes.keys).format
|
14
|
+
end
|
15
|
+
|
16
|
+
def cells
|
17
|
+
@cells ||= begin
|
18
|
+
schema = collection.first.db_schema
|
19
|
+
|
20
|
+
collection.map do |item|
|
21
|
+
item.values.map do |column, value|
|
22
|
+
CellFormatter.new(value, type: schema.dig(column, :type)).format
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def summary
|
29
|
+
collection.size
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nazar/formatter/sequel_interface'
|
4
|
+
|
5
|
+
module Nazar
|
6
|
+
module Formatter
|
7
|
+
class SequelItem
|
8
|
+
include SequelInterface
|
9
|
+
|
10
|
+
def initialize(item)
|
11
|
+
@collection = [item]
|
12
|
+
@attributes = item.values
|
13
|
+
@klass = item.class
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.valid?(data)
|
17
|
+
data.is_a?(Sequel::Model)
|
18
|
+
end
|
19
|
+
|
20
|
+
def summary
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/nazar/renderer.rb
CHANGED
@@ -2,12 +2,18 @@
|
|
2
2
|
|
3
3
|
module Nazar
|
4
4
|
class Renderer
|
5
|
-
def initialize(data)
|
5
|
+
def initialize(data, use_generic_formatter: false)
|
6
6
|
@data = data
|
7
|
+
@use_generic_formatter = use_generic_formatter
|
7
8
|
end
|
8
9
|
|
9
10
|
def render
|
10
|
-
pager.page(view.render)
|
11
|
+
pager.page(view.render)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
view.supported_data?
|
11
17
|
end
|
12
18
|
|
13
19
|
def pager
|
@@ -19,7 +25,7 @@ module Nazar
|
|
19
25
|
attr_reader :data
|
20
26
|
|
21
27
|
def view
|
22
|
-
@view ||= View.new(data)
|
28
|
+
@view ||= View.new(data, use_generic_formatter: @use_generic_formatter)
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
data/lib/nazar/version.rb
CHANGED
data/lib/nazar/view.rb
CHANGED
@@ -6,8 +6,9 @@ module Nazar
|
|
6
6
|
|
7
7
|
def_delegators :formatter, :headers, :cells, :summary
|
8
8
|
|
9
|
-
def initialize(data)
|
9
|
+
def initialize(data, use_generic_formatter: false)
|
10
10
|
@data = data
|
11
|
+
@use_generic_formatter = use_generic_formatter
|
11
12
|
end
|
12
13
|
|
13
14
|
def render
|
@@ -24,49 +25,20 @@ module Nazar
|
|
24
25
|
|
25
26
|
private
|
26
27
|
|
27
|
-
attr_reader :data
|
28
|
+
attr_reader :data, :use_generic_formatter
|
28
29
|
|
29
|
-
def
|
30
|
-
@
|
31
|
-
|
32
|
-
nil
|
33
|
-
when acttive_record_collection?
|
34
|
-
Formatter::ActiveRecordCollection
|
35
|
-
when active_record_item?
|
36
|
-
Formatter::ActiveRecordItem
|
37
|
-
when csv_table?
|
38
|
-
Formatter::CSVTable
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def formatter
|
43
|
-
@formatter ||= formatter_klass.new(data)
|
44
|
-
end
|
45
|
-
|
46
|
-
def boolean?
|
47
|
-
proc { data === true || data === false } # rubocop:disable Style/CaseEquality
|
48
|
-
end
|
49
|
-
|
50
|
-
def acttive_record_collection?
|
51
|
-
return false unless Nazar.extensions.include?(:active_record)
|
52
|
-
|
53
|
-
proc do
|
54
|
-
data.is_a?(ActiveRecord::Associations::CollectionProxy) ||
|
55
|
-
data.is_a?(ActiveRecord::Relation) ||
|
56
|
-
(data.is_a?(Array) && data.first.is_a?(ActiveRecord::Base))
|
30
|
+
def formatters
|
31
|
+
@formatters ||= Nazar.formatters.tap do |formatters|
|
32
|
+
formatters << Nazar::Formatter::Generic if use_generic_formatter
|
57
33
|
end
|
58
34
|
end
|
59
35
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
proc { data.is_a?(ActiveRecord::Base) }
|
36
|
+
def formatter_klass
|
37
|
+
@formatter_klass ||= formatters.find { |klass| klass.valid?(data) }
|
64
38
|
end
|
65
39
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
proc { data.is_a?(CSV::Table) }
|
40
|
+
def formatter
|
41
|
+
@formatter ||= formatter_klass.new(data)
|
70
42
|
end
|
71
43
|
|
72
44
|
def add_summary
|
data/lib/nazar.rb
CHANGED
@@ -10,9 +10,10 @@ require 'nazar/cell_formatter'
|
|
10
10
|
require 'nazar/headers_formatter'
|
11
11
|
require 'nazar/renderer'
|
12
12
|
require 'nazar/formatter'
|
13
|
+
require 'nazar/formatter/generic'
|
13
14
|
require 'nazar/view'
|
14
15
|
|
15
|
-
module Nazar
|
16
|
+
module Nazar # rubocop:disable Metrics/ModuleLength
|
16
17
|
extend Dry::Configurable
|
17
18
|
|
18
19
|
setting :formatter do
|
@@ -24,60 +25,130 @@ module Nazar
|
|
24
25
|
setting :enabled, default: ENV.fetch('ENABLE_TTY_COLORS') { TTY::Color.color? ? 'true' : 'false' } == 'true'
|
25
26
|
end
|
26
27
|
|
28
|
+
setting :enable_shorthand_method, default: true
|
29
|
+
|
27
30
|
class << self
|
28
|
-
def
|
29
|
-
@
|
31
|
+
def formatters
|
32
|
+
@formatters ||= Set.new
|
30
33
|
end
|
31
34
|
|
32
35
|
def enable!(extensions: [:active_record, :csv])
|
33
36
|
return if @enabled
|
34
37
|
|
35
|
-
|
36
|
-
|
38
|
+
load_extensions!(extensions)
|
39
|
+
enable_repl!
|
37
40
|
|
38
|
-
|
39
|
-
enable_for_pry! if defined?(Pry)
|
41
|
+
enable_shorthand_method! if Nazar.config.enable_shorthand_method
|
40
42
|
|
41
43
|
@enabled = true
|
42
44
|
end
|
43
45
|
|
44
|
-
def
|
45
|
-
extensions
|
46
|
+
def load!(extensions: [:active_record, :csv])
|
47
|
+
load_extensions!(extensions)
|
48
|
+
enable_shorthand_method! if Nazar.config.enable_shorthand_method
|
46
49
|
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def load_csv!
|
47
54
|
require 'csv'
|
48
|
-
|
55
|
+
|
56
|
+
register_formatter!('CSVTable', 'nazar/formatter/csv_table')
|
49
57
|
end
|
50
58
|
|
51
59
|
def load_active_record!
|
52
|
-
extensions << :active_record
|
53
|
-
|
54
60
|
require 'active_record'
|
55
|
-
|
56
|
-
|
61
|
+
|
62
|
+
register_formatter!('ActiveRecordCollection', 'nazar/formatter/active_record_collection')
|
63
|
+
register_formatter!('ActiveRecordItem', 'nazar/formatter/active_record_item')
|
64
|
+
end
|
65
|
+
|
66
|
+
def load_sequel!
|
67
|
+
require 'sequel'
|
68
|
+
|
69
|
+
register_formatter!('SequelCollection', 'nazar/formatter/sequel_collection')
|
70
|
+
register_formatter!('SequelItem', 'nazar/formatter/sequel_item')
|
71
|
+
end
|
72
|
+
|
73
|
+
def register_formatter!(klass_name, path)
|
74
|
+
require path
|
75
|
+
|
76
|
+
formatters << Nazar::Formatter.const_get(klass_name)
|
77
|
+
end
|
78
|
+
|
79
|
+
def pry_proc
|
80
|
+
return unless defined?(Pry)
|
81
|
+
|
82
|
+
proc do |output, value, instance|
|
83
|
+
renderer = Nazar::Renderer.new(value)
|
84
|
+
renderer.valid? ? renderer.render : @__original_pry_print.call(output, value, instance)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def disable!
|
89
|
+
disable_shorthand_method! if @defined_shorthand_method
|
90
|
+
|
91
|
+
return unless @enabled
|
92
|
+
|
93
|
+
disable_for_irb! if defined?(IRB)
|
94
|
+
disable_for_pry! if defined?(Pry)
|
95
|
+
|
96
|
+
@enabled = false
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def load_extensions!(extensions)
|
102
|
+
load_active_record! if extensions.include?(:active_record)
|
103
|
+
load_csv! if extensions.include?(:csv)
|
104
|
+
load_sequel! if extensions.include?(:sequel)
|
105
|
+
end
|
106
|
+
|
107
|
+
def enable_repl!
|
108
|
+
enable_for_irb! if defined?(IRB)
|
109
|
+
enable_for_pry! if defined?(Pry)
|
57
110
|
end
|
58
111
|
|
59
112
|
def enable_for_irb!
|
60
113
|
::IRB::Irb.class_eval do
|
61
114
|
alias_method :__original_output_value__, :output_value
|
62
115
|
def output_value(omit = false) # rubocop:disable Style/OptionalBooleanParameter
|
63
|
-
|
116
|
+
renderer = Nazar::Renderer.new(@context.last_value)
|
117
|
+
renderer.valid? ? renderer.render : __original_output_value__(omit)
|
64
118
|
end
|
65
119
|
end
|
66
120
|
end
|
67
121
|
|
68
122
|
def enable_for_pry!
|
69
|
-
@__original_pry_print
|
70
|
-
|
71
|
-
|
123
|
+
@__original_pry_print ||= Pry.config.print
|
124
|
+
|
125
|
+
if Pry.toplevel_binding.local_variable_defined?(:pry_instance)
|
126
|
+
Pry.toplevel_binding.eval('pry_instance.config.print = Nazar.pry_proc', __FILE__, __LINE__)
|
127
|
+
else
|
128
|
+
Pry.config.print = Nazar.pry_proc
|
72
129
|
end
|
73
130
|
end
|
74
131
|
|
75
|
-
def
|
76
|
-
|
132
|
+
def enable_shorthand_method!
|
133
|
+
if Object.respond_to?(:__)
|
134
|
+
return warn Pastel.new.red("Already defined Object#__() method, Nazar won't redefine it.")
|
135
|
+
end
|
77
136
|
|
78
|
-
|
137
|
+
@defined_shorthand_method = true
|
79
138
|
|
80
|
-
|
139
|
+
Object.class_eval do
|
140
|
+
def __(item)
|
141
|
+
Nazar::Renderer.new(item, use_generic_formatter: true).render
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def disable_shorthand_method!
|
147
|
+
@defined_shorthand_method = nil
|
148
|
+
|
149
|
+
Object.class_eval do
|
150
|
+
undef_method :__
|
151
|
+
end
|
81
152
|
end
|
82
153
|
|
83
154
|
def disable_for_irb!
|
@@ -85,7 +156,11 @@ module Nazar
|
|
85
156
|
end
|
86
157
|
|
87
158
|
def disable_for_pry!
|
88
|
-
|
159
|
+
Pry.toplevel_binding.eval(
|
160
|
+
'pry_instance.config.print = Nazar.instance_variable_get(:@__original_pry_print)',
|
161
|
+
__FILE__,
|
162
|
+
__LINE__
|
163
|
+
)
|
89
164
|
end
|
90
165
|
end
|
91
166
|
end
|
data/nazar.gemspec
CHANGED
@@ -28,7 +28,9 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_development_dependency 'activerecord', '>= 3.0', '< 6.2'
|
30
30
|
spec.add_development_dependency 'rubocop', '~> 1.21'
|
31
|
-
spec.add_development_dependency '
|
31
|
+
spec.add_development_dependency 'sequel', '~> 5.0'
|
32
|
+
spec.add_development_dependency 'simplecov', '~> 0.20'
|
33
|
+
spec.add_development_dependency 'sqlite3', '~> 1.0'
|
32
34
|
|
33
35
|
spec.add_runtime_dependency 'dry-configurable', '~> 0.12'
|
34
36
|
spec.add_runtime_dependency 'pastel', '~> 0.8'
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nazar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michał Krzyżanowski
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
FlwFUDGjWAe8lcsjyGp1dox0FK91TAHdZW1op8LYnOcO2DM8Mgzu4Gp7mibATEnx
|
37
37
|
ooN2pwmH
|
38
38
|
-----END CERTIFICATE-----
|
39
|
-
date: 2021-
|
39
|
+
date: 2021-10-06 00:00:00.000000000 Z
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activerecord
|
@@ -72,20 +72,48 @@ dependencies:
|
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '1.21'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: sequel
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '5.0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '5.0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: simplecov
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0.20'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.20'
|
75
103
|
- !ruby/object:Gem::Dependency
|
76
104
|
name: sqlite3
|
77
105
|
requirement: !ruby/object:Gem::Requirement
|
78
106
|
requirements:
|
79
|
-
- - "
|
107
|
+
- - "~>"
|
80
108
|
- !ruby/object:Gem::Version
|
81
|
-
version: '0'
|
109
|
+
version: '1.0'
|
82
110
|
type: :development
|
83
111
|
prerelease: false
|
84
112
|
version_requirements: !ruby/object:Gem::Requirement
|
85
113
|
requirements:
|
86
|
-
- - "
|
114
|
+
- - "~>"
|
87
115
|
- !ruby/object:Gem::Version
|
88
|
-
version: '0'
|
116
|
+
version: '1.0'
|
89
117
|
- !ruby/object:Gem::Dependency
|
90
118
|
name: dry-configurable
|
91
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,6 +195,10 @@ files:
|
|
167
195
|
- lib/nazar/formatter/active_record_interface.rb
|
168
196
|
- lib/nazar/formatter/active_record_item.rb
|
169
197
|
- lib/nazar/formatter/csv_table.rb
|
198
|
+
- lib/nazar/formatter/generic.rb
|
199
|
+
- lib/nazar/formatter/sequel_collection.rb
|
200
|
+
- lib/nazar/formatter/sequel_interface.rb
|
201
|
+
- lib/nazar/formatter/sequel_item.rb
|
170
202
|
- lib/nazar/headers_formatter.rb
|
171
203
|
- lib/nazar/renderer.rb
|
172
204
|
- lib/nazar/version.rb
|
metadata.gz.sig
CHANGED
Binary file
|