@@ -1373,6 +1373,224 @@ Listed below are all configuration options.
1373
1373
corresponding table in DynamoDB at model persisting if the table
1374
1374
doesn't exist yet. Default is ` true `
1375
1375
1376
+ ## Multi-Configuration Support
1377
+
1378
+ Dynamoid supports multiple configurations to connect to different DynamoDB instances
1379
+ across multiple AWS accounts or regions. This is useful when you need to:
1380
+
1381
+ - Connect to DynamoDB tables in different AWS accounts
1382
+ - Use different regions for different models
1383
+ - Separate production/staging data across different AWS setups
1384
+ - Implement cross-account data access patterns
1385
+
1386
+ ### Setting up Multiple Configurations
1387
+
1388
+ Configure multiple DynamoDB connections in your application initializer:
1389
+
1390
+ ``` ruby
1391
+ # config/initializers/dynamoid.rb
1392
+ Dynamoid .multi_configure do |config |
1393
+ # Primary configuration (e.g., main application data)
1394
+ config.add_config(:primary ) do |c |
1395
+ c.access_key = ENV [' PRIMARY_AWS_ACCESS_KEY' ]
1396
+ c.secret_key = ENV [' PRIMARY_AWS_SECRET_KEY' ]
1397
+ c.region = ' us-east-1'
1398
+ c.namespace = ' myapp_primary'
1399
+ end
1400
+
1401
+ # Secondary configuration (e.g., analytics data)
1402
+ config.add_config(:analytics ) do |c |
1403
+ c.access_key = ENV [' ANALYTICS_AWS_ACCESS_KEY' ]
1404
+ c.secret_key = ENV [' ANALYTICS_AWS_SECRET_KEY' ]
1405
+ c.region = ' us-west-2'
1406
+ c.namespace = ' myapp_analytics'
1407
+ end
1408
+
1409
+ # Cross-account configuration (e.g., partner data)
1410
+ config.add_config(:partner ) do |c |
1411
+ c.credentials = Aws ::AssumeRoleCredentials .new (
1412
+ role_arn: ENV [' PARTNER_ROLE_ARN' ],
1413
+ role_session_name: ' dynamoid-cross-account'
1414
+ )
1415
+ c.region = ' eu-west-1'
1416
+ c.namespace = ' partner_shared'
1417
+ end
1418
+ end
1419
+ ```
1420
+
1421
+ ### Using Multiple Configurations in Models
1422
+
1423
+ Specify which configuration a model should use with the ` dynamoid_config ` method:
1424
+
1425
+ ``` ruby
1426
+ # Models using primary configuration
1427
+ class User
1428
+ include Dynamoid ::Document
1429
+
1430
+ dynamoid_config :primary
1431
+
1432
+ field :name , :string
1433
+ field :email , :string
1434
+
1435
+ has_many :orders
1436
+ end
1437
+
1438
+ class Order
1439
+ include Dynamoid ::Document
1440
+
1441
+ dynamoid_config :primary
1442
+
1443
+ field :total , :number
1444
+ field :status , :string
1445
+
1446
+ belongs_to :user
1447
+ end
1448
+
1449
+ # Models using analytics configuration
1450
+ class PageView
1451
+ include Dynamoid ::Document
1452
+
1453
+ dynamoid_config :analytics
1454
+
1455
+ field :url , :string
1456
+ field :user_id , :string
1457
+ field :timestamp , :datetime
1458
+
1459
+ global_secondary_index hash_key: :user_id , range_key: :timestamp
1460
+ end
1461
+
1462
+ class Report
1463
+ include Dynamoid ::Document
1464
+
1465
+ dynamoid_config :analytics
1466
+
1467
+ field :name , :string
1468
+ field :data , :serialized
1469
+ field :generated_at , :datetime
1470
+ end
1471
+
1472
+ # Models using partner configuration
1473
+ class SharedData
1474
+ include Dynamoid ::Document
1475
+
1476
+ dynamoid_config :partner
1477
+
1478
+ field :partner_id , :string
1479
+ field :content , :serialized
1480
+ field :sync_status , :string
1481
+ end
1482
+
1483
+ # Models using default configuration (fallback to main Dynamoid.configure)
1484
+ class SystemLog
1485
+ include Dynamoid ::Document
1486
+
1487
+ # No dynamoid_config specified - uses default configuration
1488
+
1489
+ field :level , :string
1490
+ field :message , :string
1491
+ field :timestamp , :datetime
1492
+ end
1493
+ ```
1494
+
1495
+ ### Configuration Inheritance
1496
+
1497
+ Models automatically inherit the correct configuration for all operations:
1498
+
1499
+ - ** Table operations** : ` create_table ` , ` delete_table `
1500
+ - ** CRUD operations** : ` create ` , ` save ` , ` update ` , ` delete ` , ` find `
1501
+ - ** Queries** : ` where ` , ` all ` , ` first ` , ` last `
1502
+ - ** Batch operations** : ` import ` , ` batch_write `
1503
+ - ** Scanning** : ` scan `
1504
+
1505
+ ``` ruby
1506
+ # Each model uses its own DynamoDB connection
1507
+ User .create(name: " John" , email: " john@example.com" ) # Uses :primary config
1508
+ PageView .create(url: " /home" , user_id: " 123" ) # Uses :analytics config
1509
+ SharedData .create(partner_id: " partner1" , content: {}) # Uses :partner config
1510
+ SystemLog .create(level: " info" , message: " App started" ) # Uses default config
1511
+ ```
1512
+
1513
+ ### Table Names and Namespaces
1514
+
1515
+ Each configuration can have its own namespace, resulting in different table prefixes:
1516
+
1517
+ ``` ruby
1518
+ # With the configurations above:
1519
+ User .table_name # => "myapp_primary_users"
1520
+ PageView .table_name # => "myapp_analytics_page_views"
1521
+ SharedData .table_name # => "partner_shared_shared_data"
1522
+ SystemLog .table_name # => "dynamoid_system_logs" (uses default namespace)
1523
+ ```
1524
+
1525
+ ### Configuration Management
1526
+
1527
+ ``` ruby
1528
+ # List all configured names
1529
+ Dynamoid ::MultiConfig .configuration_names
1530
+ # => [:primary, :analytics, :partner]
1531
+
1532
+ # Check if a configuration exists
1533
+ Dynamoid ::MultiConfig .configuration_exists?(:primary )
1534
+ # => true
1535
+
1536
+ # Get a specific configuration
1537
+ config = Dynamoid ::MultiConfig .get_config(:primary )
1538
+ config.region # => "us-east-1"
1539
+
1540
+ # Remove a configuration
1541
+ Dynamoid ::MultiConfig .remove_config(:analytics )
1542
+
1543
+ # Clear all configurations
1544
+ Dynamoid ::MultiConfig .clear_all
1545
+ ```
1546
+
1547
+ ### Error Handling
1548
+
1549
+ If you specify a non-existent configuration, Dynamoid will raise an error:
1550
+
1551
+ ``` ruby
1552
+ class InvalidModel
1553
+ include Dynamoid ::Document
1554
+
1555
+ dynamoid_config :nonexistent # This configuration doesn't exist
1556
+
1557
+ field :name , :string
1558
+ end
1559
+
1560
+ InvalidModel .create(name: " test" )
1561
+ # => Dynamoid::Errors::UnknownConfiguration: Unknown configuration: nonexistent
1562
+ ```
1563
+
1564
+ ### Best Practices
1565
+
1566
+ 1 . ** Environment-based configuration** : Use environment variables for sensitive credentials
1567
+ 2 . ** Logical separation** : Group related models in the same configuration
1568
+ 3 . ** Namespace isolation** : Use distinct namespaces to avoid table name conflicts
1569
+ 4 . ** Role-based access** : Use IAM roles for cross-account access when possible
1570
+ 5 . ** Connection reuse** : Configurations create connection pools, so reuse them efficiently
1571
+
1572
+ ``` ruby
1573
+ # Example: Environment-based setup
1574
+ Dynamoid .multi_configure do |config |
1575
+ # Production data
1576
+ config.add_config(:production ) do |c |
1577
+ c.credentials = Aws ::InstanceProfileCredentials .new
1578
+ c.region = ENV .fetch(' PRODUCTION_REGION' , ' us-east-1' )
1579
+ c.namespace = " #{ Rails .application.class .module_parent_name.downcase} _prod"
1580
+ end
1581
+
1582
+ # Analytics warehouse
1583
+ config.add_config(:warehouse ) do |c |
1584
+ c.credentials = Aws ::AssumeRoleCredentials .new (
1585
+ role_arn: ENV [' WAREHOUSE_ROLE_ARN' ],
1586
+ role_session_name: " #{ Rails .application.class .module_parent_name.downcase} -warehouse"
1587
+ )
1588
+ c.region = ENV .fetch(' WAREHOUSE_REGION' , ' us-west-2' )
1589
+ c.namespace = " warehouse_#{ Rails .env} "
1590
+ end
1591
+ end
1592
+ ```
1593
+
1376
1594
1377
1595
## Concurrency
1378
1596
0 commit comments