зеркало из
https://github.com/rs-pro/activeadmin-quill_editor.git
synced 2026-09-07 04:05:49 +03:00
feat: Add ActiveAdmin 4 and Propshaft support
- Switch to ActiveAdmin 4 beta with Tailwind CSS - Replace Sprockets with Propshaft for Rails 8 - Migrate from jQuery to vanilla JavaScript - Implement proper module initialization without setTimeout hacks - Add esbuild for JavaScript bundling with clean import aliases - Configure Tailwind CSS build process with ActiveAdmin plugin - Update engine configuration for both Propshaft and Sprockets - Add comprehensive documentation for AA4 gem updates - Maintain backward compatibility with legacy AA versions 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Этот коммит содержится в:
417
docs/activeadmin-4-gem-update-guide.md
Обычный файл
417
docs/activeadmin-4-gem-update-guide.md
Обычный файл
@@ -0,0 +1,417 @@
|
||||
# ActiveAdmin 4 Gem Update Guide
|
||||
|
||||
This guide documents the process of updating a gem to support ActiveAdmin 4 with Propshaft, Tailwind CSS, and modern Rails 8 asset pipeline.
|
||||
|
||||
## Overview
|
||||
|
||||
ActiveAdmin 4 represents a significant architectural shift from previous versions:
|
||||
- **CSS**: From Sprockets/SCSS to Tailwind CSS with custom build process
|
||||
- **JavaScript**: From jQuery to vanilla JavaScript with ES modules
|
||||
- **Asset Pipeline**: From Sprockets to Propshaft (Rails 8 default)
|
||||
- **Styling**: From pre-built CSS to user-built Tailwind CSS
|
||||
|
||||
## Key Changes Required
|
||||
|
||||
### 1. Gem Structure Changes
|
||||
|
||||
#### Remove CSS Assets
|
||||
ActiveAdmin 4 gems should NOT ship CSS files. Users build their own CSS with Tailwind.
|
||||
|
||||
```
|
||||
# Remove these directories/files:
|
||||
vendor/assets/stylesheets/
|
||||
app/assets/stylesheets/*.scss
|
||||
```
|
||||
|
||||
#### JavaScript Assets
|
||||
Keep only initialization JavaScript in vendor/assets:
|
||||
```
|
||||
vendor/assets/javascripts/your_gem_name.js # Vanilla JS, no jQuery
|
||||
```
|
||||
|
||||
### 2. Engine Configuration
|
||||
|
||||
Update `lib/your_gem/engine.rb`:
|
||||
|
||||
```ruby
|
||||
module YourGem
|
||||
class Engine < ::Rails::Engine
|
||||
# Propshaft automatically includes vendor/assets and app/assets paths
|
||||
|
||||
initializer 'your_gem.assets' do |app|
|
||||
# For Propshaft (Rails 8 default)
|
||||
if defined?(Propshaft)
|
||||
app.config.assets.precompile += %w[
|
||||
your_gem_name.js
|
||||
]
|
||||
# For Sprockets (legacy support)
|
||||
elsif app.config.respond_to?(:assets)
|
||||
app.config.assets.precompile += %w[
|
||||
your_gem_name.js
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### 3. JavaScript Migration
|
||||
|
||||
#### Remove jQuery Dependencies
|
||||
Convert all jQuery code to vanilla JavaScript:
|
||||
|
||||
```javascript
|
||||
// Old (jQuery)
|
||||
$(document).ready(function() {
|
||||
$('.quill-editor').each(function() {
|
||||
// initialization
|
||||
});
|
||||
});
|
||||
|
||||
// New (Vanilla JS)
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('.quill-editor').forEach(function(element) {
|
||||
// initialization
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Event Handling
|
||||
Use modern event delegation:
|
||||
|
||||
```javascript
|
||||
// Support both Turbo and non-Turbo apps
|
||||
['DOMContentLoaded', 'turbo:load', 'turbolinks:load'].forEach(function(eventName) {
|
||||
document.addEventListener(eventName, initializeEditors);
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Test/Dummy App Setup
|
||||
|
||||
#### Package.json
|
||||
Create a proper `package.json` for the test app:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "your-gem-test-app",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build:js": "node esbuild.config.js",
|
||||
"build:css": "bundle exec rake active_admin:build",
|
||||
"build": "npm run build:js && npm run build:css"
|
||||
},
|
||||
"dependencies": {
|
||||
"@activeadmin/activeadmin": "^4.0.0-beta16",
|
||||
"@rails/ujs": "^7.1.3",
|
||||
"your-required-npm-package": "^x.x.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.19.0",
|
||||
"tailwindcss": "^3.4.17"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Tailwind Configuration
|
||||
Create `tailwind.config.js`:
|
||||
|
||||
```javascript
|
||||
const execSync = require('child_process').execSync;
|
||||
const activeAdminPath = execSync('bundle show activeadmin', { encoding: 'utf-8' }).trim();
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
`${activeAdminPath}/vendor/javascript/flowbite.js`,
|
||||
`${activeAdminPath}/plugin.js`,
|
||||
`${activeAdminPath}/app/views/**/*.{arb,erb,html,rb}`,
|
||||
'./app/admin/**/*.{arb,erb,html,rb}',
|
||||
'./app/views/active_admin/**/*.{arb,erb,html,rb}',
|
||||
'./app/views/admin/**/*.{arb,erb,html,rb}',
|
||||
'./app/javascript/**/*.js'
|
||||
],
|
||||
darkMode: "class",
|
||||
plugins: [
|
||||
require('@activeadmin/activeadmin/plugin')
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
#### CSS Source File Structure
|
||||
Place source CSS OUTSIDE of Rails asset paths to avoid Propshaft conflicts:
|
||||
|
||||
```
|
||||
spec/dummy/
|
||||
app/
|
||||
css/ # NOT in assets/
|
||||
active_admin_source.css # Source file for Tailwind
|
||||
assets/
|
||||
builds/
|
||||
active_admin.css # Built output
|
||||
config/
|
||||
manifest.js # Propshaft manifest
|
||||
```
|
||||
|
||||
#### Active Admin CSS Source
|
||||
Create `app/css/active_admin_source.css` (or `app/assets/stylesheets/active_admin.css` per the gist):
|
||||
|
||||
```css
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
/* Import vendor styles if needed */
|
||||
@import "../../../node_modules/your-package/dist/styles.css";
|
||||
|
||||
/* Custom component styles */
|
||||
@layer components {
|
||||
.your-component {
|
||||
@apply border border-gray-300 rounded-md;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Build Task
|
||||
Create `lib/tasks/active_admin.rake`:
|
||||
|
||||
```ruby
|
||||
namespace :active_admin do
|
||||
desc "Build Active Admin Tailwind stylesheets"
|
||||
task build: :environment do
|
||||
command = [
|
||||
"npx", "tailwindcss",
|
||||
"-i", Rails.root.join("app/assets/stylesheets/active_admin.css").to_s,
|
||||
"-o", Rails.root.join("app/assets/builds/active_admin.css").to_s,
|
||||
"-c", Rails.root.join("tailwind.config.js").to_s,
|
||||
"-m"
|
||||
]
|
||||
|
||||
system(*command, exception: true)
|
||||
end
|
||||
|
||||
desc "Watch Active Admin Tailwind stylesheets"
|
||||
task watch: :environment do
|
||||
command = [
|
||||
"npx", "tailwindcss",
|
||||
"--watch",
|
||||
"-i", Rails.root.join("app/assets/stylesheets/active_admin.css").to_s,
|
||||
"-o", Rails.root.join("app/assets/builds/active_admin.css").to_s,
|
||||
"-c", Rails.root.join("tailwind.config.js").to_s,
|
||||
"-m"
|
||||
]
|
||||
|
||||
system(*command)
|
||||
end
|
||||
end
|
||||
|
||||
Rake::Task["assets:precompile"].enhance(["active_admin:build"])
|
||||
```
|
||||
|
||||
#### ESBuild Configuration
|
||||
Create `esbuild.config.js`:
|
||||
|
||||
```javascript
|
||||
const esbuild = require('esbuild');
|
||||
const railsEnv = process.env.RAILS_ENV || 'development';
|
||||
|
||||
const config = {
|
||||
entryPoints: ['app/javascript/active_admin.js'],
|
||||
bundle: true,
|
||||
sourcemap: railsEnv !== 'production',
|
||||
format: 'esm',
|
||||
outdir: 'app/assets/builds',
|
||||
publicPath: '/assets',
|
||||
loader: {
|
||||
'.js': 'js',
|
||||
},
|
||||
minify: railsEnv === 'production',
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
if (process.argv.includes('--watch')) {
|
||||
esbuild.context(config).then((ctx) => {
|
||||
ctx.watch();
|
||||
console.log('Watching for changes...');
|
||||
});
|
||||
} else {
|
||||
esbuild.build(config).then(() => {
|
||||
console.log('Build completed');
|
||||
}).catch(() => process.exit(1));
|
||||
}
|
||||
```
|
||||
|
||||
### 5. ActiveAdmin Initializer
|
||||
|
||||
Update `config/initializers/active_admin.rb`:
|
||||
|
||||
```ruby
|
||||
ActiveAdmin.setup do |config|
|
||||
# Register CSS (required for AA4 + Propshaft)
|
||||
config.register_stylesheet 'active_admin.css'
|
||||
|
||||
# Register JavaScript files
|
||||
config.register_javascript 'active_admin.js'
|
||||
config.register_javascript 'your_gem_name.js'
|
||||
|
||||
# ... other configuration
|
||||
end
|
||||
```
|
||||
|
||||
### 6. Propshaft Manifest
|
||||
|
||||
Update `app/assets/config/manifest.js`:
|
||||
|
||||
```javascript
|
||||
//= link_tree ../images
|
||||
//= link_tree ../builds
|
||||
//= link active_admin.css
|
||||
//= link active_admin.js
|
||||
//= link your_gem_name.js
|
||||
```
|
||||
|
||||
### 7. Common Pitfalls & Solutions
|
||||
|
||||
#### Issue: CSS not loading / Only Tailwind directives visible
|
||||
**Cause**: Propshaft serving source file instead of built file
|
||||
**Solution**:
|
||||
- Ensure source CSS is outside `app/assets/` or named differently
|
||||
- Check that build process outputs to `app/assets/builds/`
|
||||
- Verify `config.register_stylesheet 'active_admin.css'` in initializer
|
||||
|
||||
#### Issue: Missing ActiveAdmin layout styles
|
||||
**Cause**: ActiveAdmin plugin not loaded or content paths missing
|
||||
**Solution**:
|
||||
- Ensure `@activeadmin/activeadmin` npm package is installed
|
||||
- Add ActiveAdmin gem paths to Tailwind content configuration
|
||||
- Use `require('@activeadmin/activeadmin/plugin')` in Tailwind config
|
||||
|
||||
#### Issue: JavaScript not initializing
|
||||
**Cause**: Turbo/Turbolinks events not handled
|
||||
**Solution**: Listen for multiple initialization events:
|
||||
```javascript
|
||||
['DOMContentLoaded', 'turbo:load', 'turbolinks:load'].forEach(function(eventName) {
|
||||
document.addEventListener(eventName, initializeComponents);
|
||||
});
|
||||
```
|
||||
|
||||
#### Issue: Double asset compilation
|
||||
**Cause**: Both Sprockets and Propshaft trying to handle same files
|
||||
**Solution**:
|
||||
- Remove/rename conflicting files in `app/assets/stylesheets/`
|
||||
- Use specific file names in manifest instead of `link_tree`
|
||||
|
||||
### 8. Testing Setup
|
||||
|
||||
#### GitHub Actions Workflow
|
||||
|
||||
Create separate workflows for different ActiveAdmin versions:
|
||||
|
||||
```yaml
|
||||
name: Tests
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test-aa4:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
ruby: ['3.2', '3.3']
|
||||
rails: ['7.1', '8.0']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby }}
|
||||
bundler-cache: true
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: |
|
||||
cd spec/dummy
|
||||
npm install
|
||||
|
||||
- name: Build assets
|
||||
run: |
|
||||
cd spec/dummy
|
||||
npm run build
|
||||
|
||||
- name: Run tests
|
||||
run: bundle exec rspec
|
||||
|
||||
test-legacy:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
ruby: ['3.0', '3.1']
|
||||
activeadmin: ['2.14', '3.2']
|
||||
# ... legacy test configuration
|
||||
```
|
||||
|
||||
### 9. Migration Checklist
|
||||
|
||||
- [ ] Remove all SCSS/CSS assets from gem
|
||||
- [ ] Convert JavaScript from jQuery to vanilla JS
|
||||
- [ ] Create test app package.json with dependencies
|
||||
- [ ] Set up Tailwind configuration
|
||||
- [ ] Create CSS build process (rake task)
|
||||
- [ ] Set up JavaScript build (esbuild)
|
||||
- [ ] Update engine.rb for Propshaft
|
||||
- [ ] Configure ActiveAdmin initializer
|
||||
- [ ] Update Propshaft manifest
|
||||
- [ ] Test with both Turbo and non-Turbo apps
|
||||
- [ ] Update CI/CD for asset building
|
||||
- [ ] Document upgrade path for gem users
|
||||
|
||||
### 10. User Migration Guide
|
||||
|
||||
Provide clear instructions for gem users:
|
||||
|
||||
```markdown
|
||||
## Upgrading to v2.0 (ActiveAdmin 4 Support)
|
||||
|
||||
### Installation
|
||||
|
||||
1. Update your Gemfile:
|
||||
```ruby
|
||||
gem 'activeadmin', '~> 4.0.0.beta'
|
||||
gem 'your_gem', '~> 2.0'
|
||||
```
|
||||
|
||||
2. Install npm package:
|
||||
```bash
|
||||
npm install your-required-package
|
||||
```
|
||||
|
||||
3. Update your Tailwind config to include gem styles:
|
||||
```javascript
|
||||
// In your tailwind.config.js
|
||||
module.exports = {
|
||||
content: [
|
||||
// ... your existing content
|
||||
'./vendor/bundle/ruby/*/gems/your_gem-*/app/**/*.rb',
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
4. Import required styles in your CSS:
|
||||
```css
|
||||
/* In app/assets/stylesheets/active_admin.css */
|
||||
@import "your-package/dist/styles.css";
|
||||
```
|
||||
|
||||
5. Build your assets:
|
||||
```bash
|
||||
rails assets:precompile
|
||||
```
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [ActiveAdmin 4.0 Beta Documentation](https://github.com/activeadmin/activeadmin/tree/master/docs)
|
||||
- [Propshaft Documentation](https://github.com/rails/propshaft)
|
||||
- [Tailwind CSS Rails Integration](https://tailwindcss.com/docs/guides/rails)
|
||||
- [Working Example Gist](https://gist.github.com/amkisko/c704c1a6462d573dfa4820ae07d807a6)
|
||||
Ссылка в новой задаче
Block a user