Scrivito 1.9.1 Release Notes

posted by Andreas

This is a bugfix release.


This release makes widget and widget list menus on properties dialogs visible again, allowing you to add widgets to widget lists or move, copy, paste, or delete widgets in details views.

Sorry for the inconvenience this bug might have caused. Please update your Gemfile and run “bundle.”

Thank you for using Scrivito!

Scrivito 1.9.0 Release Notes

posted by Andreas

Unified changes view modes

When working on a page, Scrivito lets you compare the current page contents with the version you started off with. Up to now, the changes view that lets you do this had three modes, “Additions,” “Deletions,” and “All changes” of which – according to the feedback we collected – only the latter was used.

So, for less complexity and hence better usability, we combined these modes into one, removed the dropdown, and called this page display mode – guess what: “Changes.”

Further improvements and bugfixes

  • When hovering over the sidebar, a short delay now prevents it from opening immediately. This way, the mouse pointer can be moved over the edge of the browser window without causing the sidebar to flicker.

  • It is now possible to drag widgets from one CMS object to another one using their respective handle. This comes in handy if pages are composed of more than a single CMS object.

  • In the Content Browser’s details view a spinner is now displayed while the details of a CMS object are being loaded.

  • Scrivito now lets you prevent editors from accessing the publishing history. By default, all users may use the publishing history, but by withdrawing the new read_history permission, exceptions to the default can be made. For details, see: Defining users and their permissions

  • We fixed a bug that caused URL changes (using BinaryRewrite) to be not applied to binary CMS objects (e.g. images or PDF files) with a permalink.

  • When using the SDK editing API and applying scrivito("content") to enum attributes, string values with special characters (e. g. ampersands) are now handled correctly. Thus, the default enum editor now always properly reflects the current value.

  • We fixed a bug related to the preset routes. The preset routes wrongly identified the first component of the URL path as an ID if it was exactly 16 characters long and was made up of letters and digits. Now, it identifies only hexadecimal numbers (consisting of digits and the letters "a" to "f") as IDs.
    If your routes.rb file contains calls to scrivito_route, you are not using the preset routes and are therefore not affected by this bug.

  • Scrivito now automatically optimizes JPEG and PNG images by removing their metadata and adjusting their size using the default image transformation configuration setting. As a consequence, the Scrivito::BasicObj#apply_image_transformation? hook method no longer needs to be defined for each object class that represents images. In fact, this method has been deprecated because it's not called anymore.

  • When changes to content cannot be saved (due to network dropouts, for example), Scrivito now displays an alert box instead of showing the "Changes saved" indicator.

  • We fixed a bug related to restored browser sessions that caused the displayed content to be outdated.

  • A bug was fixed that caused a filter and the “Last added” view to be selected at the same time. It occurred only after creating a CMS object using the “Create item” button displayed along with the filtered items, not when creating items using drag and drop.

Testing Your Scrivito-Based Rails App 

posted by Antony

The question of how to test Scrivito-based apps comes up less often than you would expect, but none the less it is asked. Remember that Scrivito is just Ruby, but being mainly an API, there are some caveats. It is best kept in mind what Scrivito is, a Content Management System, so your testing will essentially revolve around views.

To start, the Scrivito SDK is fully tested.  So, as usual, there's no need to test the API.


For model/unit tests it is recommended to limit testing to the model attributes.

Your views and content are best tested with either JavaScript or more as a full integration test. We recommend to set up a separate CMS and test capybara style with a web-driver of some sort.

Pages and widgets themselves are tested like normal Rails models. Actually, there is no need to  test stuff coming from the CMS. We recommend to stub the CMS attribute methods and only test your custom methods as one would normally do with a standard Rails model. 

Model specs

Here is a sample model spec based on Scrivito's example application:

require 'rails_helper' RSpec.describe BlogPostPage, type: :model do it { respond_to(:abstract) } it { respond_to(:author_email) } it { respond_to(:author_name) } it { respond_to(:image) } it { respond_to(:published_at) } describe :text_extract do it "returns an abstract when one is provided" do short_abstract = "this is a short abstract of the blog post" blog = allow(blog).to receive(:abstract).and_return(short_abstract) expect(blog.text_extract).to eq(short_abstract) end end end

