riddler 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +105 -6
  4. data/lib/riddler.rb +52 -3
  5. data/lib/riddler/configuration.rb +11 -0
  6. data/lib/riddler/context.rb +40 -2
  7. data/lib/riddler/context_builder.rb +35 -0
  8. data/lib/riddler/context_builders/faraday_builder.rb +23 -0
  9. data/lib/riddler/context_builders/user_agent.rb +34 -0
  10. data/lib/riddler/context_director.rb +67 -0
  11. data/lib/riddler/drops/hash_drop.rb +29 -0
  12. data/lib/riddler/element.rb +15 -14
  13. data/lib/riddler/elements/heading.rb +0 -1
  14. data/lib/riddler/elements/image.rb +21 -0
  15. data/lib/riddler/elements/link.rb +30 -0
  16. data/lib/riddler/elements/text.rb +17 -0
  17. data/lib/riddler/elements/variant.rb +21 -0
  18. data/lib/riddler/includeable.rb +19 -0
  19. data/lib/riddler/protobuf/content_definition.proto +51 -0
  20. data/lib/riddler/protobuf/content_definition_pb.rb +33 -0
  21. data/lib/riddler/protobuf/content_management.proto +35 -0
  22. data/lib/riddler/protobuf/content_management_pb.rb +43 -0
  23. data/lib/riddler/protobuf/content_management_services_pb.rb +27 -0
  24. data/lib/riddler/protobuf/slug.proto +61 -0
  25. data/lib/riddler/protobuf/slug_pb.rb +52 -0
  26. data/lib/riddler/step.rb +16 -16
  27. data/lib/riddler/steps/content.rb +5 -5
  28. data/lib/riddler/steps/variant.rb +23 -0
  29. data/lib/riddler/test_generator.rb +73 -0
  30. data/lib/riddler/use_cases.rb +7 -0
  31. data/lib/riddler/use_cases/admin_preview_step.rb +32 -0
  32. data/lib/riddler/use_cases/complete_interaction.rb +20 -0
  33. data/lib/riddler/use_cases/dismiss_interaction.rb +20 -0
  34. data/lib/riddler/use_cases/preview_context.rb +28 -0
  35. data/lib/riddler/use_cases/preview_step.rb +16 -5
  36. data/lib/riddler/use_cases/show_content_definition.rb +42 -0
  37. data/lib/riddler/use_cases/show_slug.rb +138 -0
  38. data/lib/riddler/version.rb +1 -1
  39. data/riddler.gemspec +12 -8
  40. metadata +100 -10
  41. data/.gitignore +0 -8
  42. data/.travis.yml +0 -7
  43. data/Gemfile +0 -6
  44. data/Gemfile.lock +0 -58
  45. data/Rakefile +0 -10
  46. data/bin/console +0 -14
  47. data/bin/setup +0 -8
@@ -0,0 +1,29 @@
1
+ module Riddler
2
+ module Drops
3
+
4
+ class HashDrop < ::Liquid::Drop
5
+ attr_reader :hash
6
+
7
+ def initialize hash
8
+ @hash = Hash[ hash.map { |k,v| [k.to_s, v] } ]
9
+ end
10
+
11
+ def []= key, value
12
+ @hash[key.to_s] = value
13
+ end
14
+
15
+ def liquid_method_missing method
16
+ @hash[method]
17
+ end
18
+
19
+ def to_hash
20
+ hash
21
+ end
22
+
23
+ def method_missing method, *_args
24
+ liquid_method_missing method.to_s
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -1,14 +1,22 @@
1
1
  module Riddler
2
-
3
2
  class Element
3
+ include ::Riddler::Includeable
4
+
4
5
  attr_reader :definition, :context
5
6
 
7
+ def self.subclasses
8
+ @@subclasses ||= []
9
+ end
10
+
11
+ def self.inherited subclass
12
+ self.subclasses << subclass
13
+ end
14
+
6
15
  def self.for definition, context
7
- # This should be "type" not "object"
8
- element_type = definition["object"]
16
+ element_type = definition["type"]
9
17
 
10
18
  # Maybe this should be a registry
11
- klass = subclasses.detect { |klass| klass.type == element_type }
19
+ klass = subclasses.detect { |k| k.type == element_type }
12
20
 
