redis_snippets 0.0.10 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -2
  3. data/.rspec +2 -0
  4. data/.travis.yml +19 -0
  5. data/Gemfile +12 -0
  6. data/README.md +84 -18
  7. data/Rakefile +5 -0
  8. data/app/controllers/redis_snippets/snippets_controller.rb +5 -6
  9. data/app/helpers/redis_snippets/snippets_helper.rb +5 -23
  10. data/app/presenters/snippet_presenter.rb +67 -0
  11. data/app/{models/redis_snippets/snippets.rb → services/snippet_store_service.rb} +9 -1
  12. data/app/views/redis_snippets/snippets/show.html.erb +11 -15
  13. data/config/routes.rb +1 -1
  14. data/lib/redis_snippets/engine.rb +3 -1
  15. data/lib/redis_snippets/redis.rb +10 -5
  16. data/lib/redis_snippets/{help.rb → util.rb} +2 -2
  17. data/lib/redis_snippets/version.rb +1 -1
  18. data/lib/redis_snippets.rb +4 -2
  19. data/redis_snippets.gemspec +5 -4
  20. data/spec/app/helpers/redis_snippets/snippets_helper_spec.rb +38 -0
  21. data/spec/app/presenters/snippet_presenter_spec.rb +53 -0
  22. data/spec/app/presenters/snippet_presenter_transform_spec.rb +45 -0
  23. data/spec/app/services/snippet_store_service_spec.rb +44 -0
  24. data/spec/dummy/.ruby-version +1 -0
  25. data/spec/dummy/Rakefile +6 -0
  26. data/spec/dummy/app/assets/config/manifest.js +3 -0
  27. data/spec/dummy/app/assets/images/.keep +0 -0
  28. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  29. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  30. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/spec/dummy/bin/rails +4 -0
  32. data/spec/dummy/bin/rake +4 -0
  33. data/spec/dummy/bin/setup +33 -0
  34. data/spec/dummy/config/application.rb +29 -0
  35. data/spec/dummy/config/boot.rb +5 -0
  36. data/spec/dummy/config/environment.rb +5 -0
  37. data/spec/dummy/config/environments/development.rb +62 -0
  38. data/spec/dummy/config/environments/test.rb +48 -0
  39. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  40. data/spec/dummy/config/initializers/assets.rb +12 -0
  41. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  42. data/spec/dummy/config/initializers/content_security_policy.rb +28 -0
  43. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  44. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  45. data/spec/dummy/config/initializers/inflections.rb +16 -0
  46. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  47. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/spec/dummy/config/puma.rb +38 -0
  49. data/spec/dummy/config/routes.rb +3 -0
  50. data/spec/dummy/config.ru +5 -0
  51. data/spec/dummy/lib/assets/.keep +0 -0
  52. data/spec/dummy/log/.keep +0 -0
  53. data/spec/dummy/tmp/.keep +0 -0
  54. data/spec/dummy/tmp/development_secret.txt +1 -0
  55. data/spec/rails_helper.rb +54 -0
  56. data/spec/spec_helper.rb +13 -0
  57. data/spec/support/simplecov_setup.rb +5 -0
  58. metadata +105 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d57ab380b6653a5a2bbadfd96bcb3f5c2b1033b0
4
- data.tar.gz: c6ef4474551730d558e675fa49fde37e5f20219a
2
+ SHA256:
3
+ metadata.gz: 1157b175b0ce0c3c72be376383f9da2d522999f69304c093cd3ddbc22eb0d25d
4
+ data.tar.gz: 7673c2ffe8fd7b0134847e1de912dd94aadf900a267c937625e3ace993f106ee
5
5
  SHA512:
