@spree/docs 0.1.85 → 0.1.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,36 +1,44 @@
1
1
  ---
2
2
  title: Tutorial
3
3
  sidebarTitle: Introduction
4
- description: Learn how to build a custom feature from scratch, covering models, Admin dashboard and API.
4
+ description: Build a complete custom feature model, admin UI, Store API, and TypeScript storefront integration — the Spree way.
5
5
  ---
6
6
 
7
- This tutorial walks you through creating a complete Spree feature from scratch, covering models, Admin dashboard, Store API, and TypeScript SDK integration.
8
- You will also learn how to extend core Spree features to connect them with your new feature.
9
- By the end, you'll understand how to add new manageable features to the Spree platform.
7
+ This tutorial walks you through creating a complete Spree feature from scratch: a "Brands" feature that lets admins manage [Product](../core-concepts/products.md) brands, exposes them through the Store API, and consumes them from TypeScript.
10
8
 
11
- ## Overview
9
+ It's written for **both backend and frontend developers**. The Ruby you'll write is minimal and mostly generated — Spree's generators produce convention-correct models, admin UIs, and API endpoints, and the TypeScript SDK gives you typed access from your storefront. You don't need to be a Rails expert to follow along.
12
10
 
13
- To fully implement a new feature, you will typically create the following components:
11
+ ## Before you start
14
12
 
15
- * Database model
16
- * Admin Dashboard controllers and views
17
- * Store API endpoints and serializers
18
- * TypeScript SDK integration
19
- * Automated tests
13
+ You need a running Spree app. The fastest path is [create-spree-app](../create-spree-app/quickstart.md) — a Docker-based project with the [Spree CLI](../cli/quickstart.md), no local Ruby required:
20
14
 
21
- ## Tutorial Sections
15
+ ```bash
16
+ npx create-spree-app@latest my-store
17
+ ```
18
+
19
+ An existing app with Spree gems works just as well. **Every command in this tutorial is shown in two forms** — **Spree CLI** (runs inside Docker) and **Without Spree CLI** (runs directly on your machine) — pick the tab that matches your setup and ignore the other.
20
+
21
+ > **NOTE:** **create-spree-app projects:** run `spree eject` once before starting. Fresh projects use a prebuilt Docker image; ejecting switches to the dev setup that mounts `backend/` into the container, so the files the generators create land in your project (and reload live as you edit them).
22
22
 
23
+ > **TIP:** Using an AI coding agent? Install the [Spree agent skills](../agentic/agent-skills.md) (`npx skills add spree/agent-skills`) and connect the [docs MCP server](../agentic/mcp.md) before starting — your agent will know the conventions this tutorial teaches and can follow along with you. See [Agentic Development](../agentic/overview.md).
23
24
 
24
- - [1. Model](model.md) — Create the Brand model with migrations, validations, and associations
25
- - [2. Admin Dashboard](admin.md) — Build admin interface for managing brands
26
- - [3. Rich Text](rich-text.md) — Add rich text descriptions using Action Text
27
- - [4. File Uploads](file-uploads.md) — Add logo images with Active Storage
28
- - [5. Extending Core Models](extending-models.md) — Connect Brands to Products using associations
29
- - [6. Store API](store-api.md) — Expose Brands through the Store API with serializers, controllers, and routes
30
- - [7. SDK](sdk.md) — Consume Brand endpoints from TypeScript using the SDK
31
- - [8. Testing](testing.md) — Write automated tests for your feature
25
+ ## What you'll build
32
26
 
27
+ * A `Brand` model with a rich text description and an uploadable logo — one generator command
28
+ * An admin UI for managing brands — one generator command, then customized
29
+ * A `brand` association on Products, surfaced in the product admin form
30
+ * Store API endpoints (`GET /api/v3/store/brands`) with serializers and prefixed IDs
31
+ * Typed TypeScript access to brands from your storefront via `@spree/sdk`
32
+ * Event subscribers and webhooks connecting the store to external systems
33
+ * Automated tests for all of it
34
+
35
+ ## Tutorial Sections
33
36
 
34
- ## Example: Building a Brands Feature
35
37
 
