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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c111b062edbb87fb756c39dcdf5628c7a71459a0f5cc98b9ae69f41894271e4
4
- data.tar.gz: 7979ca6f048af4bd2d52ad55b62c630bbdffe570ec127bd761243c9ce88c6770
3
+ metadata.gz: f3ea71c523b3f82b6882bdcb11b842e53b4f2283bc95d1ab5e8c0e17e2b1c9b6
4
+ data.tar.gz: 97017a09da4032dd35b90e34cd49cf92e96473f7c1f001a8f9ffab1c93ae6d2f
5
5
  SHA512:
6
- metadata.gz: 37cb2ef5920b6ee84296494e7f2c6e1f13fb0f3b6736ada3eb983933d9fc7384521c4fecf9328978fd6f94a778218541b7a21e35b45df6e426374bdb7be03d6a
7
- data.tar.gz: 85047535269ef0c782451c7c3d1c04a63f99ee4a412a1f34e557c6b951f72d54088191a7cf324eac82866c0c327f2fdb3277a8f7d2921dd43f31fb25206f63a1
6
+ metadata.gz: cb511b109dc83d28057e6454a5d438e799cfbb0a6eb64d2f0c55ae53dd8e92c19f0c78b4a361452307e41999738972260e2b5b4b6dc347c05ddaf81e49b452bd
7
+ data.tar.gz: 5c0f4e67fea1a380606dd75bac52de072ac9851f70b844ee8ba1464c73592e49cde3f0449fcb208cdb912b938e067fce4a8af0a7d5f7076e244e6b78d2cfa336
checksums.yaml.gz.sig CHANGED
Binary file
@@ -35,4 +35,8 @@ jobs:
35
35
  ruby-version: 2.7
36
36
  bundler-cache: true
37
37
  - name: Specs
38
- run: bundle exec rspec
38
+ uses: paambaati/codeclimate-action@v2.7.5
39
+ env:
40
+ CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
41
+ with:
42
+ coverageCommand: bundle exec rspec
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
- Nazar improves defvault inspect output for console applications (supports IRB and Pry).
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
- **Nazar is under heavy development now. Expect bumpy ride or wait until the API will stabilise a bit ;)**
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
- [![asciicast](https://asciinema.org/a/436814.png)](https://asciinema.org/a/436814)
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
 
@@ -10,11 +10,11 @@ module Nazar
10
10
  def format
11
11
  case type
12
12
  when :boolean
13
- format_boolean(value)
13
+ format_boolean
14
14
  when :integer
15
- Pastel.new(enabled: Nazar.config.colors.enabled).bright_blue(value)
15
+ format_number
16
16
  else
17
- value.nil? ? format_nil : value.to_s
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(value)
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
- Pastel.new(enabled: Nazar.config.colors.enabled).dim(Nazar.config.formatter.nil)
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
@@ -13,6 +13,10 @@ module Nazar
13
13
  @klass = item.class
14
14
  end
15
15
 
16
+ def self.valid?(data)
17
+ data.is_a?(ActiveRecord::Base)
18
+ end
19
+
16
20
  def summary
17
21
  false
18
22
  end
@@ -9,6 +9,10 @@ module Nazar
9
9
  @collection = collection
10
10
  end
11
11
 
12
+ def self.valid?(data)
13
+ data.is_a?(CSV::Table)
14
+ end
15
+
12
16
  def valid?
13
17
  !!collection && !collection.empty?
14
18
  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
@@ -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) if view.supported_data?
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nazar
4
- VERSION = '0.0.5'
4
+ VERSION = '0.1.1'
5
5
  end
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 formatter_klass
30
- @formatter_klass ||= case data
31
- when boolean?
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 active_record_item?
61
- return false unless Nazar.extensions.include?(:active_record)
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 csv_table?
67
- return false unless Nazar.extensions.include?(:csv)
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 extensions
29
- @extensions ||= Set.new
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
- load_active_record! if extensions.include?(:active_record)
36
- load_csv! if extensions.include?(:csv)
38
+ load_extensions!(extensions)
39
+ enable_repl!
37
40
 
38
- enable_for_irb! if defined?(IRB)
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 load_csv!
45
- extensions << :csv
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
- load 'nazar/formatter/csv_table.rb'
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
- load 'nazar/formatter/active_record_collection.rb'
56
- load 'nazar/formatter/active_record_item.rb'
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
- ::Nazar::Renderer.new(@context.last_value).render || __original_output_value__(omit)
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 = Pry.config.print
70
- Pry.config.print = proc do |output, value, instance|
71
- output.puts Nazar::Renderer.new(value).render || @__original_pry_print.call(output, value, instance)
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 disable!
76
- return unless @enabled
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
- disable_for_irb! if defined?(IRB)
137
+ @defined_shorthand_method = true
79
138
 
80
- @enabled = false
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
- nil
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 'sqlite3'
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.0.5
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-09-23 00:00:00.000000000 Z
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