redis_ui_rails 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +79 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +22 -0
  5. data/CODEOWNERS +2 -0
  6. data/CONTRIBUTING.md +40 -0
  7. data/MIT-LICENSE +22 -0
  8. data/PULL_REQUEST_TEMPLATE.md +28 -0
  9. data/README.md +14 -4
  10. data/app/assets/stylesheets/redis_ui_rails/application.css +2 -1
  11. data/app/controllers/redis_ui_rails/configs_controller.rb +1 -5
  12. data/app/controllers/redis_ui_rails/dashboard_controller.rb +1 -1
  13. data/app/controllers/redis_ui_rails/instances_controller.rb +1 -6
  14. data/app/controllers/redis_ui_rails/key_searches_controller.rb +31 -0
  15. data/app/controllers/redis_ui_rails/keys_controller.rb +9 -4
  16. data/app/models/redis_ui_rails/instance.rb +30 -0
  17. data/app/views/redis_ui_rails/configs/show.html.erb +1 -1
  18. data/app/views/redis_ui_rails/dashboard/index.html.erb +1 -1
  19. data/app/views/redis_ui_rails/instances/show.html.erb +8 -1
  20. data/app/views/redis_ui_rails/key_searches/new.html.erb +27 -0
  21. data/app/views/redis_ui_rails/key_searches/show.html.erb +36 -0
  22. data/app/views/shared/_flash.html.erb +29 -0
  23. data/app/views/shared/_instance_hero.html.erb +2 -2
  24. data/config/routes.rb +4 -0
  25. data/docs/demo-1080.gif +0 -0
  26. data/docs/demo.gif +0 -0
  27. data/lib/redis_ui_rails/config.rb +1 -1
  28. data/lib/redis_ui_rails/{redis_instance.rb → config_redis_instance.rb} +1 -1
  29. data/lib/redis_ui_rails/errors.rb +3 -0
  30. data/lib/redis_ui_rails/version.rb +1 -1
  31. data/lib/redis_ui_rails.rb +2 -1
  32. data/redis_ui_rails.gemspec +6 -4
  33. data/spec/integration/dashboard_spec.rb +5 -0
  34. data/spec/integration/instance_key_search_and_delete_spec.rb +34 -0
  35. data/spec/redis_ui_rails/{redis_instance_spec.rb → config_redis_instance_spec.rb} +1 -1
  36. data/spec/redis_ui_rails/config_spec.rb +1 -1
  37. metadata +52 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29709da81ecbe44cd27fe2df64d974f2b3007ecbb5109ebb5174166e73d923d7
4
- data.tar.gz: 3b7760666e5850d253e8c9e5db44f12ff2fd03383b3ccc331c37b9b5a0084dfe
3
+ metadata.gz: 022043af6bf4282e5d29a4983943786b3b12e77596f7f843a10f7d6363efd770
4
+ data.tar.gz: 5e35877700ad1aab0fb1292b3dcad16beba355e35cac51b995cb32d5decb8888
5
5
  SHA512:
6
- metadata.gz: 868503307acb61f6aacbbd9614a1c13c9408bfc66c27f104a5d1049f16909fedf113a43cdcccfcc7a779fc97a65f571e67d3e7d8ebfb98f4fee0a37196de5ab7
7
- data.tar.gz: 92c5d2236d3c3a34b927b976774aa2c070e36e0491f802047d775d952e789fdb0eafc15c59c09c15ecc4e682c5b23edbab50033a1169bf995588509d09546862
6
+ metadata.gz: fb2ab5ace7fbbeece6e33111aebbe4c2ed3441f378d6b1dfeca05ee9ac07df55d4e7316b9a19099ea4e86137ac4a8e9dd2420d22cc72cc87f233febfbc3d4126
7
+ data.tar.gz: 6796f8d8f1fa4a986e1bdfa47d6df6b1d25b8292e72494d434d7836918299ec8ec5c57d067e888fce7d0caa2ee3727fb7ef8ecd0b7fdc2b3a0b5cc07ca986495
@@ -0,0 +1,79 @@
1
+ version: 2.1
2
+
3
+ orbs:
4
+ browser-tools: circleci/browser-tools@1.4
5
+
6
+ # ------------------------------------------------------------------------------
7
+ # Docker images
8
+ # ------------------------------------------------------------------------------
9
+
10
+ ruby_image: &ruby_image
11
+ image: cimg/ruby:3.1.1-browsers
12
+ environment:
13
+ RACK_ENV: test
14
+ RAILS_ENV: test
15
+
16
+ # ------------------------------------------------------------------------------
17
+ # Shared job settings
18
+ # ------------------------------------------------------------------------------
19
+
20
+ defaults: &defaults
21
+ working_directory: ~/redis_ui_rails
22
+ docker:
23
+ - <<: *ruby_image
24
+
25
+ # ------------------------------------------------------------------------------
26
+ # Jobs
27
+ # ------------------------------------------------------------------------------
28
+
29
+ jobs:
30
+ test:
31
+ <<: *defaults
32
+ parallelism: 1
33
+ steps:
34
+ - checkout
35
+ - browser-tools/install-chrome
36
+ - browser-tools/install-chromedriver
37
+ - run:
38
+ name: Check Browser Install
39
+ command: |
40
+ google-chrome --version
41
+ chromedriver --version
42
+ - run:
43
+ name: Install Ruby deps
44
+ command: bundle install
45
+ - run:
46
+ name: Running tests
47
+ command: |
48
+ bundle exec rspec --profile 10 \
49
+ --format RspecJunitFormatter \
50
+ --out test_results/rspec.xml \
51
+ --format documentation \
52
+ $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
53
+ - store_test_results:
54
+ path: test_results
55
+ - store_artifacts:
56
+ path: coverage
57
+ destination: /coverage
58
+
59
+ static_analysis:
60
+ <<: *defaults
61
+ steps:
62
+ - checkout
63
+ - run:
64
+ name: Install deps
65
+ command: bundle install
66
+ - run:
67
+ name: Linting
68
+ command: bundle exec standardrb --format progress
69
+
70
+ # ------------------------------------------------------------------------------
71
+ # Workflows
72
+ # ------------------------------------------------------------------------------
73
+
74
+ workflows:
75
+ version: 2
76
+ build-and-test:
77
+ jobs:
78
+ - test
79
+ - static_analysis
data/.gitignore CHANGED
@@ -8,3 +8,4 @@ pkg
8
8
  .tool-versions
9
9
  .ruby-version
10
10
  *.gem
