simple-feed 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rubocop.yml +33 -0
  3. data/.github/workflows/ruby.yml +35 -0
  4. data/.relaxed-rubocop-2.4.yml +174 -0
  5. data/.rspec +1 -1
  6. data/.rubocop.yml +42 -1149
  7. data/.rubocop_todo.yml +134 -0
  8. data/.travis.yml +15 -8
  9. data/Gemfile +2 -0
  10. data/Guardfile +3 -3
  11. data/{README.md → README.adoc} +205 -140
  12. data/Rakefile +6 -7
  13. data/bin/console +1 -0
  14. data/examples/shared/provider_example.rb +10 -3
  15. data/lib/simple-feed.rb +2 -0
  16. data/lib/simple_feed.rb +2 -0
  17. data/lib/simplefeed.rb +9 -7
  18. data/lib/simplefeed/activity/base.rb +2 -0
  19. data/lib/simplefeed/activity/multi_user.rb +8 -6
  20. data/lib/simplefeed/activity/single_user.rb +5 -4
  21. data/lib/simplefeed/dsl.rb +3 -1
  22. data/lib/simplefeed/dsl/activities.rb +4 -3
  23. data/lib/simplefeed/dsl/formatter.rb +12 -12
  24. data/lib/simplefeed/event.rb +4 -3
  25. data/lib/simplefeed/feed.rb +19 -22
  26. data/lib/simplefeed/key/template.rb +5 -9
  27. data/lib/simplefeed/key/type.rb +4 -2
  28. data/lib/simplefeed/providers.rb +24 -9
  29. data/lib/simplefeed/providers/base/provider.rb +6 -3
  30. data/lib/simplefeed/providers/hash.rb +2 -0
  31. data/lib/simplefeed/providers/hash/paginator.rb +4 -2
  32. data/lib/simplefeed/providers/hash/provider.rb +11 -21
  33. data/lib/simplefeed/providers/key.rb +20 -11
  34. data/lib/simplefeed/providers/proxy.rb +13 -12
  35. data/lib/simplefeed/providers/redis.rb +2 -0
  36. data/lib/simplefeed/providers/redis/driver.rb +23 -23
  37. data/lib/simplefeed/providers/redis/provider.rb +35 -33
  38. data/lib/simplefeed/providers/redis/stats.rb +12 -13
  39. data/lib/simplefeed/response.rb +4 -2
  40. data/lib/simplefeed/version.rb +3 -1
  41. data/simple-feed.gemspec +16 -14
  42. metadata +58 -41
data/Rakefile CHANGED
@@ -1,30 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
 
4
6
  require 'yard'
5
7
 
6
-
7
8
  def shell(*args)
8
9
  puts "running: #{args.join(' ')}"
9
10
  system(args.join(' '))
10
11
  end
11
12
 
12
13
  task :permissions do
13
- shell('rm -rf pkg/')
14
+ shell('rm -rf pkg/ tmp/ coverage/')
14
15
  shell("chmod -v o+r,g+r * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*")
15
16
  shell("find . -type d -exec chmod o+x,g+x {} \\;")
16
17
  end
17
18
 
18
- task :build => :permissions
19
-
19
+ task build: :permissions
20
20
 
21
21
  YARD::Rake::YardocTask.new(:doc) do |t|
22
22
  t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE.txt)
23
23
  t.options.unshift('--title', '"SimpleFeed — Fast and Scalable "write-time" Simple Feed for Social Networks, with a Redis-based default backend implementation."')
24
- t.after = ->() { exec('open doc/index.html') } if RUBY_PLATFORM =~ /darwin/
24
+ t.after = -> { exec('open doc/index.html') } if RUBY_PLATFORM =~ /darwin/
25
25
  end
26
26
 
27
-
28
27
  RSpec::Core::RakeTask.new(:spec)
29
28
 
30
- task :default => :spec
29
+ task default: :spec
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "bundler/setup"
4
5
  require "activity/feed"