Here is a little more complex model spec that additionally tests nested widgets:

require 'rails_helper' RSpec.describe PanelGroupWidget, type: :model do it { respond_to(:layout_type) } it { respond_to(:panels) } describe :text_extract do it "returns text from each widget" do text = "this is the text in the text widget" text_widget = allow(text_widget).to receive(:text).and_return(text) widget = allow(widget).to receive(:content).and_return([text_widget]) group = allow(group).to receive(:panels).and_return([widget]) expect(group.text_extract).to eq([[text]]) end it "returns deliminated text when there are multiple texts" do text1 = "this is the text in the first text widget" text2 = "two is the text in the second text widget" text_widget1, text_widget2 =, allow(text_widget1).to receive(:text).and_return(text1) allow(text_widget2).to receive(:text).and_return(text2) widget = allow(widget).to receive(:content).and_return([text_widget1, text_widget2]) group = allow(group).to receive(:panels).and_return([widget]) expect(group.text_extract).to eq([[text1, text2]]) end end end

Controller specs

Here you can find a few example controller specs and a little spec helper for mocking pages and widgets. Scrivito provides a helper method, for_scrivito_obj, as some controllers do not have explicit routes by default. Changes in Rails 5 render the controller specs optional. These examples don't really test anything but that "it works". Nevertheless, they are included here to show some available patterns.

Example spec_helper for mocking

module ScrivitoSpecHelpers def mock_obj(klass, attributes={}) obj = attributes.each do |name, value| allow(obj).to receive(name) { value } end obj end def mock_widget(klass, attributes={}) widget = attributes.each do |name, value| allow(widget).to receive(name) { value } end widget end end

Example controller test with mocking

require 'rails_helper' RSpec.describe BlogPostPageController, type: :controller do let(:obj) { mock_obj(BlogPostPage, published_at: Time.current - 1.year) } describe 'GET index' do it 'renders the blog post page' do request.for_scrivito_obj(obj) get :index expect(response.status).to eq(200) end end end

Integration tests

For the integration tests, it would be best to mock your data requests and test only the code of your app. In an effort to keep it simple, and since one can start up the example app with consistent sample data, we are illustrating a request spec without mocking. The following example is testing that the content is rendered as expected, based on the parameters set in the controller.

Request specs

require 'rails_helper' RSpec.describe "BlogPage", type: :request do describe "GET /blog" do before do get "/blog" @posts = BlogPostPage.all.order(published_at: :desc).to_a end it "renders the blog overview page" do expect(response).to have_http_status(200) expect(response.body).to include "Tags" expect(response.body).to include "Feed" expect(response.body).to include "Photo Stream" assert_select "a[href=?]", "/#{@posts[0].title.parameterize}-#{@posts[0].id}" end it "shows titles of only the last 3 recent posts" do assert_select "div.col-md-9" do assert_select "div.row", 3 do assert_select "h4", @posts[0].title assert_select "h4", @posts[1].title assert_select "h4", @posts[2].title end end end it "does not include titles of more than the last 3 recent posts" do assert_select "h4", count: 0, html: @posts[3].title end it "includes images to the last 5 recent posts in the photo stream" do assert_select "div.col-md-3" do assert_select "div.panel" do assert_select "h2.panel-title", "Photo Stream" assert_select "ul.list-inline li a img", 5 assert_select "a[href=?]", "/#{@posts[0].title.parameterize}-#{@posts[0].id}" assert_select "a[href=?]", "/#{@posts[1].title.parameterize}-#{@posts[1].id}" assert_select "a[href=?]", "/#{@posts[2].title.parameterize}-#{@posts[2].id}" assert_select "a[href=?]", "/#{@posts[3].title.parameterize}-#{@posts[3].id}" assert_select "a[href=?]", "/#{@posts[4].title.parameterize}-#{@posts[4].id}" end end end it "has pagination" do assert_select ".previous", "← Older" expect(response.body).to_not include "Newer" end end end

