Created
March 23, 2012 01:17
-
-
Save Veejay/2165970 to your computer and use it in GitHub Desktop.
JSON Serializer built on top of Jbuilder with emphasis on ease of use
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module StaffPlan::JsonSerializer | |
def serialize(*args) | |
options = args.extract_options! | |
if args.first.is_a?(Array) or args.first.is_a?(ActiveRecord::Relation) | |
serialize_collection(args.first, options) | |
else | |
serialize_instance(args.first, options) | |
end | |
end | |
private | |
def serialize_instance(*args) | |
options = args.extract_options! | |
instance = args.first | |
Jbuilder.encode do |json| | |
json.extract! args.first, *filter_attributes(instance, options) | |
options.except(:only, :except).each do |k,v| | |
json.__send__ k.to_sym, ActiveSupport::JSON.decode(serialize(instance.send(k.to_sym), v)) | |
end | |
end | |
end | |
def serialize_collection(*args) | |
options = args.extract_options! | |
collection = case | |
when args.first.is_a?(ActiveRecord::Relation) | |
args.first.all | |
when args.first.is_a?(Array) | |
args.first | |
end | |
Jbuilder.encode do |json| | |
json.array! collection do |json, instance| | |
json.extract! instance, *filter_attributes(instance, options) | |
options.except(:only, :except).each do |k,v| | |
json.__send__ k.to_sym, ActiveSupport::JSON.decode(serialize(instance.send(k.to_sym), v)) | |
end | |
end | |
end | |
end | |
def filter_attributes(*args) | |
options = args.extract_options! | |
attributes = args.first.attributes.keys.map(&:to_sym) | |
timestamps = [:updated_at, :created_at] | |
case | |
when options.has_key?(:only) | |
options[:only] | |
when options.has_key?(:except) | |
attributes - options[:except] | |
else | |
args.first.attributes.keys.map(&:to_sym) | |
end - timestamps | |
end | |
end |
- Added support for except and all attributes
- Found out how to actually send a message to the builder. Turns out you need to send since Jbuilder inherits from BlankSlate.
- Made the two delegate methods and the convenience method filter_attributes private.
Still needs to be addressed:
- Don't like the case when in filter_attributes, it's an eye sore
- It's stupid to encode and decode all the time throughout the method (and it has a cost too)
- Support for scoping... Maybe with a syntax à la
serialize(@user, except: [:id], projects: {only: [:name, :active], work_weeks: {for: {:user, @user.id}, only: [:foobar]}})
or something... - Correct spelling mistakes automatically (typing project instead of projects) can be corrected through reflection on the association. Nice to have in the future.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What works well:
Nested relations with only as an option. Meaning you can get something like
What would be nice to have:
Adding an except option as well (blacklist instead of whitelist)Have a sensible default for when the user doesn't specify the fields he/she's interested in. Probably something like (attributes.keys - %w(updated_at created_at)).map(&:to_sym) that I could then pass to extract!foo = serialize ...; foo.target!