@@ -5,9 +5,17 @@ $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
5
5
  raise ArgumentError, 'No @feed defined in the enclosing example' unless defined?(@feed)
6
6
 
7
7
  require 'simplefeed'
8
+ require 'uuid'
9
+
10
+ srand(Time.now.to_i % 100003)
11
+
12
+ @number_of_users = ARGV[0] ? ARGV[0].to_i : 2
13
+ @users = @number_of_users.times.map do |n|
14
+ n % 2 == 0 ? UUID.generate : rand(100003)
15
+ end
16
+
17
+ pp @users
8
18
 
9
- @number_of_users = ARGV[0] ? ARGV[0].to_i : 1
10
- @users = Array.new(@number_of_users) { rand(200_000_000...800_000_000) }
11
19
  @activity = @feed.activity(@users)
12
20
  @uid = @users.first
13
21
 
@@ -24,7 +32,6 @@ def p(*args)
24
32
  end
25
33
 
26
34
  with_activity(@activity) do
27
-
28
35
  header "#{@activity.feed.provider_type} provider example"
29
36
 
30
37
  wipe
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplefeed'
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplefeed'
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'hashie/extensions/symbolize_keys'
2
4
  require 'simplefeed/version'
5
+ require 'hashie'
3
6
 
4
7
  Hashie.logger = Logger.new(nil)
5
8
 
@@ -17,9 +20,7 @@ module SimpleFeed
17
20
 
18
21
  class << self
19
22
  # @return [Hash<Symbol, Feed>] the registry of the defined feeds
20
- def registry
21
- @registry
22
- end
23
+ attr_reader :registry
23
24
 
24
25
  # @param name [Symbol] feed name
25
26
  # @param options [Hash] any key-value pairs to set on the feed
@@ -27,9 +28,9 @@ module SimpleFeed
27
28
  # @return [Feed] the feed with the given name, and defined via options and a block
28
29
  def define(name, **options, &block)
29
30
  name = name.to_sym unless name.is_a?(Symbol)
30
- feed = registry[name] ? registry[name] : SimpleFeed::Feed.new(name)
31
+ feed = registry[name] || SimpleFeed::Feed.new(name)
31
32
  feed.configure(options) do
32
- block.call(feed) if block
33
+ block&.call(feed)
33
34
  end
34
35
  registry[name] = feed
35
36
  feed
@@ -50,11 +51,12 @@ module SimpleFeed
50
51
  def provider(provider_name, *args, **opts, &block)
51
52
  provider_class = SimpleFeed::Providers.registry[provider_name]
52
53
  raise ArgumentError, "No provider named #{provider_name} was found, #{SimpleFeed::Providers.registry.inspect}" unless provider_class
54
+
53
55
  provider_class.new(*args, **opts, &block)
54
56
  end
55
57
 
56
58
  # Forward all other method calls to the Provider
57
- def method_missing(name, *args, &block)
59
+ def method_missing(name, *args, **opts, &block)
58
60
  registry[name] || super
59
61
  end
60
62
  end
@@ -62,7 +64,7 @@ module SimpleFeed
62
64
  # Returns list of class attributes based on the setter methods.
63
65
  # Not fool-proof, but works in this context.
64
66
  def self.class_attributes(klass)
65
- klass.instance_methods.grep(%r{[^=!]=$}).map { |m| m.to_s.gsub(/=/, '').to_sym }
67
+ klass.instance_methods.grep(/[^=!]=$/).map { |m| m.to_s.gsub(/=/, '').to_sym }
66
68
  end
67
69
 
68
70
  # Shortcut method to symbolize hash keys, using Hashie::Extensions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SimpleFeed
2
4
  module Activity
3
5
  class Base
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
  require_relative 'base'
3
5
 
4
6
  module SimpleFeed
5
7
  module Activity
6
8
  class MultiUser < Base
7
-
8
9
  attr_reader :user_ids
9
10
 
10
11
  extend Forwardable
@@ -16,7 +17,7 @@ module SimpleFeed
16
17
  # API Examples