6
- metadata.gz: c81fa957b20f7e9d1b7cdf0164bae965e85cea2a51f6ad1c65d3ba6f17d24a4e0119cd8f5bd9889dbc9e54c12df67735cd43eac6ab2f84897837925bf90a000a
7
- data.tar.gz: f5ed406436c21e5969129f901fcdea444f89f68b1dd10a17576a60798c7bab9790f542692e7b47823ff4487c49e272bd3614acb02ef5dae6da82a84832b385c0
6
+ metadata.gz: fc847d478f9c40aef9fe2ecb067eee24c700d23b1053bcb09280db46c5025b09a94e6363ecdb2f0d70e567a606b75cb53d0771e16844b3a934b6eb815c4bb44f
7
+ data.tar.gz: fbfc1e84fc0c9794221880574abde61e7d3e2c11720c0c92062be5592c0f15d599f428b556abe777156fc2662790b4386c60cd553720d9567a3664337761602d
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
- *.tmproj
2
- pkg
3
1
  .bundle
2
+ pkg
3
+ spec/dummy/log
4
+ Gemfile.lock
5
+ coverage
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+ cache: bundler
3
+ sudo: false
4
+ env:
5
+ global:
6
+ - CC_TEST_REPORTER_ID=aa59e066b7cd7b5477aecc5c17004d78d35012420e791d23b17c0ea705ef9cd7
7
+ before_script:
8
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
9
+ - chmod +x ./cc-test-reporter
10
+ - ./cc-test-reporter before-build
11
+ before_install:
12
+ - gem update --system
13
+ - gem install bundler --version 2.0.2
14
+ rvm:
15
+ - 2.6.5
16
+ script:
17
+ - bundle exec rake
18
+ after_script:
19
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ group :test, :development do
5
+ gem "rails", ">= 6.0"
6
+ gem "rspec-rails", ">= 3.9.0"
7
+ end
8
+
9
+ group :test do
10
+ gem "mock_redis"
11
+ gem "simplecov"
12
+ end
data/README.md CHANGED
@@ -1,20 +1,48 @@
1
1
  # Redis Snippets
2
2
 