This code tests the blog overview page. It checks whether it's returning the right blog posts and page elements, based on the parameters set in the controller.

If you cannot mock or do not wish to, it is recommended to set up additional Scrivito CMS instances to be used as testing environments. They would be used to create a working copy, add the content, publish and eventually delete everything with each run of the test. Keep in mind, an instance would only be able to deal with a single run at a time. So, if a developer wants to run such a test locally, they would have to have their own CMS instance. Otherwise, if there’s another developer running these tests in parallel against the same CMS instance, they will override each other’s data, resulting in non-predictable errors. Also, if there are CI machines running integration tests with publishes, each of these machines needs its own erasable CMS instance.

Creating the test tenant content is best done either in the test or via seed files. We advise to not copy anything from the production instance and in general completely isolate these two data sources in order to keep the production tenant as far from danger zones as possible. Also, in order to keep the tests as fast as possible, the seed data should to be as tiny as possible.

At Infopark, we use the following test workflow:

  • Reset a CMS instance at the very beginning of the test suite.
  • Run tests making publishes.

Note, we do not reset the tenant on each run, since it’s a relatively expensive and long-running operation.

In a nutshell …

… you have seen some ways to test your Rails app when used with Scrivito. Test your app and code as you would normally, and when testing content, test the view.

Scrivito 1.8.1 Release Notes

posted by Andreas


This is a bugfix release that solves two widget-related issues, and one referring to the Content Browser.

  • Restoring a widget that originally had a direct subwidget (which was deleted) no longer causes an error.
  • When restoring a widget, attributes that were originally empty are now cleared.
  • The Content Browser now applies the “base_query” if provided.

Sorry for the inconvenience these bugs might have caused. Please update your Gemfile and run “bundle.”

Thank you for using Scrivito!

Refurbished Account Settings

We are proud to present our new account settings interface on to all our Scrivito customers!

After logging in to Scrivito, you can access your settings via the menu behind your user name at the top right.

In the new account settings section you can comfortably do the following:

  • Access your demo or reset it
  • Manage your CMSs (rename, delete, set API keys)
  • Maintain your plan and billing settings

All your CMSs are neatly listed in the “CMS Instances” section which also offers a search in case you have lots of them.

Click the title or the gear icon of an entry to change the CMS's settings, e.g. its title or API keys, or to reset it, etc. Click “Create a CMS” to add another CMS instance to your account.

We hope you find the new account settings section as useful as we do! Check it out now!

Scrivito 1.8.0 Release Notes

posted by Andreas


Content Browser

The Content Browser is significantly faster now because it loads much more data in parallel. Just watch the main area while image thumbnails are being displayed!

Also, the multi-selection mode is now directly accessible in the user interface. It lets you select several items instead of just one.

This comes in handy if, for example, you want to delete a bunch of outdated images or the like. The multi-selection switch becomes available if the Content Browser is opened via the sidebar. Note that toggling the mode deselects all items.

More responsive changes list with better sorting

We've improved the look and feel of the changes dialog that lets you comfortably access the modified CMS objects of a working copy. Not only are the changes loaded much faster now, the not yet visible ones also show up continuously and smoothly as you scroll down.

The list of changed CMS objects can now be sorted using a drop-down menu instead of column headers. There are three sort criteria, last change date, object type name, and modification type. For each of them, both sort directions (ascending and descending) are available.

Configurable minimum request timeout

The Scrivito SDK fetches the content to display from the Scrivito backend located in European data centers. In case the content is requested from a far-off location, the response times might be longer than the SDK permits, resulting in a failure to load the data in time. To remedy this, you can now configure the minimum timeouts to apply to connections to the Scrivito API endpoint:

# config/initializers/scrivito.rb Scrivito.configure do |config| # … config.minimum_open_timeout = 1.0 config.minimum_ssl_timeout = 1.5 config.minimum_read_timeout = 1.0 # … end

These timeouts override shorter timeouts specified on a per-request basis, but not longer ones.