13
21
  klass.new definition, context
14
22
  end
@@ -18,20 +26,13 @@ module Riddler
18
26
  @context = context
19
27
  end
20
28
 
21
- #def id
22
- # definition["id"]
23
- #end
24
-
25
- #def type
26
- # self.class.type
27
- #end
28
-
29
29
  def to_hash
30
30
  {
31
+ content_type: "element",
31
32
  type: self.class.type,
32
- id: definition["id"]
33
+ id: definition["id"],
34
+ name: definition["name"]
33
35
  }
34
36
  end
35
37
  end
36
-
37
38
  end
@@ -14,6 +14,5 @@ module Riddler
14
14
  super.merge text: text
15
15
  end
16
16
  end
17
-
18
17
  end
19
18
  end
@@ -0,0 +1,21 @@
1
+ module Riddler
2
+ module Elements
3
+ class Image < ::Riddler::Element
4
+ def self.type
5
+ "image"
6
+ end
7
+
8
+ def src
9
+ context.render definition["src"]
10
+ end
11
+
12
+ def alt
13
+ context.render definition["alt"]
14
+ end
15
+
16
+ def to_hash
17
+ super.merge alt: alt, src: src
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module Riddler
2
+ module Elements
3
+ class Link < ::Riddler::Element
4
+ def self.type
5
+ "link"
6
+ end
7
+
8
+ def href
9
+ @href ||= context.render definition["href"]
10
+ end
11
+
12
+ def link
13
+ return href if context.variable(:interaction).nil?
14
+ "/interactions/%s/redirect?element_id=%s&url=%s" % [
15
+ context.interaction.id,
16
+ definition["id"],
17
+ href
18
+ ]
19
+ end
20
+
21
+ def text
22
+ context.render definition["text"]
23
+ end
24
+
25
+ def to_hash
26
+ super.merge text: text, href: href, link: link
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ module Riddler
2
+ module Elements
3
+ class Text < ::Riddler::Element
4
+ def self.type
5
+ "text"
6
+ end
7
+
8
+ def text
9
+ context.render definition["text"]
10
+ end
11
+
12
+ def to_hash
13
+ super.merge text: text
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Riddler
2
+ module Elements
3
+ class Varient < ::Riddler::Element
4
+ def self.type
5
+ "variant"
6
+ end
7
+
8
+ def to_hash
9
+ included_element.to_hash
10
+ end
11
+
12
+ def included_element
13
+ definition["elements"]
14
+ .map do |hash|
15
+ ::Riddler::Element.for hash, context
16
+ end
17
+ .detect(&:include?)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Riddler
2
+ module Includeable
3
+ def include?
4
+ return true unless has_include_predicate?
5
+ Predicator.evaluate include_predicate, context.to_liquid
6
+ end
7
+
8
+ def include_predicate
9
+ definition["include_predicate"]
10
+ end
11
+
12
+ private
13
+
14
+ def has_include_predicate?
15
+ definition.key? "include_predicate" and
16
+ definition["include_predicate"].to_s.strip != ""
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,51 @@
1
+ syntax = "proto3";
2
+
3
+ package riddler.protobuf;
4
+
5
+ import "google/protobuf/timestamp.proto";
6
+
7
+ /*
8
+ ContentDefinition is one of the outputs of the RiddlerAdmin app. After an admin
9
+ user has created a piece of content - it must first be approved. Once approved
10
+ it can then be published which will create the ContentDefinition in the remote
11
+ Riddler service. ContentDefinitions CAN NOT be modified. When changes are needed - a
12
+ new ContentDefinition (with a bumped version) will be created.
13
+ */
14
+ message ContentDefinition {
15
+ string id = 1;
16
+ google.protobuf.Timestamp created_at = 2;
17
+
18
+ // Type of content: STEP
19
+ ContentType content_type = 3;
20
+
21
+ // ID of the content: st_12345
22
+ string content_id = 4;
23
+
24
+ // Version of the content. Starts at 1 and increments with each new definition
25
+ int32 version = 5;
26
+
27
+ // Title of the content: User Research Prompt
28
+ string title = 6;
29
+
30
+ // Description of the version: Adds updated images
31
+ string description = 7;
32
+
33
+ // Schema version of the definition
34
+ // The format and structure of a ContentDefinition may change over time
35
+ int32 definition_schema_version = 8;
36
+
37
+ /*
38
+ The opaque definition string generated by the admin tool (contains the
39
+ structure, predicates, liquid templates, ...). This is a snapshot of models
40
+ which belong to the admin tool.
41
+ */
42
+ oneof definition {
43
+ string definition_string = 9;
44
+ }
45
+ }
46
+
47
+ enum ContentType {
48
+ UNKNOWN_CONTENT_TYPE = 0;
49
+ STEP = 1;
50
+ ELEMENT = 2;
51
+ }
@@ -0,0 +1,33 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: riddler/protobuf/content_definition.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require 'google/protobuf/timestamp_pb'
7
+ Google::Protobuf::DescriptorPool.generated_pool.build do
8
+ add_message "riddler.protobuf.ContentDefinition" do
9
+ optional :id, :string, 1
10
+ optional :created_at, :message, 2, "google.protobuf.Timestamp"
11
+ optional :content_type, :enum, 3, "riddler.protobuf.ContentType"
12
+ optional :content_id, :string, 4
13
+ optional :version, :int32, 5
14
+ optional :title, :string, 6
15
+ optional :description, :string, 7
16
+ optional :definition_schema_version, :int32, 8
17
+ oneof :definition do
18
+ optional :definition_string, :string, 9
19
+ end
20
+ end
21
+ add_enum "riddler.protobuf.ContentType" do
22
+ value :UNKNOWN_CONTENT_TYPE, 0
23
+ value :STEP, 1
24
+ value :ELEMENT, 2
25
+ end
26
+ end
27
+
28
+ module Riddler
29
+ module Protobuf
30
+ ContentDefinition = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.ContentDefinition").msgclass
31
+ ContentType = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.ContentType").enummodule
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ syntax = "proto3";
2
+
3
+ package riddler.protobuf;
4
+
5
+ import "riddler/protobuf/content_definition.proto";
6
+ import "riddler/protobuf/slug.proto";
7
+
8
+ message CreateContentDefinitionRequest {
9
+ ContentDefinition content_definition = 1;
10
+ }
11
+ message CreateContentDefinitionResponse {}
12
+
13
+ message CreateSlugRequest {
14
+ Slug slug = 1;
15
+ }
16
+ message CreateSlugResponse {}
17
+
18
+ message UpdateSlugRequest {
19
+ Slug slug = 1;
20
+ }
21
+ message UpdateSlugResponse {}
22
+
23
+ message GetSlugStatsRequest {
24
+ Slug slug = 1;
25
+ }
26
+ message GetSlugStatsResponse {
27
+ repeated SlugStats slug_stats = 1;
28
+ }
29
+
30
+ service ContentManagement {
31
+ rpc CreateContentDefinition(CreateContentDefinitionRequest) returns (CreateContentDefinitionResponse) {}
32
+ rpc CreateSlug(CreateSlugRequest) returns (CreateSlugResponse) {}
33
+ rpc UpdateSlug(UpdateSlugRequest) returns (UpdateSlugResponse) {}
34
+ rpc GetSlugStats(GetSlugStatsRequest) returns (GetSlugStatsResponse) {}
35
+ }
@@ -0,0 +1,43 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: riddler/protobuf/content_management.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require 'riddler/protobuf/content_definition_pb'
7
+ require 'riddler/protobuf/slug_pb'
8
+ Google::Protobuf::DescriptorPool.generated_pool.build do
9
+ add_message "riddler.protobuf.CreateContentDefinitionRequest" do
10
+ optional :content_definition, :message, 1, "riddler.protobuf.ContentDefinition"
11
+ end
12
+ add_message "riddler.protobuf.CreateContentDefinitionResponse" do
13
+ end
14
+ add_message "riddler.protobuf.CreateSlugRequest" do
15
+ optional :slug, :message, 1, "riddler.protobuf.Slug"
16
+ end
17
+ add_message "riddler.protobuf.CreateSlugResponse" do
18
+ end
19
+ add_message "riddler.protobuf.UpdateSlugRequest" do
20
+ optional :slug, :message, 1, "riddler.protobuf.Slug"
21
+ end
22
+ add_message "riddler.protobuf.UpdateSlugResponse" do
23
+ end
24
+ add_message "riddler.protobuf.GetSlugStatsRequest" do
25
+ optional :slug, :message, 1, "riddler.protobuf.Slug"
26
+ end
27
+ add_message "riddler.protobuf.GetSlugStatsResponse" do
28
+ repeated :slug_stats, :message, 1, "riddler.protobuf.SlugStats"
29
+ end
30
+ end
31
+
32
+ module Riddler
33
+ module Protobuf
34
+ CreateContentDefinitionRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.CreateContentDefinitionRequest").msgclass
35
+ CreateContentDefinitionResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.CreateContentDefinitionResponse").msgclass
36
+ CreateSlugRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.CreateSlugRequest").msgclass
37
+ CreateSlugResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.CreateSlugResponse").msgclass
38
+ UpdateSlugRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.UpdateSlugRequest").msgclass
39
+ UpdateSlugResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.UpdateSlugResponse").msgclass
40
+ GetSlugStatsRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.GetSlugStatsRequest").msgclass
41
+ GetSlugStatsResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("riddler.protobuf.GetSlugStatsResponse").msgclass
42
+ end
43
+ end
@@ -0,0 +1,27 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: riddler/protobuf/content_management.proto for package 'riddler.protobuf'
3
+
4
+ require 'grpc'
5
+ require 'riddler/protobuf/content_management_pb'
6
+
7
+ module Riddler
8
+ module Protobuf
9
+ module ContentManagement
10
+ class Service
11
+
12
+ include GRPC::GenericService
13
+
14
+ self.marshal_class_method = :encode
15
+ self.unmarshal_class_method = :decode
16
+ self.service_name = 'riddler.protobuf.ContentManagement'
17
+
18
+ rpc :CreateContentDefinition, CreateContentDefinitionRequest, CreateContentDefinitionResponse
19
+ rpc :CreateSlug, CreateSlugRequest, CreateSlugResponse
20
+ rpc :UpdateSlug, UpdateSlugRequest, UpdateSlugResponse
21
+ rpc :GetSlugStats, GetSlugStatsRequest, GetSlugStatsResponse
22
+ end
23
+
24
+ Stub = Service.rpc_stub_class
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,61 @@
1
+ syntax = "proto3";
2
+
3
+ package riddler.protobuf;
4
+
5
+ import "google/protobuf/timestamp.proto";
6
+
7
+ /*
8
+ Slug is one of the outputs of the RiddlerAdmin app.
9
+ It maps a URL slug to a specific ContentDefinition and allows for
10
+ control of if it is available (status) as well as a targeting predicate.
11
+ Changes to Slugs do NOT need to go through compliance approval (as they don't
12
+ allow for modification of content).
13
+ */
14
+ message Slug {
15
+ string id = 1;
16
+ google.protobuf.Timestamp created_at = 2;
17
+ google.protobuf.Timestamp updated_at = 3;
18
+
19
+ // The URL slug used to access content: user_research_prompt
20
+ string name = 4;
21
+
22
+ // LIVE or PAUSED
23
+ SlugStatus status = 5;
24
+
25
+ // ContentDefinition to be displayed
26
+ string content_definition_id = 6;
27
+
28
+ // Liquid template to define if an interaction should be reused
29
+ string interaction_identity = 7;
30
+
31
+ // Predicate to evaluate if the content should be shown
32
+ string target_predicate = 8;
33
+ }
34
+
35
+ enum SlugStatus {
36
+ UNKNOWN_SLUG_STATUS = 0;
37
+ LIVE = 1;
38
+ PAUSED = 2;
39
+ }
40
+
41
+ enum Interval {
42
+ UNKNOWN_INTERVAL = 0;
43
+ SECOND = 1;
44
+ MINUTE = 2;
45
+ HOUR = 3;
46
+ DAY = 4;
47
+ WEEK = 5;
48
+ MONTH = 6;
49
+ QUARTER = 7;
50
+ YEAR = 8;
51
+ }
52
+
53
+ message EventCount {
54
+ string event_name = 1;
55
+ int32 count = 2;
56
+ }
57
+
58
+ message SlugStats {
59
+ Interval interval = 1;
60
+ repeated EventCount event_counts = 2;
61
+ }