3
+ [![Version](https://img.shields.io/gem/v/redis_snippets.svg?style=flat-square)](https://rubygems.org/gems/redis_snippets)
4
+ [![Build](https://img.shields.io/travis/wulffeld/redis_snippets.svg?style=flat-square)](https://travis-ci.org/wulffeld/redis_snippets)
5
+ [![Maintainability](https://img.shields.io/codeclimate/maintainability/wulffeld/redis_snippets?style=flat-square)](https://codeclimate.com/github/wulffeld/redis_snippets)
6
+ [![Coverage](https://img.shields.io/codeclimate/coverage/wulffeld/redis_snippets?style=flat-square)](https://codeclimate.com/github/wulffeld/redis_snippets)
7
+
3
8
  ## Background
4
9
 
5
- Easily store snippets of content in Redis.
10
+ Easily store snippets of content in Redis. Inspired by plugin for Wordpress
11
+ named Snippets.
12
+
13
+ With redis_snippets you could for instance store AdSense code snippets or
14
+ other HTML/JS content.
15
+
16
+ ## Requirements
17
+
18
+ Gems:
19
+
20
+ * rails 5.x or higher
21
+ * redis
22
+ * redis-namespace
23
+
24
+ ## Installation
25
+
26
+ Add to your Rails projects Gemfile and bundle install:
27
+
28
+ ```
29
+ gem "redis_snippets"
30
+ ```
6
31
 
7
- ## How
32
+ ## Usage
8
33
 
9
- It's a Rails engine so add redis-snippets to your Gemfile and put this in an initializer:
34
+ It's a Rails engine so add redis-snippets to your Gemfile and put this in an
35
+ initializer:
10
36
 
11
37
  ``` ruby
12
- App::Application.config.redis_snippets = {
13
- :connection => ::Redis::Namespace.new("my_namespace", :redis => ::Redis.new),
14
- :keys => [:key1, :key2]
38
+ Rails.application.config.redis_snippets = {
39
+ connection: ::Redis::Namespace.new("my_namespace", redis: ::Redis.new),
40
+ keys: [:key1, :key2]
15
41
  }
16
42
  ```
17
43
 
44
+ The names of the keys are entirely up to you.
45
+
18
46
  You should then be able to access /admin/snippets/.
19
47
 
20
48
  In your views use helper snippet().
@@ -28,20 +56,63 @@ In your views use helper snippet().
28
56
  One snippet area can include multiple snippets if you separate them with a
29
57
 
30
58
  ```
31
- [snippet]
59
+ [section]
32
60
  ```
33
61
 
34
- The snippet helper will randomly select the snippet. This is convenient for ad delivery for example.
62
+ The snippet helper will randomly select the snippet. This is convenient for ad
63
+ delivery or perhaps A/B testing 🤷‍♂.
35
64
 
36
65
  ## Multi Site
37
66
 
38
- If you're using one app to serve multiple sites a little more configuration is necessary.
67
+ If you're using one app to serve multiple sites a little more configuration is
68
+ necessary.
39
69
 
40
70
  ``` ruby
41
- App::Application.config.redis_snippets = {
42
- :connection => ::Redis::Namespace.new("my_namespace", :redis => ::Redis.new),
43
- :multi_site => true,
44
- :keys => [:key1, :key2]
71
+ Rails.application.config.redis_snippets = {
72
+ connection: ::Redis::Namespace.new("my_namespace", redis: ::Redis.new),
73
+ multi_site: true,
74
+ keys: [:key1, :key2],
75
+ transform: "MySnippetTransform"
76
+ }
77
+ ```
78
+
79
+ ## Transforming Snippets
80
+
81
+ Sometimes you might want to transform snippets. This happens after
82
+ randomization so you get the actual snippet content to be rendered passed to
83
+ your transform class.
84
+
85
+ The transform class must respond to .transforms? and #transform. Example:
86
+
87
+ ``` ruby
88
+ class MySnippetTransform
89
+ def initialize(content:, key:)
90
+ @content = content
91
+ @key = key
92
+ end
93
+
94
+ # Must return content.
95
+ def transform
96
+ @content.gsub("Amazon", "Etsy")
97
+ end
98
+
99
+ class << self
100
+ def transforms?(key:)
101
+ key == :advert_header
102
+ end
103
+ end
104
+ end
105
+ ```
106
+
107
+ I personally use this to insert special CSS code for AdSense. This saves me
108
+ from having to do this manually whenever I update it or add it.
109
+
110
+ ``` ruby
111
+ Rails.application.config.redis_snippets = {
112
+ connection: ::Redis::Namespace.new("my_namespace", redis: ::Redis.new),
113
+ multi_site: true,
114
+ keys: [:key1, :key2],
115
+ transform: "MySnippetTransform"
45
116
  }
46
117
  ```
47
118
 
@@ -53,8 +124,3 @@ def redis_snippet_site_key
53
124
  request.host
54
125
  end
55
126
  ```
56
-
57
- ## Requirements
58
-
59
- * redis
60
- * redis-namespace
data/Rakefile CHANGED
@@ -1 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -1,7 +1,7 @@
1
1
  class RedisSnippets::SnippetsController < ApplicationController
2
- include RedisSnippets::Help
3
-
4
- before_filter :redis_snippets_authenticate_admin_user!
2
+ include RedisSnippets::Util
3
+
4
+ before_action :redis_snippets_authenticate_admin_user!
5
5
 
6
6
  layout 'admin'
7
7
 
@@ -10,10 +10,9 @@ class RedisSnippets::SnippetsController < ApplicationController
10
10
 
11
11
  def update
12
12
  params[:snippets].each do |key, content|
13
- raise "#{key} not in the specified keys." unless RedisSnippets::Engine.config.redis_snippets[:keys].include?(key.to_sym)
14
- RedisSnippets::Snippets.update(snippet_key(key), params[:snippets][key])
13
+ SnippetStoreService.update(snippet_key(key), params[:snippets][key])
15
14
  end
16
-
15
+
17
16
  flash[:notice] = 'Snippets updated.'
18
17
  redirect_to redis_snippets.snippets_path
19
18
  end
@@ -1,32 +1,14 @@
1
1
  module RedisSnippets
2
2
  module SnippetsHelper
3
- include RedisSnippets::Help
4
-
5
- def snippet_content(snippet_name)
6
- RedisSnippets::Snippets.send(snippet_key(snippet_name))
7
- end
3
+ include RedisSnippets::Util
8
4
 
9
5
  # Return true if snippet has content.
10
- def snippet_has_content?(snippet_name)
11
- !snippet_content(snippet_name).blank?
12
- end
13
-
14
- def snippet(snippet_name, classes=nil)
15
- return '' if controller.status == 404
16
- snippet = snippet_content(snippet_name)
17
- return '' if snippet.blank?
18
- snippets = snippet.split("[section]")
19
- build_snippet(snippets[rand(snippets.length)], snippet_class_list(snippet_name, classes))
20
- end
21
-
22
- def snippet_class_list(snippet_name, classes)
23
- ['snippet', classes || snippet_name.to_s].compact.join(' ').html_safe
6
+ def snippet_has_content?(key)
7
+ !SnippetStoreService.send(snippet_key(key)).blank?
24
8
  end
25
9
 
26
- def build_snippet(content, classes)
27
- content_tag(:div,
28
- content.html_safe,
29
- :class => classes)
10
+ def snippet(key, classes = nil)
11
+ SnippetPresenter.new(view: self, key: key, classes: classes).call
30
12
  end
31
13
  end
32
14
  end
@@ -0,0 +1,67 @@
1
+
2
+ class SnippetPresenter
3
+ include RedisSnippets::Util
4
+
5
+ SECTION_DELIMITER = "[section]"
6
+
7
+ delegate :random_snippet, to: "self.class"
8
+
9
+ def initialize(view:, key:, classes: nil)
10
+ @view = view
11
+ @key = key
12
+ @classes = classes
13
+ end
14
+
15
+ def call
16
+ prepare_snippet
17
+ render
18
+ end
19
+
20
+ protected
21
+
22
+ def prepare_snippet
23
+ @snippet = ""
24
+
25
+ return unless content = SnippetStoreService.send(snippet_key(@key))
26
+
27
+ snippets = content.split("#{SECTION_DELIMITER}")
28
+ @snippet = random_snippet(content)
29
+
30
+ if transform_class && transform_class.transforms?(key: @key)
31
+ @snippet = transform_class.new(content: @snippet, key: @key).transform
32
+ end
33
+ end
34
+
35
+ def snippet_class_list
36
+ [
37
+ "snippet",
38
+ @key.to_s,
39
+ *@classes
40
+ ].reject(&:blank?).join(" ").html_safe
41
+ end
42
+
43
+ def render
44
+ # If snippet is empty we avoid wrapping it in the div.
45
+ if @snippet.blank?
46
+ ""
47
+ else
48
+ @view.content_tag(:div, @snippet.html_safe, class: snippet_class_list)
49
+ end
50
+ end
51
+
52
+ def transform_class
53
+ @klass ||=
54
+ if RedisSnippets::Engine.config.redis_snippets[:transform].is_a?(Proc)
55
+ klass = RedisSnippets::Engine.config.redis_snippets[:transform].call and klass.constantize
56
+ else
57
+ RedisSnippets::Engine.config.redis_snippets[:transform] and RedisSnippets::Engine.config.redis_snippets[:transform].constantize
58
+ end
59
+ end
60
+
61
+ class << self
62
+ def random_snippet(content)
63
+ snippets = content.split("#{SECTION_DELIMITER}").map { |section| section.gsub(/^\n/, "") }
64
+ snippets[rand(snippets.length)]
65
+ end
66
+ end
67
+ end
@@ -1,10 +1,12 @@
1
- class RedisSnippets::Snippets
1
+ class SnippetStoreService
2
2
  class << self
3
3
  def update(key, content)
4
+ ensure_key_is_defined!(key)
4
5
  RedisSnippets::Redis.set("snippets:#{key}", content)
5
6
  end
6
7
 
7
8
  def del(key)
9
+ ensure_key_is_defined!(key)
8
10
  RedisSnippets::Redis.del("snippets:#{key}")
9
11
  end
10
12
 
@@ -12,5 +14,11 @@ class RedisSnippets::Snippets
12
14
  def method_missing(method, *args)
13
15
  RedisSnippets::Redis.get("snippets:#{method}")
14
16
  end
17
+
18
+ protected
19
+
20
+ def ensure_key_is_defined!(key)
21
+ raise UndefinedSnippetsKey.new("#{key} not in the specified keys.") unless RedisSnippets::Engine.config.redis_snippets[:keys].include?(key.to_sym)
22
+ end
15
23
  end
16
24
  end
@@ -1,23 +1,19 @@
1
- <div class="redis_snippets">
2
- <h1>Snippets</h1>
1
+ <div class="redis-snippets">
2
+ <h1 class="h1">Snippets</h1>
3
3
 
4
- <%= form_tag '', method: :put, class: "form-redis_snippets" do |f| %>
5
- <fieldset class="form-redis_snippets-inputs">
6
- <ol>
4
+ <%= form_tag "", method: :put, class: "redis-snippets__form" do |f| %>
5
+ <fieldset class="redis-snippets__fieldset">
6
+ <ol class="redis-snippets__list">
7
7
  <% RedisSnippets::Engine.config.redis_snippets[:keys].each do |key| %>
8
- <li class="form-redis_snippets-inputs-text form-redis_snippets-inputs-input form-redis_snippets-inputs-optional">
9
- <%= label_tag key.to_s, key.to_s, class: "form-redis_snippets-label" %>
10
- <%= text_area_tag "snippets[#{key}]", RedisSnippets::Snippets.send(snippet_key(key)), cols: 120, rows: 10 %>
8
+ <li class="redis-snippets__snippet">
9
+ <%= label_tag key.to_s, key.to_s, class: "redis-snippets__snippet-label" %>
10
+ <%= text_area_tag "snippets[#{key}]", SnippetStoreService.send(snippet_key(key)), cols: 120, rows: 10 %>
11
11
  </li>
12
12
  <% end -%>
13
13
  </ol>
14
14
  </fieldset>
15
- <fieldset class="form-redis_snippets-inputs-actions">
16
- <ol>
17
- <li class="form-redis_snippets-inputs-action form-redis_snippets-inputs-button_action">
18
- <%= button_tag 'Submit' %>
19
- </li>
20
- </ol>
21
- </field>
15
+ <fieldset class="redis-snippets__actions">
16
+ <%= button_tag "Submit", class: "redis-snippets__submit" %>
17
+ </fieldset>
22
18
  <% end -%>
23
19
  </div>
data/config/routes.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  RedisSnippets::Engine.routes.draw do
2
- resource :snippets, controller: 'snippets', only: [:show, :update]
2
+ resource :snippets, controller: 'redis_snippets/snippets', only: [:show, :update]
3
3
  end
@@ -1,5 +1,7 @@
1
1
  module RedisSnippets
2
2
  class Engine < ::Rails::Engine
3
- isolate_namespace RedisSnippets
3
+ config.generators do |g|
4
+ g.test_framework :rspec
5
+ end
4
6
  end
5
7
  end
@@ -1,17 +1,22 @@
1
1
  module RedisSnippets
2
2
  class Redis
3
3
  class << self
4
- # Can't do method_missing on get/set as they're defined somewhere by Ruby.
5
4
  def get(key)
6
- RedisSnippets::Engine.config.redis_snippets[:connection].get(key)
5
+ connection.get(key)
7
6
  end
8
7
 
9
8
  def set(key, value)
10
- RedisSnippets::Engine.config.redis_snippets[:connection].set(key, value)
9
+ connection.set(key, value)
11
10
  end
12
11
 
13
- def method_missing(method, *args)
14
- RedisSnippets::Engine.config.redis_snippets[:connection].send(method, *args)
12
+ def del(key)
13
+ connection.del(key)
14
+ end
15
+
16
+ protected
17
+
18
+ def connection
19
+ RedisSnippets::Engine.config.redis_snippets[:connection]
15
20
  end
16
21
  end
17
22
  end
@@ -1,6 +1,6 @@
1
1
  module RedisSnippets
2
- module Help
3
- # If multi_site => true the symbol returned will have the key returned with a prefix.
2
+ module Util
3
+ # If multi_site is true the symbol returned will have the key returned with a prefix.
4
4
  # This prefix is defined in your application using the redis_snippet_site_key method.
5
5
  # redis_snippet_site_key should simply return a unique string per site. For instance
6
6
  # it could be the domain of the site.