# Editmode for Rails

Editmode frees up engineering time, unblocks designers and marketers, and helps software teams build better products faster,  by allowing everyone on the team (not just the engineers) to make copy updates safely and in real time. You can think of it as "A CMS for product copy", or "If Contentful and i18n had a baby"

* Let your design, product and engineering teams work in parallel - no more rigid hand-off process.
* Inspired by i18n - just swap `<%= t('your_key') %>` for `<%= e('your_key') %>`
* Safe, secure, and fast - used actively in large-scale production rails apps.
* Changes reflect in real time - no re-deploy needed. &#x20;
* API first means no clunky Github workflows. So simple your mom could use it with no training.
* Works with your existing codebase. Integration takes on average \~1 hour.
* (Optional) Use the Magic Editor to let people make changes _**inline**_, on the page where they appear
* (Optional) Use branches to run different versions of your content - for example a/b tests.
* (Optional) Use our content API to store and serve more complex content e.g rich text transactional emails.

{% embed url="https://www.youtube.com/watch?v=0MJrdYjMYu4" %}

### Installation

**1. Add the gem to your Gemfile:**

```ruby
gem 'editmode'
```

And run `bundle install`.

**2. Create an initializer with your project\_id**

Don't have a project id? Sign up for one [here](https://editmode.com/rails?s=ghreadme)

```bash
  rails generate editmode:config YOUR-PROJECT-ID
```

This command produces an initializer file

```ruby
# config/initializers/editmode.rb
Editmode.setup do |config|
  config.project_id={project_id}
end
```

By default Editmode will now include editmode.js in every page of your rails application, unless you disable auto-include.

**3. (Rails 6 Only) Ensuring the Magic Editor works with Content Security Policy**

* Add "[https://static.editmode.com](https://static.editmode.com/)" to `style_src` and `script_src` in your content security policy.
* Add "[https://api.editmode.com](https://api.editmode.com/)" to `connect_src` in your content security policy.

### Rendering Content

Editmode provides helper methods for use in your rails views and controllers.

#### Render the content of a chunk

```markup
<%= e('cnk_x4ts............') %> # Using a chunk identifier
<%= e('marketing_page_headline') %> # Using a content key
```

#### Render an _Editable_ chunk. (This will activate the inline Magic Editor)

```markup
<%= E('cnk_x4ts............') %> # Using a chunk identifier
<%= E('marketing_page_headline') %> # Using a content key
<%= E('cnk_x4ts...', class: "a-css-class") %> # Render a chunk with inline css class
```

#### Working with multiple projects in the same codebase

If you want to include content from a different project to the one you've specified in the initializer, you can pass the project id in to the view helper.

```markup
<%= E("cnk_16e04a02d577afb610ce", project_id: "prj_02d577afb617hdb") %>
```

#### Content can also be accessed in Controllers

```ruby
@page_title = e("cnk_x4ts............")  # Using a chunk identifier
@page_title = e("marketing_page_seo_title") # Using a content key
```

#### Directly get the value of a custom field

This works when a chunk is part of a collection.

```ruby
@email_subject = e("welcome_email","Subject")
@email_content = e("welcome_email","Content")
```

#### Working with variables

```ruby
variable_values = { first_name: "Dexter", last_name: "Morgan"}

# Assume chunk content is "Hi {{first_name}} {{last_name}}"

# Single Chunk with Variables
e("cnk_d36415052285997e079b", variables: variable_values)

# Collection Field with Variables
e("cnk_16e04a02d577afb610ce", "Email Content", variables: variable_values)

# Response: "Hi Dexter Morgan"
```

#### Use collections for repeatable content

```markup
<%= c('col_j8fbs...', class: "profiles-container", item_class: "profile-item") do %>
  <h3 class="name">
    <%= F("Name", class: "profile-name") %>
  </h3>
  <p class="description">
    <%= f("Description"), class: "profile-description" %>
  </p>
<% end %>
```

| Parameter   | Type       | Description                                                                                                               |
| ----------- | ---------- | ------------------------------------------------------------------------------------------------------------------------- |
| identifier  | string     | The first argument of `c` takes the id of the collection you want to loop through                                         |
| limit       | int/string | `optional` The number of collection items you want to display                                                             |
| tags        | array      | `optional` Filter collection items based on tags listed in this parameter                                                 |
| class       | string     | `optional` Class name(s) that will be added along with “chunks-collection-wrapper” to the main collection `<div>` element |
| item\_class | string     | `optional` Class name(s) that will be added along with “chunks-collection-item–wrapper” to all collection items           |

#### Access the current index from inside a collection block

`Available from editmode-rails 1.50`

```markup
<%= c('col_j8fbs...') do |chunk,index| %>
  <div class="<% 'highlight' if index.even? %>">
    <%= F("Name") %>
  </div>
<% end %>
```

#### Working with Image Transformation

Use `transformation` attribute to perform real-time image transformations to deliver perfect images to the end-users.

```markup
# This chunk should render an image with 200 x 200 dimension
= E('id-of-some-image', transformation: "w-200 h-200")

# For image inside a collection
= c('some-collection-id') do
  = F('Avatar', transformation: "w-200 h-200")
```

Please see the complete list of [transformation parameters](https://docs.editmode.com/editmode-docs/guides/image-transformation-properties).

### Caching

In order to keep your application speedy, Editmode minimizes the amount of network calls it makes by caching content where it can.

**What's cached**

*   Any embedded content returned by the `e`, `E`, `f`, or `F` view

    helpers.

**Expiring the cache**

The editmode gem exposes a cache expiration endpoint in your application at `/editmode/clear_cache`.

1.  GET `/editmode/clear_cache?identifier={chunk_id}` clears the cache

    for a specific chunk.
2. GET `/editmode/clear_cache?full=1` clears the full Editmode cache.
3. Editmode.js will automatically hit this endpoint when you update a chunk through your frontend.
4.  You can configure cache expiration webhooks in Editmode.com to

    ensure your application is notified when content changes happen on

    Editmode.com

The cache expiration endpoint is currently **not** authenticated.

{% hint style="info" %}
We are using a method called `delete_matched` to purge your caches when a content gets updated, and this method isn't supported in `memcached`. We highly recommend using `redis_store` or `file_store`.
{% endhint %}

### Disabling editmode.js auto-include

To disable automatic insertion for a particular controller or action you can:

```
 skip_after_action :editmode_auto_include
```

