Skip to content

Commit 7b3cdff

Browse files
committed
Merge pull request #566 from reidab/patch-2
Move Routing section and add to README ToC
2 parents bf2705b + 6e816bf commit 7b3cdff

1 file changed

Lines changed: 153 additions & 152 deletions

File tree

README.md

Lines changed: 153 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ backed by ActiveRecord models or by custom objects.
3434
* [Handling Exceptions] (#handling-exceptions)
3535
* [Action Callbacks] (#action-callbacks)
3636
* [Serializer] (#serializer)
37+
* [Routing] (#routing)
3738
* [Configuration] (#configuration)
3839
* [Contributing] (#contributing)
3940
* [License] (#license)
@@ -1368,7 +1369,158 @@ JSONAPI::ResourceSerializer.new(PostResource, include: include_resources,
13681369
).serialize_to_hash(PostResource.new(post, nil))
13691370
```
13701371

1371-
#### Routing
1372+
#### Formatting
1373+
1374+
JR by default uses some simple rules to format (and unformat) an attribute for (de-)serialization. Strings and Integers are output to JSON
1375+
as is, and all other values have `.to_s` applied to them. This outputs something in all cases, but it is certainly not
1376+
correct for every situation.
1377+
1378+
If you want to change the way an attribute is (de-)serialized you have a couple of ways. The simplest method is to create a
1379+
getter (and setter) method on the resource which overrides the attribute and apply the (un-)formatting there. For example:
1380+
1381+
```ruby
1382+
class PersonResource < JSONAPI::Resource
1383+
attributes :name, :email, :last_login_time
1384+
1385+
# Setter example
1386+
def email=(new_email)
1387+
@model.email = new_email.downcase
1388+
end
1389+
1390+
# Getter example
1391+
def last_login_time
1392+
@model.last_login_time.in_time_zone(@context[:current_user].time_zone).to_s
1393+
end
1394+
end
1395+
```
1396+
1397+
This is simple to implement for a one off situation, but not for example if you want to apply the same formatting rules
1398+
to all DateTime fields in your system. Another issue is the attribute on the resource will always return a formatted
1399+
response, whether you want it or not.
1400+
1401+
##### Value Formatters
1402+
1403+
To overcome the above limitations JR uses Value Formatters. Value Formatters allow you to control the way values are
1404+
handled for an attribute. The `format` can be set per attribute as it is declared in the resource. For example:
1405+
1406+
```ruby
1407+
class PersonResource < JSONAPI::Resource
1408+
attributes :name, :email, :spoken_languages
1409+
attribute :last_login_time, format: :date_with_utc_timezone
1410+
1411+
# Getter/Setter for spoken_languages ...
1412+
end
1413+
```
1414+
1415+
A Value formatter has a `format` and an `unformat` method. Here's the base ValueFormatter and DefaultValueFormatter for
1416+
reference:
1417+
1418+
```ruby
1419+
module JSONAPI
1420+
class ValueFormatter < Formatter
1421+
class << self
1422+
def format(raw_value)
1423+
super(raw_value)
1424+
end
1425+
1426+
def unformat(value)
1427+
super(value)
1428+
end
1429+
...
1430+
end
1431+
end
1432+
end
1433+
1434+
class DefaultValueFormatter < JSONAPI::ValueFormatter
1435+
class << self
1436+
def format(raw_value)
1437+
case raw_value
1438+
when String, Integer
1439+
return raw_value
1440+
else
1441+
return raw_value.to_s
1442+
end
1443+
end
1444+
end
1445+
end
1446+
```
1447+
1448+
You can also create your own Value Formatter. Value Formatters must be named with the `format` name followed by
1449+
`ValueFormatter`, i.e. `DateWithUTCTimezoneValueFormatter` and derive from `JSONAPI::ValueFormatter`. It is
1450+
recommended that you create a directory for your formatters, called `formatters`.
1451+
1452+
The `format` method is called by the `ResourceSerializer` as is serializing a resource. The format method takes the
1453+
`raw_value` parameter. `raw_value` is the value as read from the model.
1454+
1455+
The `unformat` method is called when processing the request. Each incoming attribute (except `links`) are run through
1456+
the `unformat` method. The `unformat` method takes a `value`, which is the value as it comes in on the
1457+
request. This allows you process the incoming value to alter its state before it is stored in the model.
1458+
1459+
###### Use a Different Default Value Formatter
1460+
1461+
Another way to handle formatting is to set a different default value formatter. This will affect all attributes that do
1462+
not have a `format` set. You can do this by overriding the `default_attribute_options` method for a resource (or a base
1463+
resource for a system wide change).
1464+
1465+
```ruby
1466+
def default_attribute_options
1467+
{format: :my_default}
1468+
end
1469+
```
1470+
1471+
and
1472+
1473+
```ruby
1474+
class MyDefaultValueFormatter < JSONAPI::ValueFormatter
1475+
class << self
1476+
def format(raw_value)
1477+
case raw_value
1478+
when String, Integer
1479+
return raw_value
1480+
when DateTime
1481+
return raw_value.in_time_zone('UTC').to_s
1482+
else
1483+
return raw_value.to_s
1484+
end
1485+
end
1486+
end
1487+
end
1488+
```
1489+
1490+
This way all DateTime values will be formatted to display in the UTC timezone.
1491+
1492+
#### Key Format
1493+
1494+
By default JR uses dasherized keys as per the
1495+
[JSON API naming recommendations](http://jsonapi.org/recommendations/#naming). This can be changed by specifying a
1496+
different key formatter.
1497+
1498+
For example, to use camel cased keys with an initial lowercase character (JSON's default) create an initializer and add
1499+
the following:
1500+
1501+
```ruby
1502+
JSONAPI.configure do |config|
1503+
# built in key format options are :underscored_key, :camelized_key and :dasherized_key
1504+
config.json_key_format = :camelized_key
1505+
end
1506+
```
1507+
1508+
This will cause the serializer to use the `CamelizedKeyFormatter`. You can also create your own `KeyFormatter`, for
1509+
example:
1510+
1511+
```ruby
1512+
class UpperCamelizedKeyFormatter < JSONAPI::KeyFormatter
1513+
class << self
1514+
def format(key)
1515+
super.camelize(:upper)
1516+
end
1517+
end
1518+
end
1519+
```
1520+
1521+
You would specify this in `JSONAPI.configure` as `:upper_camelized`.
1522+
1523+
### Routing
13721524

13731525
JR has a couple of helper methods available to assist you with setting up routes.
13741526

@@ -1535,157 +1687,6 @@ phone_number_contact GET /phone-numbers/:phone_number_id/contact(.:format) co
15351687
15361688
```
15371689

1538-
#### Formatting
1539-
1540-
JR by default uses some simple rules to format (and unformat) an attribute for (de-)serialization. Strings and Integers are output to JSON
1541-
as is, and all other values have `.to_s` applied to them. This outputs something in all cases, but it is certainly not
1542-
correct for every situation.
1543-
1544-
If you want to change the way an attribute is (de-)serialized you have a couple of ways. The simplest method is to create a
1545-
getter (and setter) method on the resource which overrides the attribute and apply the (un-)formatting there. For example:
1546-
1547-
```ruby
1548-
class PersonResource < JSONAPI::Resource
1549-
attributes :name, :email, :last_login_time
1550-
1551-
# Setter example
1552-
def email=(new_email)
1553-
@model.email = new_email.downcase
1554-
end
1555-
1556-
# Getter example
1557-
def last_login_time
1558-
@model.last_login_time.in_time_zone(@context[:current_user].time_zone).to_s
1559-
end
1560-
end
1561-
```
1562-
1563-
This is simple to implement for a one off situation, but not for example if you want to apply the same formatting rules
1564-
to all DateTime fields in your system. Another issue is the attribute on the resource will always return a formatted
1565-
response, whether you want it or not.
1566-
1567-
##### Value Formatters
1568-
1569-
To overcome the above limitations JR uses Value Formatters. Value Formatters allow you to control the way values are
1570-
handled for an attribute. The `format` can be set per attribute as it is declared in the resource. For example:
1571-
1572-
```ruby
1573-
class PersonResource < JSONAPI::Resource
1574-
attributes :name, :email, :spoken_languages
1575-
attribute :last_login_time, format: :date_with_utc_timezone
1576-
1577-
# Getter/Setter for spoken_languages ...
1578-
end
1579-
```
1580-
1581-
A Value formatter has a `format` and an `unformat` method. Here's the base ValueFormatter and DefaultValueFormatter for
1582-
reference:
1583-
1584-
```ruby
1585-
module JSONAPI
1586-
class ValueFormatter < Formatter
1587-
class << self
1588-
def format(raw_value)
1589-
super(raw_value)
1590-
end
1591-
1592-
def unformat(value)
1593-
super(value)
1594-
end
1595-
...
1596-
end
1597-
end
1598-
end
1599-
1600-
class DefaultValueFormatter < JSONAPI::ValueFormatter
1601-
class << self
1602-
def format(raw_value)
1603-
case raw_value
1604-
when String, Integer
1605-
return raw_value
1606-
else
1607-
return raw_value.to_s
1608-
end
1609-
end
1610-
end
1611-
end
1612-
```
1613-
1614-
You can also create your own Value Formatter. Value Formatters must be named with the `format` name followed by
1615-
`ValueFormatter`, i.e. `DateWithUTCTimezoneValueFormatter` and derive from `JSONAPI::ValueFormatter`. It is
1616-
recommended that you create a directory for your formatters, called `formatters`.
1617-
1618-
The `format` method is called by the `ResourceSerializer` as is serializing a resource. The format method takes the
1619-
`raw_value` parameter. `raw_value` is the value as read from the model.
1620-
1621-
The `unformat` method is called when processing the request. Each incoming attribute (except `links`) are run through
1622-
the `unformat` method. The `unformat` method takes a `value`, which is the value as it comes in on the
1623-
request. This allows you process the incoming value to alter its state before it is stored in the model.
1624-
1625-
###### Use a Different Default Value Formatter
1626-
1627-
Another way to handle formatting is to set a different default value formatter. This will affect all attributes that do
1628-
not have a `format` set. You can do this by overriding the `default_attribute_options` method for a resource (or a base
1629-
resource for a system wide change).
1630-
1631-
```ruby
1632-
def default_attribute_options
1633-
{format: :my_default}
1634-
end
1635-
```
1636-
1637-
and
1638-
1639-
```ruby
1640-
class MyDefaultValueFormatter < JSONAPI::ValueFormatter
1641-
class << self
1642-
def format(raw_value)
1643-
case raw_value
1644-
when String, Integer
1645-
return raw_value
1646-
when DateTime
1647-
return raw_value.in_time_zone('UTC').to_s
1648-
else
1649-
return raw_value.to_s
1650-
end
1651-
end
1652-
end
1653-
end
1654-
```
1655-
1656-
This way all DateTime values will be formatted to display in the UTC timezone.
1657-
1658-
#### Key Format
1659-
1660-
By default JR uses dasherized keys as per the
1661-
[JSON API naming recommendations](http://jsonapi.org/recommendations/#naming). This can be changed by specifying a
1662-
different key formatter.
1663-
1664-
For example, to use camel cased keys with an initial lowercase character (JSON's default) create an initializer and add
1665-
the following:
1666-
1667-
```ruby
1668-
JSONAPI.configure do |config|
1669-
# built in key format options are :underscored_key, :camelized_key and :dasherized_key
1670-
config.json_key_format = :camelized_key
1671-
end
1672-
```
1673-
1674-
This will cause the serializer to use the `CamelizedKeyFormatter`. You can also create your own `KeyFormatter`, for
1675-
example:
1676-
1677-
```ruby
1678-
class UpperCamelizedKeyFormatter < JSONAPI::KeyFormatter
1679-
class << self
1680-
def format(key)
1681-
super.camelize(:upper)
1682-
end
1683-
end
1684-
end
1685-
```
1686-
1687-
You would specify this in `JSONAPI.configure` as `:upper_camelized`.
1688-
16891690
## Configuration
16901691

16911692
JR has a few configuration options. Some have already been mentioned above. To set configuration options create an

0 commit comments

Comments
 (0)