hensei-api/docs/importers.md

400 lines
No EOL
8.4 KiB
Markdown

# Data Importers Documentation
The importer system provides a framework for importing game data from CSV files into the database. It supports test mode for validation, tracks new and updated records, and provides detailed error reporting.
## Architecture
### Base Importer
All importers inherit from `BaseImporter` which provides:
- CSV parsing and validation
- Test mode for dry runs
- New and updated record tracking
- Error handling and reporting
- Verbose logging support
- Batch processing with ActiveRecord transactions
### Available Importers
#### CharacterImporter
Imports character data from CSV files.
**Required CSV Fields:**
- `granblue_id` - Unique character ID
- `name_en` - English name
- `name_jp` - Japanese name
- `rarity` - Character rarity
- `element` - Element type
- `flb` - Has 5★ uncap (true/false)
- `ulb` - Has 6★ uncap (true/false)
- `wiki_en` - Wiki page name
**Example CSV:**
```csv
granblue_id,name_en,name_jp,rarity,element,flb,ulb,wiki_en
3040001000,Katalina,カタリナ,4,3,true,false,Katalina
```
#### WeaponImporter
Imports weapon data from CSV files.
**Required CSV Fields:**
- `granblue_id` - Unique weapon ID
- `name_en` - English name
- `name_jp` - Japanese name
- `rarity` - Weapon rarity
- `element` - Element type
- `weapon_type` - Type of weapon
- `wiki_en` - Wiki page name
**Example CSV:**
```csv
granblue_id,name_en,name_jp,rarity,element,weapon_type,wiki_en
1040001000,Murgleis,ミュルグレス,5,3,1,Murgleis
```
#### SummonImporter
Imports summon data from CSV files.
**Required CSV Fields:**
- `granblue_id` - Unique summon ID
- `name_en` - English name
- `name_jp` - Japanese name
- `rarity` - Summon rarity
- `element` - Element type
- `max_level` - Maximum level
- `wiki_en` - Wiki page name
**Example CSV:**
```csv
granblue_id,name_en,name_jp,rarity,element,max_level,wiki_en
2040001000,Bahamut,バハムート,5,0,150,Bahamut
```
## Usage
### Ruby API
```ruby
# Import character data
importer = Granblue::Importers::CharacterImporter.new(
'db/seed/updates/characters.csv',
test_mode: false,
verbose: true
)
result = importer.import
# Check results
result[:new_records] # => Array of newly created records
result[:updated_records] # => Array of updated records
result[:errors] # => Array of error messages
# Test mode - validate without importing
test_importer = Granblue::Importers::WeaponImporter.new(
'db/seed/updates/weapons.csv',
test_mode: true,
verbose: true
)
test_result = test_importer.import
```
### Rake Task
The main import task processes all CSV files in `db/seed/updates/`:
```bash
# Import all CSV files
rake granblue:import_data
# Test mode - validate without importing
rake granblue:import_data TEST=true
# Verbose output
rake granblue:import_data VERBOSE=true
# Both test and verbose
rake granblue:import_data TEST=true VERBOSE=true
```
## CSV File Format
### File Location
Place CSV files in: `db/seed/updates/`
### Naming Convention
- `characters_YYYYMMDD.csv` - Character data
- `weapons_YYYYMMDD.csv` - Weapon data
- `summons_YYYYMMDD.csv` - Summon data
### Encoding
- UTF-8 encoding required
- Unix line endings (LF) preferred
### Headers
- First row must contain field names
- Field names are case-sensitive
- Order doesn't matter
### Data Types
- **Strings**: Plain text, quotes optional unless contains commas
- **Numbers**: Integer or decimal values
- **Booleans**: `true` or `false` (lowercase)
- **Dates**: ISO 8601 format (YYYY-MM-DD)
- **Empty values**: Leave blank or use empty string
## Field Mappings
### Element Values
```
0 = Null/None
1 = Wind
2 = Fire
3 = Water
4 = Earth
5 = Dark
6 = Light
```
### Weapon Types
```
1 = Sword
2 = Dagger
3 = Spear
4 = Axe
5 = Staff
6 = Gun
7 = Melee
8 = Bow
9 = Harp
10 = Katana
```
### Rarity Values
```
1 = R (Rare)
2 = SR (Super Rare)
3 = SSR (Super Super Rare)
4 = SSR+
5 = Grand/Limited
```
## Test Mode
Test mode validates data without making database changes:
```bash
rake granblue:import_data TEST=true
```
Test mode will:
1. Parse CSV files
2. Validate all data
3. Check for duplicates
4. Report what would be created/updated
5. Show any validation errors
6. **NOT** save to database
Output example:
```
[TEST MODE] Would create Character: Katalina (3040001000)
[TEST MODE] Would update Weapon: Murgleis (1040001000)
[TEST MODE] Validation error for Summon: Invalid element value
```
## Error Handling
### Import Errors
The importer tracks various error types:
```ruby
{
errors: [
{
row: 5,
field: 'element',
message: 'Invalid element value: 99',
record: { granblue_id: '3040001000', name_en: 'Katalina' }
}
]
}
```
### Validation Errors
Records are validated before save:
- Required fields must be present
- Granblue ID must be unique
- Element must be valid (0-6)
- Rarity must be valid (1-5)
### Duplicate Handling
When a record with the same `granblue_id` exists:
1. Existing record is updated with new values
2. Update is tracked in `updated_records`
3. Original values are preserved in update log
## Batch Processing
The import system uses transactions for efficiency:
```ruby
ActiveRecord::Base.transaction do
records.each do |record|
# Process record
end
end
```
Benefits:
- All-or-nothing imports
- Better performance
- Automatic rollback on errors
## Best Practices
### 1. Always Test First
```bash
# Test mode first
rake granblue:import_data TEST=true VERBOSE=true
# Review output, then import
rake granblue:import_data VERBOSE=true
```
### 2. Use Dated Filenames
```
db/seed/updates/
├── characters_20240101.csv
├── weapons_20240115.csv
└── summons_20240201.csv
```
### 3. Validate Data Format
Before importing:
- Check CSV encoding (UTF-8)
- Verify headers match expected fields
- Validate element and rarity values
- Ensure granblue_id uniqueness
### 4. Backup Before Large Imports
```bash
# Backup database
pg_dump hensei_development > backup_$(date +%Y%m%d).sql
# Run import
rake granblue:import_data
# If issues, restore
psql hensei_development < backup_20240315.sql
```
### 5. Monitor Import Results
```ruby
# In Rails console
import_log = ImportLog.last
import_log.new_records_count
import_log.updated_records_count
import_log.errors
```
## Custom Importer Implementation
To create a custom importer:
```ruby
module Granblue
module Importers
class CustomImporter < BaseImporter
private
# Required: specify model class
def model_class
CustomModel
end
# Required: build attributes from CSV row
def build_attributes(row)
{
granblue_id: parse_value(row['granblue_id']),
name_en: parse_value(row['name_en']),
name_jp: parse_value(row['name_jp']),
custom_field: parse_custom_value(row['custom'])
}
end
# Optional: custom parsing logic
def parse_custom_value(value)
# Custom parsing
value.to_s.upcase
end
# Optional: additional validation
def validate_record(attributes)
errors = []
if attributes[:custom_field].blank?
errors << "Custom field is required"
end
errors
end
end
end
end
```
## Data Pipeline
Complete data import pipeline:
1. **Export from source** → CSV files
2. **Place in updates folder**`db/seed/updates/`
3. **Test import**`rake granblue:import_data TEST=true`
4. **Review results** → Check logs for errors
5. **Execute import**`rake granblue:import_data`
6. **Download images**`rake granblue:download_all_images[type]`
7. **Fetch wiki data**`rake granblue:fetch_wiki_data`
## Troubleshooting
### Import Not Finding Files
1. Check files are in `db/seed/updates/`
2. Verify file extensions are `.csv`
3. Ensure file permissions allow reading
### Validation Errors
1. Check CSV headers match expected fields
2. Verify data types (strings, numbers, booleans)
3. Validate element and rarity values
4. Ensure granblue_id is unique
### Encoding Issues
1. Save CSV as UTF-8
2. Remove BOM if present
3. Use Unix line endings (LF)
4. Check for special characters
### Performance Issues
For large imports:
1. Use batch processing
2. Disable callbacks if safe
3. Consider direct SQL for bulk operations
4. Import in smaller chunks
### Debugging
Enable verbose mode:
```bash
rake granblue:import_data VERBOSE=true
```
Check Rails console:
```ruby
# Recent imports
ImportLog.recent
# Failed imports
ImportLog.where(status: 'failed')
# Check specific record
Character.find_by(granblue_id: '3040001000')
```