36
- In this guide we will create a complete "Brands" feature that allows admins to manage [Product](../core-concepts/products.md) brands.
38
+ - [1. Model](model.md) Generate the Brand model columns, rich text description, and logo upload in one command
39
+ - [2. Admin Dashboard](admin.md) — Scaffold the admin UI, then add the description editor, logo upload, and table columns
40
+ - [3. Extending Core Models](extending-models.md) — Connect Brands to Products using a decorator and an association
41
+ - [4. API](api.md) — Expose Brands through the Store and Admin APIs — generated in one command, or hand-built to learn the pieces
42
+ - [5. Events & Webhooks](events.md) — React to store activity and connect external systems — OMS, warehouse, ERP
43
+ - [6. SDK](sdk.md) — Consume Brand endpoints from TypeScript using the SDK
44
+ - [7. Testing](testing.md) — Write automated tests for your feature
@@ -1,41 +1,102 @@
1
1
  ---
2
2
  title: Model
3
- description: Learn how to create a database model for the Brands feature
3
+ description: Create the Brand model columns, rich text description, and logo upload — with a single generator command
4
4
  ---
5
5
 
6
- ## Step 1: Create the Model and Database Migration
6
+ In this step we'll create the `Spree::Brand` model with everything it needs: a `name` column, a rich text `description`, and an uploadable `logo`.
7
7
 
8
- To create a new model and database migration file, run the following command:
8
+ ## Step 1: Generate the Model
9
9
 
10
- ```bash
11
- bin/rails g spree:model Spree::Brand name:string:index
10
+ Spree ships a `spree:model` generator that produces a model and migration following all Spree conventions — `Spree::` namespacing, prefixed IDs, presence validations, and API filtering allowlists. It understands Rails attribute types including the virtual ones, so rich text and file attachments are part of the same command:
11
+
12
+
13
+ ```bash Spree CLI (Docker)
14
+ spree generate model Brand name:string:index description:rich_text logo:attachment
15
+ ```
16
+
17
+ ```bash Without Spree CLI
18
+ bin/rails g spree:model Brand name:string:index description:rich_text logo:attachment
12
19
  ```
13
20
 
14
- This will create a couple of files:
15
- - `app/models/spree/brand.rb` - the model file
16
- - `db/migrate/XXXXXXXXXXXXXX_create_spree_brands.rb` - the database migration file
17
21
 
18
- Now run the migration:
22
+ > **INFO:** Throughout this tutorial every command is shown in two forms. **Spree CLI** is for projects created with [create-spree-app](../create-spree-app/quickstart.md), where the app runs in Docker and `spree <command>` routes into the container. **Without Spree CLI** is for apps running Spree backend directly on your machine.
23
+
24
+ This creates two files:
25
+
26
+ - `app/models/spree/brand.rb` — the model
27
+ - `db/migrate/XXXXXXXXXXXXXX_create_spree_brands.rb` — the migration
28
+
29
+ Now apply the migration:
30
+
19
31
 
20
- ```bash
32
+ ```bash Spree CLI (Docker)
33
+ spree migrate
34
+ ```
35
+
36
+ ```bash Without Spree CLI
21
37
  bin/rails db:migrate
22
38
  ```
23
39
 
24
- This will create the table `spree_brands` with the column `name` in the database. The `name` column is indexed for faster lookups. Also the model file `app/models/spree/brand.rb` is created.
25
40
 
26
- ## Step 2: Extend the Model file
41
+ This creates the `spree_brands` table with an indexed `name` column. The `description` and `logo` attributes don't add columns — rich text lives in Action Text's `action_text_rich_texts` table, and uploads live in Active Storage's tables.
27
42
 
28
- Now that the model file is created, let's add some additional functionality to it, starting with validations:
43
+ ## Step 2: Understand the Generated Model
29
44
 
30
- ```ruby app/models/spree/brand.rb {3-4}
45
+ Open `app/models/spree/brand.rb`:
46
+
47
+ ```ruby app/models/spree/brand.rb
31
48
  module Spree
32
- class Brand < Spree::Base
33
- # Validations
49
+ class Brand < Spree.base_class
50
+ has_prefix_id :brand
51
+
52
+ has_rich_text :description
53
+ has_one_attached :logo
54
+
34
55
  validates :name, presence: true
