> ## Documentation Index
> Fetch the complete documentation index at: https://rollout.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ruby on Rails

## Step 1: Create View Template

Add a container element in your ERB template:

```xml theme={null}
<!-- app/views/your_controller/index.html.erb -->
<h1>Your Application</h1>
<div id="rollout-container"></div>
```

## Step 2: Add JavaScript Initialization

Create a JavaScript file or add to your existing pack:

### Choose what data to sync

An **entity** is a type of data, such as people, notes, or tasks. People sync automatically where supported. The examples below enable optional notes and tasks with `entitiesToSync`; choose the types your app needs. Alternatively, omit this prop to use the defaults you choose in [dashboard Settings](/docs/advanced-guides/controlling-which-records-sync-with-rollout#set-defaults-in-dashboard-settings). An explicit selection in code takes precedence over those defaults.

This configures new connections. For other types or accounts that are already connected, see [Choose what data to sync](/docs/advanced-guides/controlling-which-records-sync-with-rollout).

```javascript theme={null}
// app/javascript/packs/rollout.js
document.addEventListener('DOMContentLoaded', function() {
  const container = document.getElementById('rollout-container');
  
  // Fetch token from Rails backend
  fetch('/rollout-token', {
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': document.querySelector("[name='csrf-token']").content
    }
  })
  .then(response => response.json())
  .then(data => {
    const token = data.token;
    
    // Add required styles
    const styleLink = document.createElement('link');
    styleLink.rel = 'stylesheet';
    styleLink.href = 'https://esm.sh/@rollout/link-react@latest/dist/style.css';
    document.body.appendChild(styleLink);

    // Dynamically load Rollout bundle
    import(/* webpackIgnore: true */ 'https://esm.sh/@rollout/link-react@latest?bundle=all').then(
      ({ RolloutLinkProvider, CredentialsManager, createElement, createRoot }) => {
        const root = createRoot(container);
        
        root.render(
          createElement(
            RolloutLinkProvider,
            { token },
            createElement(CredentialsManager, {
              entitiesToSync: { notes: true, tasks: true }
            })
          )
        );
      }
    );
  });
});
```

## Step 3: Add Rails Route

Create a route to handle token generation:

```ruby theme={null}
# config/routes.rb
get '/rollout-token', to: 'rollout#generate_token'
```

## Step 4: Create Controller

Implement token generation in a controller:

```ruby theme={null}
# app/controllers/rollout_controller.rb
class RolloutController < ApplicationController
  def generate_token
    # Implement your actual token generation logic here
    # This should use your ROLLOUT_CLIENT_SECRET
    
    render json: {
      token: generate_secure_token # Replace with actual token generation
    }
  end

  private

  def generate_token(user_id)
   now = Time.now.to_i
 
   JWT.encode({
     iss: ENV['ROLLOUT_CLIENT_ID'],
     sub: user_id,
     iat: now,
     exp: now + 900  # 15 minutes
   },
   ENV['ROLLOUT_CLIENT_SECRET'],
   'HS512')
  end
end
```

## Step 5 (Optional): Handle Credential Events

Add event handling in the JavaScript:

```javascript theme={null}
// Update the import block
.then(({ RolloutLinkProvider, CredentialsManager, createElement, createRoot }) => {
  const handleCredentialAdded = ({ id, appKey }) => {
    console.log(`New credential added - ID: ${id}, App: ${appKey}`);
    
    // Send to Rails backend
    fetch('/store-credential', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': document.querySelector("[name='csrf-token']").content
      },
      body: JSON.stringify({
        credential_id: id,
        app_key: appKey
      })
    });
  };

  const root = createRoot(container);
  root.render(
    createElement(
      RolloutLinkProvider,
      { token },
      createElement(CredentialsManager, {
        entitiesToSync: { notes: true, tasks: true },
        onCredentialAdded: handleCredentialAdded
      })
    )
  );
});
```

## Step 6: Update CSP

Update `config/initializers/content_security_policy.rb`:

```ruby theme={null}
# config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy do |policy|
  policy.default_src :self
  policy.font_src    :self, :data
  policy.img_src     :self, :data
  policy.object_src  :none
  
  # Allow esm.sh for scripts and styles
  policy.script_src  :self, :unsafe_eval, :unsafe_inline, 'https://esm.sh'
  policy.style_src   :self, :unsafe_inline, 'https://esm.sh'
  
  # Allow connecting to your backend and Rollout's API
  policy.connect_src :self, 'https://universal.rollout.com'
  
  # If you're using webpack-dev-server in development
  if Rails.env.development?
    policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035", 'https://universal.rollout.com'
  end

  policy.worker_src  :self
end
```

### Alternative to CSP

You can also use nonces or hashes for better security, but that's more complex to set up with dynamic imports. If you want to go that route, you'd need to:

```ruby theme={null}
rubyCopyRails.application.config.content_security_policy do |policy|
  policy.script_src :self, :unsafe_eval, 'https://esm.sh' do |source|
    source.nonce :script
  end
end
```

And then update your JavaScript to include the nonce:

```javascript theme={null}
<script nonce="<%= request.content_security_policy_nonce %>">
  // Your code here
</script>
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.