Module: Testimonials

Defined in:
lib/testimonials.rb,
lib/testimonials/seeds.rb,
lib/testimonials/engine.rb,
lib/testimonials/widget.rb,
lib/testimonials/version.rb,
lib/testimonials/demo_video.rb,
lib/testimonials/configuration.rb,
lib/testimonials/prompt_helper.rb,
lib/testimonials/has_testimonials.rb,
app/models/testimonials/testimonial.rb,
app/models/testimonials/nps_response.rb,
app/models/testimonials/prompt_event.rb,
app/helpers/testimonials/widget_helper.rb,
app/models/testimonials/application_record.rb,
app/controllers/testimonials/nps_controller.rb,
app/controllers/testimonials/media_controller.rb,
lib/generators/testimonials/migration_helpers.rb,
lib/generators/testimonials/nps/nps_generator.rb,
app/controllers/testimonials/events_controller.rb,
app/controllers/testimonials/widgets_controller.rb,
app/controllers/testimonials/api/base_controller.rb,
app/controllers/testimonials/api/stats_controller.rb,
app/controllers/testimonials/dashboard_controller.rb,
app/controllers/testimonials/collection_controller.rb,
app/controllers/testimonials/application_controller.rb,
app/controllers/testimonials/submissions_controller.rb,
lib/generators/testimonials/tenant/tenant_generator.rb,
app/controllers/testimonials/testimonials_controller.rb,
app/controllers/concerns/testimonials/request_context.rb,
app/controllers/testimonials/nps_responses_controller.rb,
lib/generators/testimonials/install/install_generator.rb,
app/controllers/testimonials/api/testimonials_controller.rb,
lib/generators/testimonials/prompt_events/prompt_events_generator.rb

Overview

Testimonials, reviews and NPS for Rails. An iOS-style in-app widget collects star ratings and testimonials (text or video) at moments your code chooses; a public page collects them from shareable links; NPS promoters are routed straight into the testimonial ask. Everything lands in your own database with a minimal dashboard to approve, feature, and pick best lines — and a read API to render approved testimonials wherever you like.

Defined Under Namespace

Modules: Api, DemoVideo, Generators, HasTestimonials, PromptHelper, RequestContext, Seeds, Widget, WidgetHelper Classes: ApplicationController, ApplicationRecord, CollectionController, Configuration, DashboardController, Engine, EventsController, MediaController, NpsController, NpsResponse, NpsResponsesController, PromptEvent, SubmissionsController, Testimonial, TestimonialsController, WidgetsController

Constant Summary collapse

VERSION =
'0.8.1'

Class Method Summary collapse

Class Method Details

.admin?(request) ⇒ Boolean

Can this request browse and triage submissions? Checked by every dashboard action.

Returns:

  • (Boolean)


43
44
45
# File 'lib/testimonials.rb', line 43

def admin?(request)
  !!config.authorize_admin.call(request)
end

.app_nameObject



47
48
49
# File 'lib/testimonials.rb', line 47

def app_name
  config.app_name.presence || rails_app_name
end

.base_controllerObject

The class Testimonials::DashboardController inherits from. Resolved on every call rather than memoized, so a host that reassigns base_controller_class in a reloadable initializer is not pinned to a stale, unloaded constant.



37
38
39
# File 'lib/testimonials.rb', line 37

def base_controller
  config.base_controller_class.to_s.constantize
end

.configObject



19
20
21
# File 'lib/testimonials.rb', line 19

def config
  @config ||= Configuration.new
end

.configure {|config| ... } ⇒ Object

Yields:



23
24
25
# File 'lib/testimonials.rb', line 23

def configure
  yield config
end

The public-use consent line, stored verbatim when a customer allows their testimonial to be shown publicly. Override with config.consent_text.



84
85
86
87
88
# File 'lib/testimonials.rb', line 84

def consent_text
  config.consent_text.presence ||
    I18n.t('testimonials.consent_public',
           default: 'You can use my testimonial publicly in your marketing and sales.')
end

The exact line the customer agreed to, given their public/private choice.



97
98
99
# File 'lib/testimonials.rb', line 97

def consent_text_for(public_use)
  public_use ? consent_text : consent_text_private
end

The private-use line, stored when a customer allows only internal use.



91
92
93
94
# File 'lib/testimonials.rb', line 91

def consent_text_private
  I18n.t('testimonials.consent_private',
         default: 'You can only use my testimonial privately in your marketing and sales.')
end

.enabled?(request) ⇒ Boolean

Can this request see the widget and submit? Checked on the server for every public endpoint and by the helper before rendering.

Returns:

  • (Boolean)


29
30
31
# File 'lib/testimonials.rb', line 29

def enabled?(request)
  !!config.enabled.call(request)
end

.for(record) ⇒ Object

Testimonials belonging to a host record, keyed by its GlobalID — the documented tenant convention. Sugar for Testimonial.for_tenant(...); the has_testimonials model concern is built on this.



62
63
64
# File 'lib/testimonials.rb', line 62

def for(record)
  Testimonial.for_tenant(tenant_key_for(record))
end

.nps_for(record) ⇒ Object

The NPS responses belonging to a host record, same keying as .for.



67
68
69
# File 'lib/testimonials.rb', line 67

def nps_for(record)
  NpsResponse.for_tenant(tenant_key_for(record))
end

.questionsObject

The guiding questions for the current locale, with %app filled in. I18n leaves the token alone when no interpolation values are passed, so a plain gsub covers built-in, literal, and lambda-provided strings alike.



75
76
77
78
79
80
# File 'lib/testimonials.rb', line 75

def questions
  list = config.questions
  list = list.call if list.respond_to?(:call)
  list = I18n.t('testimonials.questions', default: []) if list.nil?
  Array(list).map { |q| q.to_s.gsub('%{app}', app_name) }
end

.tenant(request) ⇒ Object

The tenant key for this request, or nil for the single global collection. Normalized to a string so where(tenant:) is consistent whether the resolver returns a GlobalID, an integer id, or a slug. Blank resolves to nil — an app that only sometimes has a tenant falls back to global.



55
56
57
# File 'lib/testimonials.rb', line 55

def tenant(request)
  config.tenant.call(request).presence&.to_s
end