17
18
  # ============
18
19
  #
19
- #```ruby
20
+ # ```ruby
20
21
  # @multi = SimpleFeed.get(:feed_name).activity(User.active.map(&:id))
21
22
  #
22
23
  # @multi.store(value:, at:)
@@ -54,15 +55,15 @@ module SimpleFeed
54
55
  # # => [Response] { user_id => [Time] last_read, ... }
55
56
  #
56
57
  # @multi.total_count
57
- # # => [Response] { user_id => [Integer] total_count, ... }
58
+ # # => [Response] { user_id => [Integer, String] total_count, ... }
58
59
  #
59
60
  # @multi.unread_count
60
- # # => [Response] { user_id => [Integer] unread_count, ... }
61
+ # # => [Response] { user_id => [Integer, String] unread_count, ... }
61
62
  #
62
63
  # @multi.last_read
63
64
  # # => [Response] { user_id => [Time] last_read, ... }
64
65
  #
65
- #```
66
+ # ```
66
67
 
67
68
  SimpleFeed::Providers.define_provider_methods(self) do |instance, method, *args, **opts, &block|
68
69
  opts.merge!(user_ids: instance.user_ids)
@@ -71,8 +72,9 @@ module SimpleFeed
71
72
  opts.delete(:event)
72
73
  end
73
74
  response = instance.feed.send(method, *args, **opts, &block)
74
- yield(response) if block_given?
75
+ block&.call(response)
75
76
  raise StandardError, "Nil response from provider #{instance.feed.provider&.provider&.class}, method #{method}(#{opts})" unless response
77
+
76
78
  response
77
79
  end
78
80
 
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'base'
2
4
 
3
5
  module SimpleFeed
4
6
  module Activity
5
-
6
7
  # Lazy implementation of SingleUser based on delegating an array of
7
8
  # one user_id to +MultiUser+
8
9
 
@@ -16,7 +17,7 @@ module SimpleFeed
16
17
  yield(user_id)
17
18
  end
18
19
 
19
- #```ruby
20
+ # ```ruby
20
21
  # @activity = SimpleFeed.get(:feed_name).activity(current_user.id)
21
22
  #
22
23
  # @activity.store(value:, at:)
@@ -61,14 +62,14 @@ module SimpleFeed
61
62
  # @activity.last_read
62
63
  # # => [Time] last_read
63
64
 
64
-
65
65
  SimpleFeed::Providers.define_provider_methods(self) do |instance, method, *args, **opts, &block|
66
66
  response = instance.user_activity.send(method, *args, **opts, &block)
67
67
  unless response.has_user?(instance.user_id)
68
68
  raise StandardError, "Nil response from provider #{instance.feed.provider&.provider&.class}, method #{method}(#{opts}) — user_id #{instance.user_id}"
69
69
  end
70
+
70
71
  response = response[instance.user_id]
71
- yield(response) if block_given?
72
+ block&.call(response)
72
73
  response
73
74
  end
74
75
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'providers'
2
4
  require 'simplefeed'
3
5
  require_relative 'dsl/activities'
@@ -22,7 +24,7 @@ module SimpleFeed
22
24
  attr_accessor :debug
23
25
 
24
26
  def debug?
25
- self.debug
27
+ debug
26
28
  end
27
29
  end
28
30
 
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'formatter'
2
4
  module SimpleFeed
3
5
  module DSL
4
6
  class Activities
5
-
6
7
  include SimpleFeed::DSL::Formatter
7
8
 
8
9
  attr_accessor :activity, :feed
@@ -14,7 +15,7 @@ module SimpleFeed
14
15
  self.class.instance_eval do
15
16
  attr_accessor key
16
17
  end
17
- self.send("#{key}=".to_sym, value)
18
+ send("#{key}=".to_sym, value)
18
19
  end
19
20
  end
20
21
 
@@ -60,7 +61,7 @@ module SimpleFeed
60
61
 
61
62
  def print_debug_info(method, **opts)