Other improvements

  • The Content Browser now ignores CMS objects of the MigrationStore type. Such objects are used by the SDK internally to identify migrations that have already been run.
  • The Scrivito::Workspace.use('workspace title') method now fails with a proper error message if there is no working copy with the given title. Previously, it failed with an unclear error message.

Scrivito 1.7.0 Release Notes

posted by Andreas


Rails 5.0 support

This release of Scrivito adds support for Rails 5.0 to the SDK. Rails 5.0 was released this summer and includes numerous speed improvements, refactorings and new features (see the Rails 5.0 overview for details).

Scrivito continues to support Rails 4.2, so in case you don't want to upgrade to Rails 5.0 yet, you can still update Scrivito to the latest version. A simple bundle update scrivito does the trick. There is one small exception: We no longer support the json gem in versions prior to 1.8.3. Previously, json 1.7.7 or newer was supported.

We worked hard to support both Rails versions and to facilitate a smooth transition from Rails 4.2 to 5.0. If you want to upgrade your application to Rails 5.0, please first upgrade to Scrivito 1.7.0 or later, then update Rails itself. See the Guide for Upgrading Ruby on Rails for a detailed list of changes between Rails 4.2 and 5.0.

We continue to support Ruby 2.1. Rails 5.0, however, requires Ruby 2.2.2 or newer. Since Ruby 2.1 has already reached a state in which it only receives security fixes, it is highly advised to upgrade to a newer Ruby version (see the Support plans for Ruby 2.0.0 and 2.1 for details).

Other improvements and changes

  • Due to optimizations regarding the saving indicator, adding widgets to and removing them from pages using the UI is now performed faster.
  • Scrivito has been optimized with respect to connections to the backend, which are now established in advance. Depending on your connection quality, this can save 100 ms or more per request during UI initialization.
  • The documented signature of scrivito_cache has been corrected: scrivito_cache should not be called with options=nil.
  • Due to unexpected behavior in the “Deletions” view mode, the Content Browser is now disabled in this mode.
  • Assets are now compiled deterministically into the “scrivito_app_extensions.js” file, yielding the same JavaScript file independently of the host OS or machine.
  • We fixed a bug that caused the changes list to redirect to the wrong URL for non-binary CMS objects after removing the /:id route.
  • In rare cases, opening a widget or navigation menu caused an error. This bug has been fixed.
  • The Content Browser is now able to handle different error situations in which an image cannot be displayed. If, for example, an image cannot be transformed due to its type or if the image is too large, the Content Browser now displays an appropriate thumbnail with an explanatory message.

    100 % CDN-Backed Asset Delivery

    One of the central benefits of using Scrivito is that binary content, e.g. images, is delivered fast and reliably to the visitors of your website, no matter where they're located. The technology behind this, the transparent use of a Content Distribution Network, isn't new to our CMS. In fact, CDN integration was an early milestone in the course of developing Scrivito.

    So what's the news?

    As of mid-December 2016, all content delivery is backed by the CDN behind Scrivito, Amazon CloudFront. For this to work, we recently changed the asset URLs.

    Before that, only assets part of the published content and of working copies being previewed were delivered via the CDN. In editing mode, assets were served solely by EU-based Amazon S3.

    So, when editing pages containing any amount of images, pages should load speedier now, especially if you're not located in the EU.

    Happy editing!

    Scrivito 1.5.5 and 1.6.1 Release Notes

    posted by Dave


    In some cases, the referencelist attribute editor was unable to process references with purely numeric IDs.

    According to our in-house mathematician, Scrivito users had a 0,054% chance to hit this issue. The number increased with the size of the referencelist. After fixing the issue, the chance of a clash is most probably zero.

    Please update your Gemfile and run “bundle.”

    Thank you for using Scrivito!

    Scrivito 1.4.3 and 1.5.4 Release Notes

    posted by Andreas


    These releases make Scrivito compatible with jquery-ui-rails 6.

    On November 29, 2016, jquery-ui-rails 6 has been released. Unfortunately, Scrivito was incompatible with this new major version.

    Sorry to everyone who has been bitten by this. Please update your Gemfile and run “bundle.”

    Thank you for using Scrivito!