Skip to content

Commit c340d6e

Browse files
committed
Update readme
1 parent ee15679 commit c340d6e

File tree

1 file changed

+106
-16
lines changed

1 file changed

+106
-16
lines changed

README.md

Lines changed: 106 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,50 @@ end
7070

7171
### Creating Loaders
7272

73-
Create loader classes to define how to fetch and map data from Shopify's GraphQL APIs:
73+
Create loader classes to define how to fetch and map data from Shopify's GraphQL APIs. There are two approaches: the new **attribute-based approach** (recommended) and the legacy **manual fragment approach**.
74+
75+
#### Attribute-Based Approach (Recommended)
76+
77+
Use the new `attribute` method to define GraphQL fields with automatic type coercion and fragment generation:
7478

7579
```ruby
7680
# For Admin API
7781
module ActiveShopifyGraphQL::Loaders::AdminApi
7882
class CustomerLoader < ActiveShopifyGraphQL::AdminApiLoader
79-
def fragment
80-
<<~GRAPHQL
81-
fragment CustomerFragment on Customer {
82-
id
83-
displayName
84-
defaultEmailAddress {
85-
emailAddress
86-
}
87-
createdAt
88-
}
89-
GRAPHQL
90-
end
83+
graphql_type "Customer"
84+
85+
# Define attributes with automatic GraphQL path inference and type coercion
86+
attribute :id, type: :string
87+
attribute :name, path: "displayName", type: :string
88+
attribute :email, path: "defaultEmailAddress.emailAddress", type: :string
89+
attribute :created_at, type: :datetime
90+
91+
# Custom transform example
92+
attribute :tags, type: :string, transform: ->(tags_array) { tags_array.join(", ") }
93+
94+
# The fragment and map_response_to_attributes are automatically generated!
95+
end
96+
end
97+
```
98+
99+
#### Manual Fragment Approach (Legacy)
100+
101+
For more complex scenarios or when you need full control over the GraphQL fragment:
102+
103+
```ruby
104+
# For Admin API
105+
module ActiveShopifyGraphQL::Loaders::AdminApi
106+
class CustomerLoader < ActiveShopifyGraphQL::AdminApiLoader
107+
graphql_type "Customer"
108+
109+
fragment <<~GRAPHQL
110+
id
111+
displayName
112+
defaultEmailAddress {
113+
emailAddress
114+
}
115+
createdAt
116+
GRAPHQL
91117

92118
def map_response_to_attributes(response_data)
93119
customer_data = response_data.dig("data", "customer")
@@ -104,6 +130,45 @@ module ActiveShopifyGraphQL::Loaders::AdminApi
104130
end
105131
```
106132

133+
#### Attribute Definition Options
134+
135+
The `attribute` method supports several options for flexibility:
136+
137+
```ruby
138+
attribute :name,
139+
path: "displayName", # Custom GraphQL path (auto-inferred if omitted)
140+
type: :string, # Type coercion (:string, :integer, :float, :boolean, :datetime)
141+
null: false, # Whether the attribute can be null (default: true)
142+
transform: ->(value) { value.upcase } # Custom transformation block
143+
```
144+
145+
**Auto-inference:** When `path` is omitted, it's automatically inferred by converting snake_case to camelCase (e.g., `display_name``displayName`).
146+
147+
**Nested paths:** Use dot notation for nested GraphQL fields (e.g., `"defaultEmailAddress.emailAddress"`).
148+
149+
**Type coercion:** Automatic conversion using ActiveModel types ensures type safety.
150+
151+
#### Customer Account API Example
152+
153+
The Customer Account API has different field names and doesn't require an ID for customer queries:
154+
155+
```ruby
156+
# For Customer Account API
157+
module ActiveShopifyGraphQL::Loaders::CustomerAccountApi
158+
class CustomerLoader < ActiveShopifyGraphQL::CustomerAccountApiLoader
159+
graphql_type "Customer"
160+
161+
# Customer Account API uses different field names
162+
attribute :id, type: :string
163+
attribute :name, path: "firstName", type: :string
164+
attribute :last_name, path: "lastName", type: :string
165+
attribute :email, path: "emailAddress.emailAddress", type: :string
166+
attribute :phone, path: "phoneNumber.phoneNumber", type: :string, null: true
167+
attribute :created_at, path: "createdAt", type: :datetime
168+
end
169+
end
170+
```
171+
107172
### Finding Records
108173

109174
Use the `find` method to retrieve records by ID:
@@ -134,6 +199,28 @@ customer = Customer.with_customer_account_api(token).find
134199
customer = Customer.with_admin_api.find(id)
135200
```
136201

202+
### Querying Records
203+
204+
Use the `where` method to query multiple records using Shopify's search syntax:
205+
206+
```ruby
207+
# Simple conditions
208+
customers = Customer.where(email: "john@example.com")
209+
customers = Customer.where(first_name: "John", country: "Canada")
210+
211+
# Range queries
212+
customers = Customer.where(created_at: { gte: "2024-01-01", lt: "2024-02-01" })
213+
customers = Customer.where(orders_count: { gte: 5 })
214+
215+
# Multi-word values are automatically quoted
216+
customers = Customer.where(first_name: "John Doe")
217+
218+
# With custom loader and limits
219+
customers = Customer.where({ email: "john@example.com" }, loader: custom_loader, limit: 100)
220+
```
221+
222+
The `where` method automatically converts Ruby conditions into Shopify's GraphQL query syntax and validates that the query fields are supported by Shopify.
223+
137224
## Associations
138225

139226
ActiveShopifyGraphQL provides ActiveRecord-like associations to define relationships between the Shopify native models and your own custom ones.
@@ -167,7 +254,7 @@ end
167254
#### Using the Association
168255

169256
```ruby
170-
customer = Customer.find("gid://shopify/Customer/123456789")
257+
customer = Customer.find("gid://shopify/Customer/123456789") # or Customer.find(123456789)
171258

172259
# Access associated orders (lazy loaded)
173260
customer.rewards
@@ -191,16 +278,19 @@ The associations automatically handle Shopify GID format conversion, extracting
191278

192279
## Next steps
193280

194-
- [ ] Support `Model.where(param: value)` proxying params to the GraphQL query attribute
281+
- [x] Support `Model.where(param: value)` proxying params to the GraphQL query attribute
195282
- [ ] Eager loading of GraphQL connections via `Customer.includes(:orders).find(id)` in a single GraphQL query
283+
- [ ] Better error handling and retry mechanisms for GraphQL API calls
284+
- [ ] Caching layer for frequently accessed data
285+
- [ ] Support for GraphQL subscriptions
196286

197287
## Development
198288

199289
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
200290

201291
## Contributing
202292

203-
Bug reports and pull requests are welcome on GitHub at https://github.com/team-cometeer/active_shopify_graphql.
293+
Bug reports and pull requests are welcome on GitHub at https://github.com/nebulab/active_shopify_graphql.
204294

205295
## License
206296

0 commit comments

Comments
 (0)