62
63
  brackets = opts.empty? ? ['', ''] : %w{( )}
63
- printf "\n#{self.feed.name.to_s.blue}.#{method.to_s.cyan.bold}#{brackets[0]}#{opts.to_s.gsub(/[{}]/, '').blue}#{brackets[1]} \n" if SimpleFeed::DSL.debug?
64
+ printf "\n#{feed.name.to_s.blue}.#{method.to_s.cyan.bold}#{brackets[0]}#{opts.to_s.gsub(/[{}]/, '').blue}#{brackets[1]} \n" if SimpleFeed::DSL.debug?
64
65
  response = yield if block_given?
65
66
  puts response.inspect.yellow if SimpleFeed::DSL.debug?
66
67
  response
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplefeed/dsl'
2
4
  require 'simplefeed/activity/single_user'
3
5
  require 'simplefeed/activity/multi_user'
@@ -13,9 +15,9 @@ module SimpleFeed
13
15
 
14
16
  def color_dump(this_activity = activity)
15
17
  this_activity = if this_activity.is_a?(SimpleFeed::Activity::SingleUser)
16
- this_activity.feed.activity([this_activity.user_id])
17
- else
18
- this_activity
18
+ this_activity.feed.activity([this_activity.user_id])
19
+ else
20
+ this_activity
19
21
  end
20
22
  _puts
21
23
 
@@ -32,8 +34,7 @@ module SimpleFeed
32
34
 
33
35
  [['User ID', user_id, "\n"],
34
36
  ['Activities', sprintf('%d total, %d unread', total_count[user_id], unread_count[user_id]), "\n"],
35
- ['Last Read', this_last_read ? Time.at(this_last_read) : 'N/A'],
36
- ].each do |field, value, *args|
37
+ ['Last Read', this_last_read ? Time.at(this_last_read) : 'N/A'],].each do |field, value, *args|
37
38
  field(field, value, *args)
38
39
  end
39
40
 
@@ -42,7 +43,6 @@ module SimpleFeed
42
43
  this_events = fetch[user_id]
43
44
  this_events_count = this_events.size
44
45
  this_events.each_with_index do |_event, _index|
45
-
46
46
  if this_last_event_at.nil? && _event.at < this_last_read
47
47
  print_last_read_separator(this_last_read)
48
48
  elsif this_last_event_at && this_last_read < this_last_event_at && this_last_read > _event.at
@@ -86,12 +86,12 @@ module SimpleFeed
86
86
 
87
87
  def field_value(value)
88
88
  case value
89
- when Numeric
90
- sprintf '%-20d', value
91
- when Time
92
- sprintf '%-30s', value.strftime(TIME_FORMAT)
93
- else
94
- sprintf '%-20s', value.to_s
89
+ when Numeric
90
+ sprintf '%-20d', value
91
+ when Time
92
+ sprintf '%-30s', value.strftime(TIME_FORMAT)
93
+ else
94
+ sprintf '%-20s', value.to_s
95
95
  end
96
96
  end
97
97
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module SimpleFeed
@@ -6,7 +8,7 @@ module SimpleFeed
6
8
  include Comparable
7
9
 
8
10
  def initialize(*args, value: nil, at: Time.now)
9
- if args && args.size > 0
11
+ if args && !args.empty?
10
12
  self.value = args[0]
11
13
  self.at = args[1]
12
14
  end
@@ -44,7 +46,7 @@ module SimpleFeed
44
46
  self.value.hash
45
47
  end
46
48
 
47
- def to_json
49
+ def to_json(*_args)
48
50
  to_h.to_json
49
51
  end
50
52
 
@@ -75,6 +77,5 @@ module SimpleFeed
75
77
  raise ArgumentError, "Required arguments missing, value=[#{value}], at=[#{at}]"
76
78
  end
77
79
  end
78
-
79
80
  end
80
81
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'providers'
2
4
  require_relative 'activity/base'
3
5
  require 'simplefeed/key/template'
4
6
 
5
7
  module SimpleFeed
6
8
  class Feed