56
+
57
+ self.whitelisted_ransackable_attributes = %w[name]
58
+ self.whitelisted_ransackable_associations = %w[]
59
+ self.whitelisted_ransackable_scopes = %w[]
35
60
  end
36
61
  end
37
62
  ```
38
63
 
39
- This is a standard [Ruby on Rails ActiveRecord model](https://guides.rubyonrails.org/active_record_basics.html). Let's break down each part:
40
- - Inherits from `Spree::Base` to automatically inherit all Spree functionality. Also the model itself is namespaced under `Spree::` module, so it's available as `Spree::Brand` in the application.
41
- - `validates :name, presence: true` - using ActiveRecord validations to ensure that the name is present.
64
+ Line by line:
65
+
66
+ - **`Spree.base_class`** inherits all Spree model functionality (multi-store scoping helpers, preferences, and more). The class is namespaced under `Spree::`, so it's available as `Spree::Brand`.
67
+ - **`has_prefix_id :brand`** — records get Stripe-style public IDs like `brand_k5nR8xLq`. APIs never expose raw database IDs.
68
+ - **`has_rich_text :description`** — formatted content via [Action Text](https://guides.rubyonrails.org/action_text_overview.html).
69
+ - **`has_one_attached :logo`** — file uploads via [Active Storage](https://guides.rubyonrails.org/active_storage_overview.html), with image processing and direct-to-storage uploads.
70
+ - **`validates :name, presence: true`** — generated automatically for required columns.
71
+ - **`whitelisted_ransackable_attributes`** — controls which attributes API clients may filter and sort by. Only allowlisted attributes are queryable, so adding `name` here is what later makes `?q[name_cont]=nike` work.
72
+
73
+ ## Step 3: Try It in the Console
74
+
75
+
76
+ ```bash Spree CLI (Docker)
77
+ spree console
78
+ ```
79
+
80
+ ```bash Without Spree CLI
81
+ bin/rails console
82
+ ```
83
+
84
+
85
+ ```ruby
86
+ brand = Spree::Brand.create!(name: "Wilson")
87
+ brand.prefixed_id # => "brand_k5nR8xLq"
88
+
89
+ brand.update!(description: "<h1>Hello</h1><p>World</p>")
90
+ brand.description.to_s # => rendered rich text HTML
91
+ brand.description.to_plain_text # => "Hello World"
92
+
93
+ Spree::Brand.find_by_prefix_id!("brand_k5nR8xLq") # lookup by public ID
94
+ ```
95
+
96
+ We'll upload the logo through the admin UI in the next step — the model side is already done.
97
+
98
+ > **TIP:** The generator accepts more attribute types and options — references with auto-resolved class names (`user:belongs_to`), unique indexes (`slug:string:uniq`), soft delete (`--paranoid`), and custom fields support (`--metafields`). Run it with `--help` to see everything.
99
+
100
+ ## Next Step
101
+
102
+ The model is complete. Now let's give admins a UI to manage brands: [Admin Dashboard](admin.md).
@@ -3,9 +3,9 @@ title: SDK
3
3
  description: Use the TypeScript SDK to consume your custom Brand endpoints and extended Product data
4
4
  ---
5
5
 
6
- In this tutorial, we'll use the `@spree/sdk` TypeScript SDK to consume the Brand API endpoints we created in the [Store API tutorial](store-api.md), and work with the extended Product data that now includes brand information.
6
+ In this tutorial, we'll use the `@spree/sdk` TypeScript SDK to consume the Brand API endpoints we created in the [API tutorial](api.md), and work with the extended Product data that now includes brand information.
7
7
 
8
- > **INFO:** This guide assumes you've completed the [Store API](store-api.md) tutorial and have the Brand endpoints running.
8
+ > **INFO:** This guide assumes you've completed the [API](api.md) tutorial and have the Brand endpoints running.
9
9
 
10
10
  ## What We're Building
11
11
 
@@ -115,7 +115,7 @@ const full = await client.products.get(
115
115
 
116
116
  ### Filtering Products by Brand
117
117
 
118
- Ransack predicates work on whitelisted attributes and associations. The [Store API tutorial](store-api.md) shows how to register `brand_id` and `brand` via `Spree.ransack` — once that's done, you can filter:
118
+ Ransack predicates work on whitelisted attributes and associations. The [API tutorial](api.md) shows how to register `brand_id` and `brand` via `Spree.ransack` — once that's done, you can filter:
119
119
 
120
120
  ```typescript
