-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Hi.
Just wanted to pitch an idea and see what you think: I'm writing an integration gem for a public API. Like many JSON APIs it uses CamelCase for the key names that do not map cleanly to ruby attribute names. For example:
PriceInclVAT should map to price_incl_vat but the gem doesn't do any conversions, leaving you with two choices: roll your own or live with the weird attribute names.
I'd like to add the ability to convert key names when transforming to/from JSON. One way would be to just do a straight map, given at attribute declaration time:
require 'model_attribute'
class User
extend ModelAttribute
attribute :id, :integer, key: 'UserID'
attribute :paid, :boolean, key: 'Paid'
attribute :name, :string, key: 'UserName'
attribute :created_at, :time, key: 'RegistrationTime'
attribute :vat_schedule, :json, key: 'VATSchedule'
def initialize(attributes = {})
set_attributes(attributes)
end
end
or by assigning a conversion method
require 'model_attribute'
class User
extend ModelAttribute
attribute :id, :integer
attribute :paid, :boolean
attribute :name, :string
attribute :created_at, :time
attribute :vat_schedule, :json
def convert( key, export = false )
map = {
id: 'UserID',
paid: 'Paid',
name: 'UserName',
created_at: 'RegistrationTime',
vat_schedule: 'VATSchedule',
}
map.reverse! if export
map[ key ]
end
def initialize(attributes = {})
set_attributes(attributes)
end
end
Idealy you could do both, use the key directly if it exists and call the method if it doesn't.
require 'model_attribute'
class User
extend ModelAttribute
attribute :id, :integer, key: 'UserID'
attribute :paid, :boolean
attribute :name, :string, key: 'UserName'
attribute :created_at, :time, key: 'RegistrationTime'
attribute :vat_schedule, :json, key: 'VATSchedule'
def convert( key, export = false)
return key.to_s.capitalize unless export
'UserID'.gsub(/(.+[a-z])([A-Z])/, '\1_\2' ).downcase.to_sym
end
def initialize(attributes = {})
set_attributes(attributes)
end
end
Right now I use Virtus with a hand rolled version of the combined approach. I have a map and a generic method. If the key is in the map it's used else the method is run.
Would this be interesting for you? If so I can open a PR when I have something that we can discuss.