7
-
8
9
  attr_accessor :per_page, :max_size, :batch_size, :meta, :namespace
9
10
  attr_reader :name
10
11
 
@@ -18,14 +19,10 @@ module SimpleFeed
18
19
  # set the defaults if not passed in
19
20
  @meta = {}
20
21
  @namespace = nil
21
- @per_page ||= 50
22
- @max_size ||= 1000
23
- @batch_size ||= 10
24
- @proxy = nil
25
- end
26
-
27
- def key_template
28
- SimpleFeed::Key::Template.new(namespace)
22
+ @per_page ||= 50
23
+ @max_size ||= 1000
24
+ @batch_size ||= 10
25
+ @proxy = nil
29
26
  end
30
27
 
31
28
  def provider=(definition)
@@ -38,10 +35,6 @@ module SimpleFeed
38
35
  @proxy
39
36
  end
40
37
 
41
- def key(user_id)
42
- SimpleFeed::Providers::Key.new(user_id, key_template)
43
- end
44
-
45
38
  def provider_type
46
39
  SimpleFeed::Providers::Base::Provider.class_to_registry(@proxy.provider.class)
47
40
  end
@@ -61,28 +54,32 @@ module SimpleFeed
61
54
  user_activity(one_or_more_users)
62
55
  end
63
56
 
64
- # @deprecated Please use {#activity} instead
65
- def for(*args)
66
- STDERR.puts 'WARNING: method #for is deprecated, please use #activity'
67
- activity(*args)
68
- end
69
-
70
57
  def configure(hash = {})
71
58
  SimpleFeed.symbolize!(hash)
72
59
  class_attrs.each do |attr|
73
- self.send("#{attr}=", hash[attr]) if hash.key?(attr)
60
+ send("#{attr}=", hash[attr]) if hash.key?(attr)
74
61
  end
75
62
  yield self if block_given?
76
63
  end
77
64
 
65
+ def key(user_id)
66
+ SimpleFeed::Providers::Key.new(user_id, key_template)
67
+ end
68
+
78
69
  def eql?(other)
79
70
  other.class == self.class &&
80
- %i(per_page max_size name).all? { |m| self.send(m).equal?(other.send(m)) } &&
81
- self.provider.provider.class == other.provider.provider.class
71
+ %i(per_page max_size name).all? { |m| send(m).equal?(other.send(m)) } &&
72
+ provider.provider.class == other.provider.provider.class
82
73
  end
83
74
 
84
75
  def class_attrs
85
76
  SimpleFeed.class_attributes(self.class)
86
77
  end
78
+
79
+ private
80
+
81
+ def key_template
82
+ SimpleFeed::Key::Template.new(namespace)
83
+ end
87
84
  end
88
85
  end
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base62-rb'
2
4
  require 'hashie/mash'
3
5
 
4
6
  module SimpleFeed
5
7
  module Key
6
-
7
8
  class TextTemplate < Struct.new(:text)
8
9
  def render(params = {})
9
- output = self.text.dup
10
+ output = text.dup
10
11
  params.each_pair do |key, value|
11
- output.gsub!(%r[{{\s*#{key}\s*}}], value.to_s)
12
+ output.gsub!(/{{\s*#{key}\s*}}/, value.to_s)
12
13
  end
13
14
  output
14
15
  end
@@ -21,8 +22,7 @@ module SimpleFeed
21
22
 
22
23
  def initialize(namespace,
23
24
  key_types = DEFAULT_TYPES,
24
- text_template = DEFAULT_TEXT_TEMPLATE
25
- )
25
+ text_template = DEFAULT_TEXT_TEMPLATE)
26
26
 
27
27
  self.namespace = namespace
28
28
  self.key_types = key_types
@@ -43,10 +43,6 @@ module SimpleFeed
43
43
  def key_names
44
44
  key_types.map(&:name).map(&:to_s).sort
45
45
  end
46
-
47
- private
48
-
49
46
  end
50
47
  end
51
48
  end
52
-