Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ruby 2.7.1
ruby 3.3.3
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
timescaledb (0.3.1)
timescaledb (0.3.2)
activerecord
activesupport
ostruct
Expand Down Expand Up @@ -33,8 +33,8 @@ GEM
concurrent-ruby (~> 1.0)
method_source (1.0.0)
minitest (5.18.0)
ostruct (0.6.1)
pg (1.5.8)
ostruct (0.6.3)
pg (1.6.2)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
Expand Down
6 changes: 3 additions & 3 deletions Gemfile.scenic.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
timescaledb (0.3.1)
timescaledb (0.3.2)
activerecord
activesupport
ostruct
Expand Down Expand Up @@ -57,8 +57,8 @@ GEM
nokogiri (1.12.5)
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
ostruct (0.6.1)
pg (1.5.9)
ostruct (0.6.3)
pg (1.6.2)
pry (0.14.1)
coderay (~> 1.1)
method_source (~> 1.0)
Expand Down
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,28 @@ gem install timescaledb

## Quick Start

### 1. Configuration

Configuration options can be optionally passed in using an initializer.

```ruby
# config/initializers/timescaledb.rb
Timescaledb.configure do |config|
# config.some_option = true
end
```

The following table includes all currently available configuration options:

| Option | Supported Values | Default Value | Explanation |
|----------------------|---------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `scenic_integration` | `:enabled`<br>`:disabled` | `:enabled` | Controls whether the gem automatically integrates with the Scenic gem for managing database views. When set to :enabled (default), the gem will auto-detect if Scenic is available and configure it to work with TimescaleDB continuous aggregates. Set to :disabled to prevent automatic Scenic integration.<br><br>**Warning:** This integration may cause issues when used with multiple databases and one of the databases does not support TimescaleDB |

### 2. Create Hypertables in the Active Record Migrations

The timescaledb gem provides helpers for creating hypertables, configuring compression, retention policies, and more.
After adding the gem to your Gemfile, you can create hypertables in your migrations.

### 1. Create Hypertables in the Active Record Migrations

```ruby
class CreateEvents < ActiveRecord::Migration[7.0]
def up
Expand All @@ -61,7 +78,7 @@ class CreateEvents < ActiveRecord::Migration[7.0]
end
```

### 2. Enable TimescaleDB in Your Models
### 3. Enable TimescaleDB in Your Models

You can enable TimescaleDB in your models by adding the `acts_as_hypertable` macro to your model. This macro extends your existing model with timescaledb-related functionality.

Expand Down
14 changes: 14 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
volumes:
timescaledb:
external: false

services:
timescaledb:
image: timescale/timescaledb-ha:pg18
volumes:
- timescaledb:/home/postgres/pgdata/data
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=timescaledb_test
ports:
- 5432:5432
171 changes: 171 additions & 0 deletions docs/development/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Running the Test Suite

This guide explains how to set up and run the test suite for the TimescaleDB Ruby gem.

## Prerequisites

### Ruby Version

The test suite requires Ruby 3.3.3 (as specified in `.ruby-version`). The gem itself supports Ruby >= 2.3.0, but the test suite uses Ruby 3.3.3.

You can use a Ruby version manager like `rbenv` or `rvm` to install and manage the correct version:

```bash
# Using rbenv
rbenv install 3.3.3
rbenv local 3.3.3

# Using rvm
rvm install 3.3.3
rvm use 3.3.3
```

### TimescaleDB Installation

You need to have TimescaleDB installed and running. TimescaleDB is a PostgreSQL extension, so you'll need:

1. PostgreSQL installed
2. TimescaleDB extension installed and enabled

