-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Products and variants documentation #2437
Changes from all commits
2ae124d
ffa2c82
1e99fd2
124f323
944fa53
69731eb
a74c091
1178983
b5d6d0c
a581055
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Multi-currency support | ||
|
||
`Spree::Price` objects track a price for a specific currency and variant | ||
combination. For example, if a variant is available for $15 USD or €7 EUR, that | ||
variant would have two `Spree::Price` objects associated with it (one for each | ||
currency). | ||
|
||
<!-- TODO: | ||
It looks like there are other circumstances where another a Spree::Price | ||
object would be created in regards to currency. For example, if you sell your | ||
products in EUR but sell them to multiple countries that have different VAT | ||
rates. | ||
--> | ||
|
||
If none of a product's `Spree::Variant`s have a price value for the site's | ||
configured currency, that product is not visible in the store frontend. | ||
|
||
You can see a variant's price in the store's configured currency by calling the | ||
`price` method on that instance: | ||
|
||
```ruby | ||
Spree::Variant.find(1).price | ||
# => 15.99 | ||
``` | ||
|
||
You can also call the `price` method on a `Spree::Product`. If you call the | ||
`price` method on a product, it gets the price of the product's master variant. | ||
|
||
For a list of all of the `Spree::Price`s associated with a product or variant, | ||
you can call the `prices` method on an instance of them: | ||
|
||
```ruby | ||
Spree::Product.find(1).prices | ||
# => [#<Spree::Price id: 2 ...] | ||
# [#<Spree::Price id: 3 ...] | ||
|
||
Spree::Variant.find(1).prices | ||
# => [#<Spree::Price id: 4 ...] | ||
# [#<Spree::Price id: 5 ...] | ||
``` | ||
|
||
<!-- TODO: | ||
Some of this article could be repurposed for a new section about Spree::Price. | ||
--> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# Overview of products and variants | ||
|
||
Products and variants are integral to Solidus. While the `Spree::Product` and | ||
`Spree::Variant` models depend on each other, it is important to understand how | ||
they are different: | ||
|
||
- `Spree::Product`s track the general information about a product. This includes | ||
the product description and the permalink where a customer would find the | ||
product listing on a store. If you sell a mug and a t-shirt, you would set up | ||
a separate product for each of them. | ||
- `Spree::Variant`s track the specific information about a variant of that | ||
product. For example, the variant provides the dimensions and weight. The | ||
variant provides the information required by orders and shipments. If you sell | ||
a red t-shirt and a green t-shirt, you could make each one a variant of your | ||
t-shirt product. Similarly, if all of your t-shirts come in small, medium, and | ||
large, then you would make additional variants for each of those: small green | ||
t-shirt, small red t-shirt, medium green t-shirt, medium red t-shirt, and | ||
so on. | ||
|
||
The rest of this article introduces essential information for using products and | ||
variants in Solidus. | ||
|
||
<!-- TODO: | ||
It might be worth diagramming how Spree::Products, Spree::Variants, | ||
and Spree::LineItems affect an order and how it's priced. | ||
--> | ||
|
||
## Products | ||
|
||
`Spree::Product`s track unique products within your store. If you sell a mug and | ||
a t-shirt, you would set up a product for each of them. | ||
|
||
If you have a number of items that are similar (like t-shirts that come in | ||
small, medium, and large sizes), you can create [variants](#variants) for a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This information should come first to provide context about the information listed above. |
||
single product instead of creating three separate products. | ||
|
||
You can categorize products using [taxonomies and | ||
taxons](#taxonomies-and-taxons). And, if you want to offer more extensive | ||
information about a single product, you can add custom [product | ||
properties](product-properties.md) for any product. | ||
|
||
## Variants | ||
|
||
`Spree::Variant`s track the unique properties of multiple similar products that | ||
you sell. For example, if you sell a red mug and a green mug that have many | ||
other properties in common, you could create a single product ("Mug") with two | ||
variants. | ||
|
||
Here are a few key points to note about variants: | ||
|
||
- If a product has more than one variant, all variants require an option type | ||
and option value. (For example, an option type of "Size" with the values | ||
"Small", "Medium", and "Large".) | ||
- Every product has a master variant. When additional variants are created, they | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A master variant is a complicated concept that should have additional information. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a link to more information about master variants here. It lives in the |
||
inherit properties from the master variant. The properties can be overridden | ||
by the variant's own unique values. See [Master variants][master-variants] for | ||
more information. | ||
- All product images are linked to a product's variants. Product images are | ||
either associated with a specific variant or can be used for all of the | ||
variants. | ||
|
||
For more information about variants, see the [Variants][variants] article. | ||
|
||
[master-variants]: variants.md#master-variants | ||
[variants]: variants.md | ||
|
||
## Taxonomies and taxons | ||
|
||
You can create categories for products using `Spree::Taxonomy`s and | ||
`Spree::Taxon`s. The following taxonomies are common in ecommerce stores: | ||
|
||
- Categories | ||
- Brands | ||
|
||
Where taxons act as subcategories to taxonomies: | ||
|
||
``` | ||
Categories | ||
|-- Luggage | ||
|-- Clothing | ||
|-- T-shirts | ||
|-- Socks | ||
|-- Shoes | ||
Brands | ||
|-- Adidas | ||
|-- Bentley | ||
|-- Calvin Klein | ||
``` | ||
|
||
Taxons become associated with products via the `Spree::Classification` model. | ||
|
||
For more detailed information about taxonomies and taxons, see the [Taxonomies | ||
and taxons](taxonomies-and-taxons.md) article. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Product images | ||
|
||
Product images belong to the `Spree::Image` model and belong to the variants of | ||
a product. Solidus handles the creation and storage of images using | ||
[Paperclip][paperclip-gem]. | ||
|
||
Take note of these product image properties: | ||
|
||
- `viewable_id`: The ID for the variant that this image is linked to. | ||
- `attachment_width` and `attachment_height`: The width and height of the | ||
original image that was uploaded. See the [Paperclip | ||
section](#paperclip-settings) of this article for more information about how | ||
Solidus resizes product images. | ||
- `position`: Sets the image's position in a list of images. For example, an | ||
image with the `position` of `2` would be displayed after the image with the | ||
`position` of `1`. | ||
- `alt`: The alt text for an image. Administrators can add this from the | ||
backend. | ||
|
||
## Fallback images | ||
|
||
Every product image is linked to the ID of a specific `Spree::Variant`. However, | ||
if the variant is a master variant (the variant's `is_master` property equals | ||
`true`) this image can be displayed as a fallback for other variants without | ||
images. | ||
|
||
If you want to change the image that is displayed when a product has no image, | ||
you can override Solidus's [`noimage` defaults][solidus-noimage] in your project | ||
by creating a `app/asets/images/noimages` directory. | ||
|
||
If you have changed your [Paperclip configuration](#paperclip-settings), make | ||
sure that you include `noimage` images for each of image attachment keys that | ||
you have defined. The default keys are `mini`, `small`, `product`, and `large`. | ||
|
||
## Images for all variants | ||
|
||
Administrators can upload images when adding or editing a product in the | ||
[`solidus_backend`][solidus-backend]. The images can be set to be displayed | ||
for a specific variant or for **All** variants. | ||
|
||
If set to **All**, the `viewable_id` is set to the master variant for the | ||
current product. | ||
|
||
## Paperclip settings | ||
|
||
[Paperclip][paperclip-gem] handles the creation and storage of product images. | ||
By default, it creates creates several version of each image at specific sizes. | ||
|
||
You can check the default settings by calling the `attachment_definitions` | ||
method on `Spree::Image` in your Rails console: | ||
|
||
```shell | ||
Spree::Image.attachment_definitions[:attachment][:styles] | ||
=> { | ||
mini=>"48x48>", | ||
small=>"100x100>", | ||
product=>"240x240>", | ||
large=>"600x600>" | ||
} | ||
``` | ||
|
||
The default sizes can be changed in an initializer. For example, in your | ||
`config/initializers/paperclip.rb` file. You can set new defaults like this: | ||
|
||
```ruby | ||
Spree::Image.attachment_definitions[:attachment][:styles] = { | ||
mini: '128x128>', | ||
small: '256x256>', | ||
product: '512x512>', | ||
large: '1024x1024>' | ||
} | ||
``` | ||
|
||
### Regenerate thumbnails | ||
|
||
If you change the default image sizes, you must regenerate the Paperclip | ||
thumbnails by running a Rake task: | ||
|
||
```shell | ||
bundle exec rake paperclip:refresh:thumbnails CLASS=Spree::Image | ||
``` | ||
|
||
[paperclip-gem]: https://github.com/thoughtbot/paperclip | ||
[solidus-backend]: https://github.com/solidusio/solidus/tree/master/backend | ||
[solidus-noimage]: https://github.com/solidusio/solidus/tree/master/core/app/assets/images/noimage |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Product properties | ||
|
||
Product properties belong to the `Spree::ProductProperty` model. They track | ||
individual attributes for a product that would not apply to all of your | ||
products. Typically, product properties would be used for additional product | ||
information. | ||
|
||
As an example, you might see a list of product properties for a limited edition | ||
t-shirt as a table on its product page: | ||
|
||
| Property name | Property value | | ||
|---------------|------------------| | ||
| Fit | Tapered | | ||
| Manufacturer | American Apparel | | ||
| Material | 100% cotton | | ||
|
||
You can retrieve the value for a property on a `Spree::Product` object by | ||
calling the `property` method on it and passing through that property's name: | ||
|
||
```shell | ||
Spree::Product.find(1).property("fit") | ||
=> "Tapered" | ||
``` | ||
|
||
You can set a property on a product by calling the `set_property` method: | ||
|
||
```ruby | ||
Spree::Product.find(1).set_property("fit", "Tapered") | ||
``` | ||
|
||
If this property doesn't already exist, a new `Property` instance with this name | ||
will be created. | ||
|
||
## Product properties are not option types | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good point and needs further detail. When should I use a property, and when should I use an option type? |
||
|
||
A product property should not be confused with an [option type][option-types], | ||
which is used to define variants for a product. | ||
|
||
Use product properties to describe a product: "The t-shirt is 100% cotton." Use | ||
option types to show how variants are distinct from each other: "The t-shirt can | ||
be purchased in one of two colors: red or green." | ||
|
||
[option-types]: variants.md#option-types |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Products | ||
|
||
`Spree::Product`s track separate products within your store. If you sell a mug | ||
and a t-shirt, you would set up a product for each of them. | ||
|
||
Products have the following attributes: | ||
|
||
- `name`: The short name for a product. | ||
- `description`: The full description for your product. | ||
- `slug`: An SEO-slug based on the product name. This slug is used in the | ||
product's URL. | ||
- `available_on`: The first date the product becomes available for sale online | ||
in your shop. If you don't set the `available_on` attribute, the product does | ||
not appear among your store's products for sale. | ||
- `deleted_at`: The date the product is no longer available for sale in the | ||
store. | ||
- `meta_description`: A description targeted at search engines for search engine | ||
optimization (SEO). This description is shown in search results and may be | ||
truncated after 160 characters. | ||
- `meta_keywords`: Comma-separated keywords and phrases related to the product, | ||
also targeted at search engines. | ||
- `meta_title`: Title to put in HTML `<title>` tag. If left blank, the product | ||
name is used instead. | ||
- `promotionable`: Determines whether or not promotions can apply to the | ||
product. (Labeled "Promotable" in the admin interface.) | ||
|
||
## Variants | ||
|
||
Most of Solidus's product-related business logic belongs to `Spree::Variant`s | ||
rather than products. This includes the product's price, dimensions, and product | ||
images. | ||
|
||
Even if your store only sells a single product that only comes in one size and | ||
color, that product would have a single variant that handles the additional | ||
properties. | ||
|
||
For more information about variants, see the [variants](variants.md) article. | ||
|
||
## Product properties | ||
|
||
You can also configure products to have [product | ||
properties](product-properties.md). Product properties allow you to add custom | ||
product information for a single product. | ||
|
||
A "Size" attribute would be used for many products and would be more useful as | ||
an [option type](variants.md#option-types) for variants. However, if you decide | ||
to sell a limited edition t-shirt you might want to add unique product | ||
properties for marketing purposes - like "Fit", "Material", and "Manufacturer". | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're talking about products and variants here using the same terms. I think it would be best to start with examples of cases where a product has variants, and what the product is and what the variant is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are very right. I've extended the products and variants bullet points here.