nazar 0.0.5 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 [](https://github.com/krzyzak/nazar/actions) [](https://codeclimate.com/github/krzyzak/nazar)
|
|
1
|
+
# Nazar [](https://github.com/krzyzak/nazar/actions) [](https://badge.fury.io/rb/nazar) [](https://codeclimate.com/github/krzyzak/nazar) [](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
|