121
121
  // Products from a specific brand
@@ -164,6 +164,7 @@ products.data.forEach(p => {
164
164
 
165
165
  ## Related Documentation
166
166
 
167
- - [Store API Tutorial](store-api.md) - Creating the Brand API endpoints
167
+ - [API Tutorial](api.md) - Creating the Brand API endpoints
168
168
  - [SDK Overview](/sdk) - Full SDK documentation
169
169
  - [Search & Filtering](../core-concepts/search-filtering.md) - Ransack predicates and sorting
170
+ - [Agentic Development](../agentic/overview.md) - Agent skills and the docs MCP server cover the SDK patterns used here
@@ -7,30 +7,35 @@ Automated testing is a crucial part of the development process. It helps you ens
7
7
  Spree uses [RSpec](https://rspec.info), [Factory Bot](https://github.com/thoughtbot/factory_bot_rails), and [Capybara](https://github.com/teamcapybara/capybara) for testing.
8
8
  We also provide the `spree_dev_tools` gem that helps you write Spree-specific tests.
9
9
 
10
- > **INFO:** This guide assumes you've completed all previous tutorials through [Store API](store-api.md). You should have a complete `Spree::Brand` model with admin features and API endpoints.
10
+ > **INFO:** This guide assumes you've completed all previous tutorials through [API](api.md). You should have a complete `Spree::Brand` model with admin features and API endpoints.
11
11
 
12
12
  ## Setup
13
13
 
14
- ### Step 1: Set RSpec as the Test Framework
14
+ **If your app came from [create-spree-app](../create-spree-app/quickstart.md) or [spree-starter](https://github.com/spree/spree-starter), the test environment is already set up** — RSpec, Factory Bot, Capybara, DatabaseCleaner, and the `spree_dev_tools` helpers (`stub_authorization!`, the `'API v3 Store'` shared context, Spree factories) ship preconfigured in `spec/support/`. Skip to creating the fixtures file below.
15
15
 
16
- ```bash
17
- bin/rails g rspec:install
18
- ```
16
+ <details>
17
+ <summary>Setting up an app that doesn't have RSpec yet</summary>
19
18
 
20
- ### Step 2: Run the spree\_dev\_tools Generator
19
+ For an existing Rails app without test setup, install RSpec and the Spree test helpers:
21
20
 
22
- ```bash
21
+
22
+ ```bash Spree CLI (Docker)
23
+ spree generate rspec:install
24
+ spree generate spree_dev_tools:install
25
+ ```
26
+
27
+ ```bash Without Spree CLI
28
+ bin/rails g rspec:install
23
29
  bin/rails g spree_dev_tools:install
24
30
  ```
25
31
 
26
- This adds Spree-specific test helpers to your `spec/support/` directory, including:
27
32
 
28
- * Authorization helpers (`stub_authorization!`)
29
- * Factory Bot configuration
30
- * Capybara setup for feature tests
31
- * and more…
33
+ The `spree_dev_tools` generator adds the Spree-specific helpers to `spec/support/`: authorization helpers (`stub_authorization!`), Factory Bot configuration, Capybara setup for feature tests, and more.
34
+
35
+ </details>
32
36
 
33
- ### Step 3: Create the Fixtures Directory and File
37
+
38
+ ### Create the Fixtures Directory and File
34
39
 
35
40
  When writing tests that involve file attachments (like images, PDFs, etc.), you need fixture files that your factories can use. Here's how to set them up.
36
41
 
@@ -38,13 +43,11 @@ When writing tests that involve file attachments (like images, PDFs, etc.), you
38
43
  mkdir -p spec/fixtures/files && printf '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDATx\x9cc\xf8\x0f\x00\x00\x01\x01\x00\x05\x18\xd8N\x00\x00\x00\x00IEND\xaeB`\x82' > spec/fixtures/files/logo.png
39
44
  ```
40
45
 
41
- ### Step 4: Generate Test Files
46
+ ### What the generators already created
42
47
 
43
- ```bash
44
- bin/rails g rspec:model Spree::Brand
45
- ```
48
+ If you used `spree generate api_resource` in the [API step](api.md), you already have controller specs (`spec/controllers/spree/api/v3/store/brands_controller_spec.rb` and `…/admin/brands_controller_spec.rb`) and a factory (`spec/factories/spree/brand_factory.rb`). The sections below build the same things by hand — compare as you go, and keep whichever you prefer.
46
49
 
47
- This creates `spec/models/spree/brand_spec.rb`.
50
+ For the model spec, create `spec/models/spree/brand_spec.rb` — we'll fill it in below.
48
51
 
49
52
  ## Writing Factories
50
53
 
@@ -213,10 +216,11 @@ Controller tests verify that your endpoints respond correctly and perform the ex
213
216
 
214
217
  ### Store API Controller Tests
215
218
 
216
- Test the API endpoints we created in the [Store API tutorial](store-api.md). Store API tests use the `'API v3 Store'` shared context which sets up a store, publishable API key, and JWT tokens.
219
+ Test the API endpoints we created in the [API tutorial](api.md). Store API tests use the `'API v3 Store'` shared context which sets up a store, publishable API key, and JWT tokens — it ships in the `spree_api` gem, so require `spree/api/testing_support/v3/base` at the top of the spec.
217
220
 
218
221
  ```ruby spec/controllers/spree/api/v3/store/brands_controller_spec.rb
219
222
  require 'rails_helper'
223
+ require 'spree/api/testing_support/v3/base'
220
224
 
221
225
  RSpec.describe Spree::Api::V3::Store::BrandsController, type: :controller do
222
226
  render_views
@@ -320,6 +324,7 @@ Test that the custom Product serializer includes brand data:
320
324
 
321
325
  ```ruby spec/controllers/spree/api/v3/store/products_brand_spec.rb
322
326
  require 'rails_helper'
327
+ require 'spree/api/testing_support/v3/base'
323
328
 
324
329
  RSpec.describe Spree::Api::V3::Store::ProductsController, type: :controller do
325
330
  render_views
@@ -582,23 +587,35 @@ expect(page).to have_content('Success!')
582
587
 
583
588
  ## Running Tests
584
589
 
585
- ```bash
586
- # Run all tests
587
- bundle exec rspec
590
+ In the Docker flow the container's `DATABASE_URL` points at the development database, so tests need two overrides: a dedicated test database, and DatabaseCleaner's opt-in for non-localhost database hosts (its safeguard against cleaning a database it doesn't own). One-time test database setup:
588
591
 
589
- # Run specific test file
590
- bundle exec rspec spec/models/spree/brand_spec.rb
592
+ ```bash Spree CLI (Docker) — one-time setup
593
+ spree exec env RAILS_ENV=test DATABASE_URL=postgres://postgres@postgres:5432/spree_test bin/rails db:prepare
594
+ ```
591
595
 
592
- # Run specific test
593
- bundle exec rspec spec/models/spree/brand_spec.rb:15
596
+ Then run tests:
594
597
 
595
- # Run with documentation format
596
- bundle exec rspec --format documentation
597
598
 
598
- # Run only feature tests
599
- bundle exec rspec spec/features/
599
+ ```bash Spree CLI (Docker)
600
+ # Define once per shell (or add as an alias):
601
+ alias spree-rspec='spree exec env RAILS_ENV=test DATABASE_URL=postgres://postgres@postgres:5432/spree_test DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL=true bundle exec rspec'
602
+
603
+ spree-rspec # all tests
604
+ spree-rspec spec/models/spree/brand_spec.rb # specific file
605
+ spree-rspec spec/models/spree/brand_spec.rb:15 # specific test
606
+ spree-rspec --format documentation # documentation format
607
+ spree-rspec spec/features/ # only feature tests
608
+ ```
609
+
610
+ ```bash Without Spree CLI
611
+ bundle exec rspec # all tests
612
+ bundle exec rspec spec/models/spree/brand_spec.rb # specific file
613
+ bundle exec rspec spec/models/spree/brand_spec.rb:15 # specific test
614
+ bundle exec rspec --format documentation # documentation format
615
+ bundle exec rspec spec/features/ # only feature tests
600
616
  ```
601
617
 
618
+
602
619
  ## Best Practices
603
620
 
604
621
 
@@ -659,7 +676,7 @@ spec/
659
676
  * [Model Tutorial](model.md) - Creating the Brand model
660
677
  * [Admin Tutorial](admin.md) - Building the admin interface
661
678
  * [Extending Core Models](extending-models.md) - Connecting Brands to Products
662
- * [Store API Tutorial](store-api.md) - Creating Brand API endpoints
679
+ * [API Tutorial](api.md) - Creating Brand API endpoints
663
680
  * [RSpec Documentation](https://rspec.info/documentation/) - Official RSpec docs
664
681
  * [Factory Bot Documentation](https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md) - Factory Bot guide
665
682
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spree/docs",
3
- "version": "0.1.85",
3
+ "version": "0.1.86",
4
4
  "description": "Spree Commerce developer documentation for AI agents and local reference",
5
5
  "type": "module",
6
6
  "license": "CC-BY-4.0",
@@ -1,121 +0,0 @@
1
- ---
2
- title: File Uploads
3
- description: Learn how to add file uploads to the Brands feature
4
- ---
5
-
6
- > **INFO:** This guide assumes you've completed the [Model](model.md), [Admin](admin.md), and [Rich Text](rich-text.md) tutorials.
7
-
8
- In this tutorial, we'll add a logo image upload to our Brand model. Spree uses [Rails Active Storage](https://guides.rubyonrails.org/active_storage_overview.html) for handling file attachments, image processing, and storage.
9
-
10
- ## Step 1: Add Attachment to the Model
11
-
12
- First, let's add a logo attachment to the Brand model:
13
-
14
- ```ruby app/models/spree/brand.rb {3}
15
- module Spree
16
- class Brand < Spree::Base
17
- has_one_attached :logo
18
-
19
- # ... existing code ...
20
- end
21
- end
22
- ```
23
-
24
- ## Step 2: Permit the Attachment Attribute
25
-
26
- For the admin form to accept the file upload, we need to permit the `logo` attribute in the controller.
27
-
28
- Update your brands controller:
29
-
30
- ```ruby app/controllers/spree/admin/brands_controller.rb {10}
31
- module Spree
32
- module Admin
33
- class BrandsController < ResourceController
34
- private
35
-
36
- def permitted_resource_params
37
- params.require(:brand).permit(
38
- :name,
39
- :description,
40
- :logo
41
- )
42
- end
43
- end
44
- end
45
- end
46
- ```
47
-
48
- ## Step 3: Add File Upload Field to the Admin Form
49
-
50
- Now let's add the file upload field to the brand form. Spree provides a `spree_file_field` helper that handles everything including:
51
-
52
- - Drag and drop upload
53
- - Image preview
54
- - Direct upload to storage
55
- - Optional image cropping
56
-
57
- Update your brand form partial:
58
-
59
- ```erb app/views/spree/admin/brands/_form.html.erb {11-19}
60
- <div class="card mb-6">
61
- <div class="card-header">
62
- <h5 class="card-title"><%= Spree.t(:general_settings) %></h5>
63
- </div>
64
- <div class="card-body">
65
- <%= f.spree_text_field :name, required: true %>
66
- <%= f.spree_rich_text_area :description %>
67
- </div>
68
- </div>
69
-
70
- <div class="card mb-6">
71
- <div class="card-header">
72
- <h5 class="card-title"><%= Spree.t(:logo) %></h5>
73
- </div>
74
- <div class="card-body">
75
- <%= f.spree_file_field :logo, width: 300, height: 300 %>
76
- </div>
77
- </div>
78
- ```
79
-
80
- ### Add cropping functionality
81
-
82
- To enable cropping functionality, add the `crop: true` option to the `spree_file_field` helper.
83
-
84
- ## Step 4: Display the Logo in the Index Table
85
-
86
- Let's show a thumbnail of the brand logo in the admin index view.
87
-
88
- Update the table header partial:
89
-
90
- ```erb app/views/spree/admin/brands/_table_header.html.erb {2}
91
- <tr>
92
- <th><%= Spree.t(:logo) %></th>
93
- <th><%= Spree.t(:name) %></th>
94
- <th></th>
95
- </tr>
96
- ```
97
-
98
- Update the table row partial to display the logo:
99
-
100
- ```erb app/views/spree/admin/brands/_table_row.html.erb {3-12}
101
- <tr id="<%= spree_dom_id brand %>" class="cursor-pointer" data-controller="row-link">
102
- <td data-action="click->row-link#openLink" class="w-70">
103
- <div class="d-flex align-items-center gap-2">
104
- <% if brand.logo.attached? %>
105
- <%= spree_image_tag brand.logo, width: 48, height: 48, class: 'rounded' %>
106
- <% else %>
107
- <div class="bg-light rounded d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;">
108
- <%= icon('photo-off', class: 'text-muted') %>
109
- </div>
110
- <% end %>
111
- <span class="font-weight-bold"><%= brand.name %></span>
112
- </div>
113
- </td>
114
- <td data-action="click->row-link#openLink" class="w-20">
115
- <%= spree_date(brand.created_at) %>
116
- </td>
117
- <td class="actions w-10">
118
- <%= link_to_edit(brand, data: { row_link_target: :link, turbo_frame: '_top' }) if can? :edit, brand %>
119
- </td>
120
- </tr>
121
- ```
@@ -1,73 +0,0 @@
1
- ---
2
- title: Rich Text
3
- description: Learn how to add rich text content to the Brands feature using Action Text
4
- ---
5
-
6
- > **INFO:** This guide assumes you've completed the [Model](model.md) and [Admin](admin.md) tutorials.
7
-
8
- Our Brand model has a `name` attribute to store the brand name. However it's missing a description. That's because we're going to use [Action Text](https://guides.rubyonrails.org/action_text_overview.html) to handle the rich text content.
9
-
10
- ## Step 1: Add Action Text to the Model
11
-
12
- ```ruby app/models/spree/brand.rb {4-5}
13
- module Spree
14
- class Brand < Spree::Base
15
- # Action text for rich text content
16
- has_rich_text :description
17
-
18
- # ... other code ...
19
- end
20
- end
21
- ```
22
-
23
- You don't need to run any migrations, as we won't be adding any new columns to the `spree_brands` table. That's because [Action Text](https://guides.rubyonrails.org/action_text_overview.html) stores all the rich text content in a separate table called `action_text_rich_texts`.
24
-
25
- You can access the description content in code like this:
26
-
27
- ```ruby
28
- brand.description.to_s
29
- # => "<h1>Hello</h1><p>World</p>"
30
- ```
31
-
32
- Or if you prefer plain text:
33
-
34
- ```ruby
35
- brand.description.to_plain_text
36
- # => "Hello World"
37
- ```
38
-
39
- ## Step 2: Add a WYSIWYG editor to the Admin Dashboard
40
-
41
- In the Admin dashboard we want to use a WYSIWYG editor to add formatted text to the brand description. To do this, edit the `app/views/spree/admin/brands/_form.html.erb` file and add the following code:
42
-
43
- ```erb app/views/spree/admin/brands/_form.html.erb {4}
44
- <div class="card mb-6">
45
- <div class="card-body">
46
- <%= f.spree_text_field :name %>
47
- <%= f.spree_rich_text_area :description %>
48
- </div>
49
- </div>
50
- ```
51
-
52
- This will render a WYSIWYG editor to the brand description field in the Admin dashboard.
53
-
54
- ## Step 3: Update permitted parameters in controller
55
-
56
- To permit the `description` attribute to be saved, we need to update the permitted parameters in the controller file and add the following code:
57
-
58
- ```ruby app/controllers/spree/admin/brands_controller.rb {9}
59
- module Spree
60
- module Admin
61
- class BrandsController < ResourceController
62
- private
63
-
64
- def permitted_resource_params
65
- params.require(:brand).permit(
66
- :name,
67
- :description
68
- )
69
- end
70
- end
71
- end
72
- end
73
- ```