diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3746d66..0000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: ruby - -env: - - 'RAILS_VERSION=5.2.0' - - 'RAILS_VERSION=6.0.0' - - 'RAILS_VERSION=6.1.0' - -before_script: - - 'yarn' - - 'bundle install' - - 'RAILS_ENV=test bundle exec rake db:create' - - 'RAILS_ENV=test bundle exec rake db:migrate' - -script: 'RAILS_ENV=test bundle exec rake test' \ No newline at end of file diff --git a/README.md b/README.md index 18ef7d7..0b395e2 100644 --- a/README.md +++ b/README.md @@ -78,12 +78,15 @@ Tell Abraham where to insert its generated JavaScript in `app/views/layouts/appl ## Defining your tours -Define your tours in the `config/tours` directory corresponding to the views defined in your application. Its directory structure mirrors your application's controllers, and the tour files mirror your actions/views. +Define your tours in the `config/tours` directory corresponding to the views defined in your application. Its directory structure mirrors your application's controllers, and the tour files mirror your actions/views. (As of version 2.4.0, Abraham respects controllers organized into modules.) ``` config/ └── tours/ - └── blog/ + ├── admin/ + │ └── articles/ + │ └── edit.en.yml + ├── blog/ │ ├── show.en.yml │ └── show.es.yml └── articles/ @@ -147,7 +150,8 @@ Abraham tries to be helpful when your tour steps attach to page elements that ar ### Automatic vs. manual tours -By default, Abraham will automatically start a tour that the current user hasn't seen yet. You can instead define a tour to be triggered manually using the `trigger` option: +By default, Abraham will automatically start a tour that the current user hasn't seen yet. +You can instead define a tour to be triggered manually using the `trigger` option: ```yml walkthrough: @@ -193,7 +197,18 @@ end We provide a [small example app](https://github.com/actmd/abraham-example) that implements Abraham, so you can see it in action. -## Upgrading from version 1 +## Upgrading + +### From version 2.3.0 or earlier + +Abraham 2.4.0 introduced an updated initializer that supports controllers organized into modules. +Rerun the generator with these options to replace the old initializer: + +``` +$ rails generate abraham:install --skip-migration --skip-config +``` + +### From version 1 Abraham v1 was built using Shepherd 1.8, v2 now uses Shepherd 6 – quite a jump, yes. @@ -249,7 +264,7 @@ gem 'abraham', path: '~/Workspace/abraham' #### Automated testing -We use TravisCI to automatically test this engine with Rails 5.2, 6.0, and 6.1. For test history, venture over to [TravisCI](https://travis-ci.com/actmd/abraham). +We use GitHub Actions to automatically test this engine with Rails 5.2, 6.0, and 6.1. ### Releasing diff --git a/app/helpers/abraham_helper.rb b/app/helpers/abraham_helper.rb index caa54dc..7d4db7b 100644 --- a/app/helpers/abraham_helper.rb +++ b/app/helpers/abraham_helper.rb @@ -3,15 +3,15 @@ module AbrahamHelper def abraham_tour # Do we have tours for this controller/action in the user's locale? - tours = Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.locale}"] + tours = Rails.configuration.abraham.tours["#{controller_path}.#{action_name}.#{I18n.locale}"] # Otherwise, default to the default locale - tours ||= Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.default_locale}"] + tours ||= Rails.configuration.abraham.tours["#{controller_path}.#{action_name}.#{I18n.default_locale}"] if tours # Have any automatic tours been completed already? completed = AbrahamHistory.where( creator_id: current_user.id, - controller_name: controller_name, + controller_name: controller_path, action_name: action_name ) @@ -33,7 +33,7 @@ module AbrahamHelper end def abraham_cookie_prefix - "abraham-#{fetch_application_name.to_s.underscore}-#{current_user.id}-#{controller_name}-#{action_name}" + "abraham-#{fetch_application_name.to_s.underscore}-#{current_user.id}-#{controller_path}-#{action_name}" end def fetch_application_name @@ -44,7 +44,6 @@ module AbrahamHelper end end - def abraham_domain request.host end diff --git a/app/views/application/_abraham.html.erb b/app/views/application/_abraham.html.erb index 886a092..51d24b4 100644 --- a/app/views/application/_abraham.html.erb +++ b/app/views/application/_abraham.html.erb @@ -9,7 +9,7 @@ headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ authenticity_token: '<%= form_authenticity_token %>', - controller_name: '<%= controller_name %>', + controller_name: '<%= controller_path %>', action_name: '<%= action_name %>', tour_name: '<%= tour_name %>' }) diff --git a/lib/generators/abraham/install_generator.rb b/lib/generators/abraham/install_generator.rb index 323f759..03ee440 100644 --- a/lib/generators/abraham/install_generator.rb +++ b/lib/generators/abraham/install_generator.rb @@ -10,6 +10,7 @@ module Abraham class_option :'skip-migration', type: :boolean, desc: "Don't generate a migration for the histories table" class_option :'skip-initializer', type: :boolean, desc: "Don't generate an initializer" + class_option :'skip-config', type: :boolean, desc: "Don't generate a config file" source_root File.expand_path(File.join(File.dirname(__FILE__), "templates")) @@ -24,6 +25,11 @@ module Abraham return if options["skip-initializer"] copy_file "initializer.rb", "config/initializers/abraham.rb" + end + + def create_config + return if options["skip-config"] + copy_file "abraham.yml", "config/abraham.yml" end end diff --git a/lib/generators/abraham/templates/initializer.rb b/lib/generators/abraham/templates/initializer.rb index 9bc5502..b5bbe26 100644 --- a/lib/generators/abraham/templates/initializer.rb +++ b/lib/generators/abraham/templates/initializer.rb @@ -2,18 +2,18 @@ Rails.application.configure do tours = {} + tours_root = Pathname.new(Rails.root.join("config/tours")) - if Rails.root.join('config/tours').exist? - Dir[Rails.root.join('config/tours/*/')].each do |dir| - Dir[dir + '*.yml'].each do |yml| - path_parts = yml.split(File::SEPARATOR) - controller = path_parts[path_parts.size - 2] - file_parts = path_parts[path_parts.size - 1].split('.') - action = file_parts[0] - locale = file_parts[1] - t = YAML.load_file(yml) - tours["#{controller}.#{action}.#{locale}"] = t - end + if Rails.root.join("config/tours").exist? + Dir.glob(Rails.root.join("config/tours/**/*.yml")).each do |yml| + relative_filename = Pathname.new(yml).relative_path_from(tours_root) + # `controller_path` is either "controller_name" or "module_name/controller_name" + controller_path, filename = relative_filename.split + file_parts = filename.to_s.split(".") + action = file_parts[0] + locale = file_parts[1] + t = YAML.load_file(yml) + tours["#{controller_path}.#{action}.#{locale}"] = t end end diff --git a/test/dummy/app/controllers/foobar/dashboard_controller.rb b/test/dummy/app/controllers/foobar/dashboard_controller.rb new file mode 100644 index 0000000..63c5322 --- /dev/null +++ b/test/dummy/app/controllers/foobar/dashboard_controller.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class Foobar::DashboardController < ApplicationController + def home; end +end diff --git a/test/dummy/app/views/foobar/dashboard/home.html.erb b/test/dummy/app/views/foobar/dashboard/home.html.erb new file mode 100644 index 0000000..d2bd68f --- /dev/null +++ b/test/dummy/app/views/foobar/dashboard/home.html.erb @@ -0,0 +1,4 @@ +
Find me in app/views/foobar/dashboard/home.html.erb
+ +We should get a unique tour for this module, not the same one as Dashboard#home \ No newline at end of file diff --git a/test/dummy/config/initializers/abraham.rb b/test/dummy/config/initializers/abraham.rb index 033092f..b5bbe26 100644 --- a/test/dummy/config/initializers/abraham.rb +++ b/test/dummy/config/initializers/abraham.rb @@ -2,18 +2,18 @@ Rails.application.configure do tours = {} + tours_root = Pathname.new(Rails.root.join("config/tours")) if Rails.root.join("config/tours").exist? - Dir[Rails.root.join("config/tours/*/")].each do |dir| - Dir[dir + "*.yml"].each do |yml| - path_parts = yml.split(File::SEPARATOR) - controller = path_parts[path_parts.size - 2] - file_parts = path_parts[path_parts.size - 1].split(".") - action = file_parts[0] - locale = file_parts[1] - t = YAML.load_file(yml) - tours["#{controller}.#{action}.#{locale}"] = t - end + Dir.glob(Rails.root.join("config/tours/**/*.yml")).each do |yml| + relative_filename = Pathname.new(yml).relative_path_from(tours_root) + # `controller_path` is either "controller_name" or "module_name/controller_name" + controller_path, filename = relative_filename.split + file_parts = filename.to_s.split(".") + action = file_parts[0] + locale = file_parts[1] + t = YAML.load_file(yml) + tours["#{controller_path}.#{action}.#{locale}"] = t end end diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb index 48cc29f..cebcb7a 100644 --- a/test/dummy/config/routes.rb +++ b/test/dummy/config/routes.rb @@ -6,5 +6,9 @@ Rails.application.routes.draw do get "dashboard/placement" get "dashboard/missing" + namespace :foobar do + get "dashboard/home" + end + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/test/dummy/config/tours/foobar/dashboard/home.en.yml b/test/dummy/config/tours/foobar/dashboard/home.en.yml new file mode 100644 index 0000000..0939c09 --- /dev/null +++ b/test/dummy/config/tours/foobar/dashboard/home.en.yml @@ -0,0 +1,4 @@ +module: + steps: + 1: + text: "This tour should appear for the Foobar::DashboardController only" \ No newline at end of file diff --git a/test/dummy/test/controllers/foobar/dashboard_controller_test.rb b/test/dummy/test/controllers/foobar/dashboard_controller_test.rb new file mode 100644 index 0000000..9eb1a38 --- /dev/null +++ b/test/dummy/test/controllers/foobar/dashboard_controller_test.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require "test_helper" + +class Foobar::DashboardControllerTest < ActionDispatch::IntegrationTest + test "home should have home tour code" do + get foobar_dashboard_home_url + assert_response :success + + assert_select "body script" do |element| + # it's the Foobar module home tour + assert element.text.include? "This tour should appear for the Foobar::DashboardController only" + end + end +end