11
+ .DS_Store
data/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ <!-- Add unreleased changes here -->
11
+
12
+ ## [1.1.0] - 2022-09-16
13
+
14
+ - Fix `vertical-align` class to properly align text in Firefox
15
+
16
+ - Add the ability to view the value of a single key, and optionally delete that key.
17
+
18
+ ## [1.0.1] - 2022-08-04
19
+
20
+ ### Added
21
+
22
+ - Initial commit. It's ugly and simple, but it's getting the basic job done.
data/CODEOWNERS ADDED
@@ -0,0 +1,2 @@
1
+ # additional maintainers wanted
2
+ * @adsteel
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,40 @@
1
+ # Contribution Guidelines
2
+
3
+ Want to get started working on redis_ui_rails? Start here!
4
+
5
+ ## How To Contribute
6
+
7
+ * Consider creating an issue first, to solicit opinions and buy-in
8
+ * Follow the local development steps described in [the README](README.md#local-development)
9
+ * Create a topic branch: `git checkout -b my_feature`
10
+ * Commit your changes
11
+ * Add a [changelog entry](CHANGELOG.md)
12
+ * Keep up to date: `git fetch && git rebase origin/master`
13
+
14
+ Once you’re ready:
15
+
16
+ * Fork the project on GitHub
17
+ * Add your repository as a remote: `git remote add your_remote your_repo`
18
+ * Push up your branch: `git push your_remote awesome_feature`
19
+ * Create a Pull Request for the topic branch, asking for review.
20
+
21
+ If you’re looking for things to hack on, please check
22
+ [GitHub Issues](https://github.com/rubygems/rubygems.org/issues). If you’ve
23
+ found bugs or have feature ideas don’t be afraid to pipe up and ask the
24
+ [mailing list](https://groups.google.com/group/rubygems-org) or IRC channel
25
+ (`#rubygems` on `irc.freenode.net`) about them.
26
+
27
+ ## Acceptance
28
+
29
+ **Contributions WILL NOT be accepted without tests.**
30
+
31
+ If you haven't tested before, start reading up in the `spec/` directory to see
32
+ what's going on. This gem roughly rollows the [testing pyramid](https://martinfowler.com/articles/practical-test-pyramid.html) philosophy.
33
+
34
+ ## Branching
35
+
36
+ For your own development, use the topic branches. Basically, cut each
37
+ feature into its own branch and send pull requests based off those.
38
+
39
+ The `main`` branch is the primary production branch. **Always** should be fast-forwardable.
40
+
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2022, Stitch Fix
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ # Problem
2
+
3
+ <!--
4
+ Explain the problem being addressed in this PR. PRs addressing multiple
5
+ problems should be considered for splitting into multiple PRs.
6
+ -->
7
+
8
+ # Solution
9
+
10
+ <!--
11
+ Explain how this solution is solving the problem, including
12
+ any known tradeoffs or other options considered.
13
+ -->
14
+
15
+ # Checklist
16
+
17
+ <!--
18
+ Consider these before making the pull request. This section may be
19
+ included in the final pull request description or cleared.
20
+ -->
21
+
22
+ * [ ] Is there test coverage of the new code?
23
+ * [ ] Is there a CHANGELOG entry for the new changes?
24
+ * [ ] Is the PR solving a single problem?
25
+ * [ ] Does the PR description contain a problem statement?
26
+ * [ ] Does the PR description explain the solution?
27
+ * [ ] Are the commits atomic?
28
+ * [ ] Are the commit messages serving as a clear record of why?
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
+ [![stitchfix](https://circleci.com/gh/stitchfix/redis_ui_rails.svg?style=svg)](https://app.circleci.com/pipelines/github/stitchfix/redis_ui_rails)
2
+
1
3
  # RedisUiRails
2
4
 
3
- A mountable UI Rails engine for inspecting your Redis instances. The teams that will get the most value out of this engine are teams that cannot use the Rails console to inspect their production Redis instances.
5
+ A Rails engine for inspecting your Redis instances through a web UI.
6
+
7
+ Built for teams that cannot easily use more direct access methods (e.g. console) to inspect their Redis instances.
8
+
9
+ ![Animated GIF of functionality](docs/demo.gif)
4
10
 
5
11
  ## Installation
6
12
 
@@ -21,18 +27,18 @@ end
21
27
  3. Precompile your assets
22
28
 
23
29
  ```bash
24
- cd path/to/app/root
30
+ cd path/to/your/rails/app/root
25
31
  bundle exec rake assets:precompile
26
32
  ```
27
33
 
28
- 4. Configure your Redis UI engine.
34
+ 4. Configure your engine.
29
35
 
30
36
  Example:
31
37
 
32
38
  ```ruby
33
39
  # config/initializers/redis_ui_rail.rb
34
40
 
35
- # Each "instance" is a hash, with the following symbolized key structure:
41
+ # Each Redis "instance" is a hash, with the following symbolized key structure:
36
42
  # :id (required) The ID used in the URL for this instance.
37
43
  # :name (required) The name that differentiates this Redis instance from others.
38
44
  # :url (required) The URL of the redis instance.
@@ -84,3 +90,7 @@ direnv allow
84
90
  ```
85
91
  bundle exec rspec spec
86
92
  ```
93
+
94
+ ## Contributing
95
+
96
+ Want to contribute? Awesome! Check out [our guidelines](CONTRIBUTING.md).
@@ -22,5 +22,6 @@
22
22
  }
23
23
 
24
24
  .vertical-align {
25
- vertical-align: -webkit-baseline-middle
25
+ vertical-align: -webkit-baseline-middle;
26
+ vertical-align: -moz-middle-with-baseline;
26
27
  }
@@ -1,11 +1,7 @@
1
1
  module RedisUiRails
2
2
  class ConfigsController < ApplicationController
3
3
  def show
4
- @instance = RedisUiRails.config.redis_instances.detect { |obj| params[:id].to_s == obj.id.to_s }
5
-
6
- raise "Missing instance for params: #{params.inspect}. Options are: #{RedisUiRails.config.redis_instances.map(&:id)}" if @instance.nil?
7
-
8
- @redis = Redis.new(url: @instance.url(unredacted: true))
4
+ @instance = Instance.find(params[:id])
9
5
  end
10
6
  end
11
7
  end
@@ -1,7 +1,7 @@
1
1
  module RedisUiRails
2
2
  class DashboardController < ApplicationController
3
3
  def index
4
- @redis_instances = RedisUiRails.config.redis_instances
4
+ @instances = Instance.all
5
5
  end
6
6
  end
7
7
  end
@@ -1,12 +1,7 @@
1
1
  module RedisUiRails
2
2
  class InstancesController < ApplicationController
3
3
  def show
4
- @instance = RedisUiRails.config.redis_instances.detect { |obj| params[:id].to_s == obj.id.to_s }
5
-
6
- raise "Missing instance for params: #{params.inspect}. Options are: #{RedisUiRails.config.redis_instances.map(&:id)}" if @instance.nil?
7
-
8
- @redis = Redis.new(url: @instance.url(unredacted: true))
9
- @sample_keys = 50.times.map { @redis.randomkey }
4
+ @instance = Instance.find(params[:id])
10
5
  end
11
6
  end
12
7
  end
@@ -0,0 +1,31 @@
1
+ module RedisUiRails
2
+ class KeySearchesController < ApplicationController
3
+ def new
4
+ @instance = Instance.find(params[:id])
5
+ end
6
+
7
+ def create
8
+ @instance = Instance.find(params[:id])
9
+ key = params[:key]
10
+ value = @instance.get(params[:key])
11
+
12
+ if value.nil?
13
+ flash[:warning] = "No key '#{key}' found in Redis instance '#{@instance.id}'"
14
+ render :new
15
+ else
16
+ redirect_to instance_key_search_path(id: @instance.id, key: key)
17
+ end
18
+ end
19
+
20
+ def show
21
+ @instance = Instance.find(params[:id])
22
+ @key = params[:key]
23
+ @value = @instance.get(params[:key])
24
+
25
+ if @value.nil?
26
+ flash[:warning] = "No key '#{params[:key]}' found in Redis instance '#{@instance.id}'"
27
+ render :new
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,12 +1,17 @@
1
1
  module RedisUiRails
2
2
  class KeysController < ApplicationController
3
3
  def show
4
- @instance = RedisUiRails.config.redis_instances.detect { |obj| params[:id].to_s == obj.id.to_s }
4
+ @instance = Instance.find(params[:id])
5
+ @sample_keys = 50.times.map { @instance.randomkey }.uniq
6
+ end
7
+
8
+ def destroy
9
+ @instance = Instance.find(params[:id])
10
+ @instance.del(params[:key])
5
11
 
6
- raise "Missing instance for params: #{params.inspect}. Options are: #{RedisUiRails.config.redis_instances.map(&:id)}" if @instance.nil?
12
+ flash[:notice] = "Key #{params[:key]} deleted"
7
13
 
8
- @redis = Redis.new(url: @instance.url(unredacted: true))
9
- @sample_keys = 50.times.map { @redis.randomkey }.uniq
14
+ redirect_to new_instance_key_search_path(@instance.id)
10
15
  end
11
16
  end
12
17
  end
@@ -0,0 +1,30 @@
1
+ module RedisUiRails
2
+ class Instance < Struct.new(:config_redis_instance)
3
+ class << self
4
+ def find(id)
5
+ instance = all.detect { |obj| id.to_s == obj.id.to_s }
6
+
7
+ if instance.nil?
8
+ raise InstanceMissing.new(
9
+ "Instance with id '#{id}' not found. Options are: #{Instance.all.map(&:id)}"
10
+ )
11
+ end
12
+
13
+ instance
14
+ end
15
+
16
+ def all
17
+ @_all ||= RedisUiRails.config.redis_instances.map { |instance| new(instance) }
18
+ end
19
+ end
20
+
21
+ delegate :name, :id, :url, :resource_links, to: :config_redis_instance
22
+ delegate :randomkey, :info, :get, :set, :del, to: :redis
23
+
24
+ private
25
+
26
+ def redis
27
+ @_redis ||= Redis.new(url: url(unredacted: true))
28
+ end
29
+ end
30
+ end
@@ -11,7 +11,7 @@
11
11
  <section class="section">
12
12
  <h1 class="title">Server Config</h1>
13
13
  <ul>
14
- <% @redis.info.except("redis_version").sort.each do |k, v| %>
14
+ <% @instance.info.except("redis_version").sort.each do |k, v| %>
15
15
  <li><b><%= k %></b>: <%= v %></li>
16
16
  <% end %>
17
17
  </ul>
@@ -15,7 +15,7 @@
15
15
  <section class="section">
16
16
  <h1>Redis Instances</h1>
17
17
  <ul>
18
- <% @redis_instances.each do |instance| %>
18
+ <% @instances.each do |instance| %>
19
19
  <br>
20
20
  <li><%= link_to "#{instance.name} - #{instance.url}", instance_path(instance.id) %></li>
21
21
  <% end %>
@@ -17,10 +17,17 @@
17
17
  <br>
18
18
  <%= link_to instance_keys_path(@instance.id) do %>
19
19
  <div style="color: black;">
20
- <button class="button is-warning">Keys</button>
20
+ <button class="button is-warning">Key Samples</button>
21
21
  <span class="vertical-align">View a sample of keys currently stored in this Redis.</span>
22
22
  </div>
23
23
  <% end %>
24
+ <br>
25
+ <%= link_to new_instance_key_search_path(@instance.id) do %>
26
+ <div style="color: black;">
27
+ <button class="button is-link">Single Key</button>
28
+ <span class="vertical-align">Find (and delete) the value of a single key in Redis</span>
29
+ </div>
30
+ <% end %>
24
31
  </section>
25
32
 
26
33
  <section class="section">
@@ -0,0 +1,27 @@
1
+ <nav class="breadcrumb" aria-label="breadcrumbs">
2
+ <ul>
3
+ <li><%= link_to "Dashboard", root_path %></li>
4
+ <li><%= link_to "Instance Overview", instance_path(@instance.id) %></li>
5
+ <li class="is-active"><a href="#" aria-current="page">Key Search</a></li>
6
+ </ul>
7
+ </nav>
8
+
9
+ <%= render "shared/instance_hero" %>
10
+
11
+ <br>
12
+
13
+ <section class="section">
14
+ <%= render "shared/flash" %>
15
+ <br>
16
+
17
+ <%= form_with url: instance_key_searches_path(@instance.id), method: :post do |f| %>
18
+ <div class="field">
19
+ <%= f.label :key, "Search for key (exact matches only)", class: "label" %>
20
+ <%= f.text_field :key, class: "input" %>
21
+ </div>
22
+
23
+ <div class="control">
24
+ <%= f.submit 'Search', class: "button is-link" %>
25
+ </div>
26
+ <% end %>
27
+ </section>
@@ -0,0 +1,36 @@
1
+ <nav class="breadcrumb" aria-label="breadcrumbs">
2
+ <ul>
3
+ <li><%= link_to "Dashboard", root_path %></li>
4
+ <li><%= link_to "Instance Overview", instance_path(@instance.id) %></li>
5
+ <li class="is-active"><a href="#" aria-current="page">Key Search</a></li>
6
+ </ul>
7
+ </nav>
8
+
9
+ <%= render "shared/instance_hero" %>
10
+
11
+ <br>
12
+
13
+ <section class="section">
14
+ <h2 class="title is-3">Key - Value</h2>
15
+ <div>
16
+ <b class="has-text-weight-bold">Key:</b> <%= @key %>
17
+ </div>
18
+ <div>
19
+ <b class="has-text-weight-bold">Value:</b> <%= @value %>
20
+ </div>
21
+ <br>
22
+ <%= link_to new_instance_key_search_path(@instance.id) do %>
23
+ <div style="color: black;">
24
+ <button class="button is-success">New Key Search</button>
25
+ </div>
26
+ <% end %>
27
+ <br>
28
+ <%= form_with(url: destroy_instance_key_path(id: @instance.id, key: @key), \
29
+ method: :post, \
30
+ html: { onsubmit: "if(!confirm('This action cannot be undone. Delete key #{@key}?')){return false;}" }) \
31
+ do |f| %>
32
+ <div class="control">
33
+ <%= f.submit 'Delete Key', class: "button is-danger" %>
34
+ </div>
35
+ <% end %>
36
+ </section>
@@ -0,0 +1,29 @@
1
+ <% if flash.any? %>
2
+ <div>
3
+ <% flash.each do |type, msg| %>
4
+ <%
5
+ message_class = case type
6
+ when "error" then "danger"
7
+ when "notice" then "info"
8
+ else
9
+ type
10
+ end
11
+
12
+ header_text = case type
13
+ when "error" then "Error"
14
+ when "notice" then "Info"
15
+ else
16
+ type.downcase.capitalize
17
+ end
18
+ %>
19
+ <article class="message is-<%= message_class %>">
20
+ <div class="message-header">
21
+ <%= header_text %>
22
+ </div>
23
+ <div class="message-body">
24
+ <%= msg %>
25
+ </div>
26
+ </article>
27
+ <% end %>
28
+ </div>
29
+ <% end %>
@@ -1,10 +1,10 @@
1
1
  <section class="hero is-primary">
2
2
  <div class="hero-body">
3
- <h1 class="title">
3
+ <h1 class="title is-2">
4
4
  [<%= Rails.env %>] Redis instance: '<%= @instance.name %>'
5
5
  </h1>
6
6
  <p class="subtitle">
7
- redis v<%= @redis.info["redis_version"] %>
7
+ redis v<%= @instance.info["redis_version"] %>
8
8
  </p>
9
9
  <p class="subtitle">
10
10
  URL: </b><%= @instance.url %>
data/config/routes.rb CHANGED
@@ -4,5 +4,9 @@ RedisUiRails::Engine.routes.draw do
4
4
  resources :instances, only: [:show]
5
5
 
6
6
  get "instance/:id/keys", to: "keys#show", as: :instance_keys
7
+ post "instance/:id/keys/:key", to: "keys#destroy", as: :destroy_instance_key
8
+ get "instance/:id/key_search/new", to: "key_searches#new", as: :new_instance_key_search
9
+ post "instance/:id/key_searches", to: "key_searches#create", as: :instance_key_searches
10
+ get "instance/:id/key_search/:key", to: "key_searches#show", as: :instance_key_search
7
11
  get "instance/:id/config", to: "configs#show", as: :instance_config
8
12
  end
Binary file
data/docs/demo.gif ADDED
Binary file
@@ -20,7 +20,7 @@ module RedisUiRails
20
20
 
21
21
  def ingest
22
22
  self.redis_instances = Array(all_redis_instances).compact.map do |redis_instance|
23
- RedisInstance.new(redis_instance.symbolize_keys)
23
+ ConfigRedisInstance.new(redis_instance.symbolize_keys)
24
24
  end
25
25
  end
26
26
 
@@ -1,5 +1,5 @@
1
1
  module RedisUiRails
2
- class RedisInstance
2
+ class ConfigRedisInstance
3
3
  include ActiveModel::Validations
4
4
 
5
5
  REQUIRED_OPTIONS_KEYS = [:url, :name, :id].freeze
@@ -0,0 +1,3 @@
1
+ module RedisUiRails
2
+ class InstanceMissing < StandardError; end
3
+ end
@@ -1,3 +1,3 @@
1
1
  module RedisUiRails
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -6,7 +6,8 @@ require "uri"
6
6
  require "redis"
7
7
 
8
8
  require "redis_ui_rails/version"
9
- require "redis_ui_rails/redis_instance"
9
+ require "redis_ui_rails/errors"
10
+ require "redis_ui_rails/config_redis_instance"
10
11
  require "redis_ui_rails/config"
11
12
  require "redis_ui_rails/engine"
12
13
 
@@ -3,14 +3,14 @@ require "./lib/redis_ui_rails/version"
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "redis_ui_rails"
5
5
  spec.version = RedisUiRails::VERSION
6
- spec.authors = ['Stitch Fix Engineering']
7
- spec.email = ['eng@stitchfix.com']
6
+ spec.authors = ["Stitch Fix Engineering", "Adam Steel"]
7
+ spec.email = ["opensource@stitchfix.com", "adam.steel@stitchfix.com"]
8
8
  spec.homepage = "https://github.com/stitchfix/redis_ui_rails"
9
9
  spec.summary = "A drop-in Rails UI for Redis."
10
+ spec.license = "MIT"
10
11
 
11
12
  spec.files = `git ls-files`.split("\n")
12
- spec.test_files = `git ls-files -- {spec}/*`.split("\n")
13
- spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
+ spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
14
14
  spec.require_paths = ["lib"]
15
15
 
16
16
  spec.add_dependency "rails", ">= 6.1.5.1"
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.add_dependency "redis"
20
20
  spec.add_development_dependency "rspec"
21
21
  spec.add_development_dependency "pry"
22
+ spec.add_development_dependency "standardrb"
23
+ spec.add_development_dependency "rspec_junit_formatter"
22
24
 
23
25
  # For Dummy Rails app tests
24
26
  spec.add_development_dependency "capybara"
@@ -1,9 +1,14 @@
1
1
  require "feature_spec_helper"
2
2
 
3
3
  RSpec.describe "Dashboard View", type: :feature do
4
+ let(:mock_redis) { MockRedis.new }
4
5
  # Just a simple smoke test to make sure we haven't broken anything.
5
6
  # Testing details beyond this isn't worth the time given the current
6
7
  # simplicity.
8
+ before do
9
+ allow(Redis).to receive(:new).and_return(mock_redis)
10
+ end
11
+
7
12
  it "loads without error" do
8
13
  visit "redis_ui/"
9
14
 
@@ -0,0 +1,34 @@
1
+ require "feature_spec_helper"
2
+
3
+ RSpec.describe "Instance Key Search and Delete", type: :feature do
4
+ let(:mock_redis) { MockRedis.new }
5
+ let(:instance) { RedisUiRails::Instance.find("dummy") }
6
+
7
+ before do
8
+ allow(Redis).to receive(:new).and_return(mock_redis)
9
+ end
10
+
11
+ it "allows the user to search and delete by key", js: true do
12
+ instance.set("test-key", "test-value")
13
+
14
+ visit "redis_ui/instance/dummy/key_search/new"
15
+
16
+ fill_in :key, with: "test-key"
17
+
18
+ click_button "Search"
19
+
20
+ expect(page).to have_content "test-value"
21
+
22
+ click_button "Delete Key"
23
+
24
+ page.driver.browser.switch_to.alert.dismiss
25
+
26
+ expect(page).to have_content "test-value"
27
+
28
+ click_button "Delete Key"
29
+
30
+ page.driver.browser.switch_to.alert.accept
31
+
32
+ expect(page).to have_content "test-key deleted"
33
+ end
34
+ end
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe RedisUiRails::RedisInstance do
3
+ RSpec.describe RedisUiRails::ConfigRedisInstance do
4
4
  let(:options) do
5
5
  {
6
6
  id: "test",
@@ -20,7 +20,7 @@ RSpec.describe RedisUiRails::Config do
20
20
  it "slurps hash instances into instance objects" do
21
21
  config.ingest
22
22
 
23
- expect(config.redis_instances.map(&:class)).to contain_exactly(RedisUiRails::RedisInstance)
23
+ expect(config.redis_instances.map(&:class)).to contain_exactly(RedisUiRails::ConfigRedisInstance)
24
24
  end
25
25
  end
26
26
 
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_ui_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stitch Fix Engineering
8
+ - Adam Steel
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2022-08-04 00:00:00.000000000 Z
12
+ date: 2022-09-21 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rails
@@ -94,6 +95,34 @@ dependencies:
94
95
  - - ">="
95
96
  - !ruby/object:Gem::Version
96
97
  version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: standardrb
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: rspec_junit_formatter
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
97
126
  - !ruby/object:Gem::Dependency
98
127
  name: capybara
99
128
  requirement: !ruby/object:Gem::Requirement
@@ -180,16 +209,23 @@ dependencies:
180
209
  version: '0'
181
210
  description:
182
211
  email:
183
- - eng@stitchfix.com
212
+ - opensource@stitchfix.com
213
+ - adam.steel@stitchfix.com
184
214
  executables: []
185
215
  extensions: []
186
216
  extra_rdoc_files: []
187
217
  files:
218
+ - ".circleci/config.yml"
188
219
  - ".env.example"
189
220
  - ".envrc"
190
221
  - ".gitignore"
191
222
  - ".rspec.example"
223
+ - CHANGELOG.md
224
+ - CODEOWNERS
225
+ - CONTRIBUTING.md
192
226
  - Gemfile
227
+ - MIT-LICENSE
228
+ - PULL_REQUEST_TEMPLATE.md
193
229
  - README.md
194
230
  - app/assets/config/manifest.js
195
231
  - app/assets/images/redis_ui_rails/.keep
@@ -198,26 +234,35 @@ files:
198
234
  - app/controllers/redis_ui_rails/configs_controller.rb
199
235
  - app/controllers/redis_ui_rails/dashboard_controller.rb
200
236
  - app/controllers/redis_ui_rails/instances_controller.rb
237
+ - app/controllers/redis_ui_rails/key_searches_controller.rb
201
238
  - app/controllers/redis_ui_rails/keys_controller.rb
239
+ - app/models/redis_ui_rails/instance.rb
202
240
  - app/views/layouts/redis_ui_rails/application.html.erb
203
241
  - app/views/redis_ui_rails/configs/show.html.erb
204
242
  - app/views/redis_ui_rails/dashboard/index.html.erb
205
243
  - app/views/redis_ui_rails/instances/show.html.erb
244
+ - app/views/redis_ui_rails/key_searches/new.html.erb
245
+ - app/views/redis_ui_rails/key_searches/show.html.erb
206
246
  - app/views/redis_ui_rails/keys/show.html.erb
247
+ - app/views/shared/_flash.html.erb
207
248
  - app/views/shared/_instance_hero.html.erb
208
249
  - config/routes.rb
250
+ - docs/demo-1080.gif
251
+ - docs/demo.gif
209
252
  - lib/redis_ui_rails.rb
210
253
  - lib/redis_ui_rails/config.rb
254
+ - lib/redis_ui_rails/config_redis_instance.rb
211
255
  - lib/redis_ui_rails/engine.rb
212
- - lib/redis_ui_rails/redis_instance.rb
256
+ - lib/redis_ui_rails/errors.rb
213
257
  - lib/redis_ui_rails/version.rb
214
258
  - redis_ui_rails.gemspec
215
259
  - spec/feature_spec_helper.rb
216
260
  - spec/integration/dashboard_spec.rb
217
261
  - spec/integration/instance_config_spec.rb
262
+ - spec/integration/instance_key_search_and_delete_spec.rb
218
263
  - spec/integration/instance_keys_spec.rb
264
+ - spec/redis_ui_rails/config_redis_instance_spec.rb
219
265
  - spec/redis_ui_rails/config_spec.rb
220
- - spec/redis_ui_rails/redis_instance_spec.rb
221
266
  - spec/redis_ui_rails_spec.rb
222
267
  - spec/spec_helper.rb
223
268
  - spec/support/dummy/app/assets/config/manifest.js
@@ -255,7 +300,8 @@ files:
255
300
  - spec/support/dummy/public/apple-touch-icon.png
256
301
  - spec/support/dummy/public/favicon.ico
257
302
  homepage: https://github.com/stitchfix/redis_ui_rails
258
- licenses: []
303
+ licenses:
304
+ - MIT
259
305
  metadata: {}
260
306
  post_install_message:
261
307
  rdoc_options: []