For installation instructions, see the [TimescaleDB documentation](https://docs.timescale.com/install/latest/).

### Database Connection

The test suite requires a PostgreSQL database with TimescaleDB enabled. You'll need to:

1. Create a test database (if it doesn't exist)
2. Enable the TimescaleDB extension on that database
3. Set the `PG_URI_TEST` environment variable

## Setup

### 1. Install Dependencies

```bash
bundle install
```

### 2. Configure Database Connection

Set the `PG_URI_TEST` environment variable to point to your test database:

```bash
export PG_URI_TEST="postgresql://username:password@localhost:5432/timescale_test"
```

Or create a `.env` file in the project root:

```bash
PG_URI_TEST=postgresql://username:password@localhost:5432/timescale_test
```

The `.env` file will be automatically loaded by the test suite (via the `dotenv` gem).

### 3. Create and Configure Test Database

Create the test database and enable TimescaleDB:

```bash
# Connect to PostgreSQL
psql -U postgres

# Create the database
CREATE DATABASE timescale_test;

# Connect to the test database
\c timescale_test

# Enable TimescaleDB extension
CREATE EXTENSION IF NOT EXISTS timescaledb;
CREATE EXTENSION IF NOT EXISTS timescaledb_toolkit;
```

### 4. Setup Test Tables

Before running tests, you need to set up the test tables. This will create the necessary hypertables and test fixtures:

```bash
bundle exec rake test:setup
```

This command:
- Tears down any existing test tables
- Creates fresh test tables with the correct schema
- Sets up hypertables for testing

**Note:** You should run `rake test:setup` whenever:
- You first set up the test environment
- The test schema changes
- Tests are failing due to missing or incorrect tables

## Running Tests

### Run All Tests

```bash
bundle exec rspec
```

### Run Specific Test Files

```bash
bundle exec rspec spec/timescaledb/migration_helper_spec.rb
```

### Run Specific Tests

```bash
bundle exec rspec spec/timescaledb/migration_helper_spec.rb:114
```

### Run Tests with Output

By default, ActiveRecord SQL logging is silenced. To see SQL queries during tests, set the `DEBUG` environment variable:

```bash
DEBUG=1 bundle exec rspec
```

### Run Only Failed Tests

```bash
bundle exec rspec --only-failures
```

## Troubleshooting

### Database Connection Errors

If you see connection errors, verify:
- PostgreSQL is running
- The database exists
- TimescaleDB extension is enabled
- `PG_URI_TEST` is set correctly

### Missing Tables Errors

If tests fail with "table does not exist" errors, run:

```bash
bundle exec rake test:setup
```

### TimescaleDB Extension Not Found

If you see errors about TimescaleDB functions not being available:
- Verify TimescaleDB is installed: `psql -c "SELECT * FROM pg_extension WHERE extname = 'timescaledb';"`
- Ensure the extension is enabled on your test database
- Check that your PostgreSQL version is compatible with your TimescaleDB version

### Timescale Toolkit Not Installed

Occasionally you may see numerous failures related to functions being undefined within TimescaleDB. To resolve this, ensure you have the [TimescaleDB Toolkit](https://github.com/timescale/timescaledb-toolkit) plugin installed and enabled

## Continuous Integration

The test suite is designed to work in CI environments. Make sure your CI configuration:

1. Sets the `PG_URI_TEST` environment variable
2. Has TimescaleDB installed and enabled
3. Runs `bundle exec rake test:setup` before running tests

53 changes: 43 additions & 10 deletions lib/timescaledb.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# frozen_string_literal: true

require 'active_record'

require_relative 'timescaledb/configuration'
require_relative 'timescaledb/application_record'
require_relative 'timescaledb/acts_as_hypertable'
require_relative 'timescaledb/acts_as_hypertable/core'
Expand All @@ -22,6 +25,39 @@
require_relative 'timescaledb/version'

module Timescaledb
class << self
def configure
yield(configuration) if block_given?
end

def configuration
@configuration ||= Configuration.new
end

def setup_scenic_integration
return unless configuration.enable_scenic_integration?
return if @scenic_integration_setup

begin
require 'scenic'
require_relative 'timescaledb/scenic/adapter'
require_relative 'timescaledb/scenic/extension'

::Scenic.configure do |config|
config.database = Timescaledb::Scenic::Adapter.new
end

::Scenic::Adapters::Postgres.include(Timescaledb::Scenic::Extension)
::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Timescaledb::Scenic::MigrationHelpers)

@scenic_integration_setup = true
rescue LoadError
# This is expected when the scenic gem is not being used
@scenic_integration_setup = false
end
end
end

module_function

def connection
Expand Down Expand Up @@ -65,15 +101,12 @@ def default_hypertable_options
end
end

begin
require 'scenic'
require_relative 'timescaledb/scenic/adapter'
require_relative 'timescaledb/scenic/extension'

Scenic.configure do |config|
config.database = Timescaledb::Scenic::Adapter.new
# Delay scenic integration setup to respect user configuration when using Rails
if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
ActiveSupport.on_load(:active_record) do
Timescaledb.setup_scenic_integration
end

rescue LoadError
# This is expected when the scenic gem is not being used
else
# For non-Rails usage, setup immediately
Timescaledb.setup_scenic_integration
end
32 changes: 32 additions & 0 deletions lib/timescaledb/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module Timescaledb
class Configuration
attr_accessor :scenic_integration

DEFAULTS = {
scenic_integration: :enabled
}.freeze

def initialize
@scenic_integration = DEFAULTS[:scenic_integration]
end

def enable_scenic_integration?
case @scenic_integration
when :enabled then scenic_detected?
else false # :disabled, :false, nil, etc.
end
end

private

def scenic_detected?
# Try to require scenic to see if it's available
require 'scenic'
true
rescue LoadError
false
end
end
end
Loading