JSON serialization of ActiveRecord models and colections (relations or array of objects). Also can serialzie any Array or Hash with minimal syntax.
Add this line to your application's Gemfile:
gem 'fars'
And then execute:
$ bundle
Or install it yourself as:
$ gem install fars
class Customer < ActiveRecord::Base
has_many :orders
endCreate serializer class named CustomerSerializer or V1::CustomerSerializer
class CustomerSerializer < Fars::BaseModelSerializer
attributes :id, :name, :data, # attrs
:created_at, :updated_at, # methods
:orders # relations
def created_at
object.created_at.try(:strftime, "%F %H:%M")
end
def updated_at
object.updated_at.try(:strftime, "%F %H:%M")
end
# _metadata (optional)
def meta
abilities = [:update, :destroy].select { |a| scope.can?(a, object) }
{ abilities: abilities }
end
endThen you can call #serialize method on object
# Option :scope is optional, can be used for providing metadata.
Customer.first.serialize scope: current_userAvailable options are: :api_version, :serializer, :scope, :fields, :add_metadata, :root_key, :params.
Description of this options provided in next section.
customer = Customer.first
# whould be serizlized with CustomerSerializer class
customer.serialize
# whould be serizlized with V1::CustomerSerializer class
customer.serialize api_version: 'V1'
# whould be serizlized with V1::ExtendedCustomerSerializer class
customer.serialize api_version: 'V1', serializer: "ExtendedCustomerSerializer"You can specify model class and item root key in serializer:
class ExtendedCustomerSerializer < Fars::BaseModelSerializer
self.model = Customer
self.root_key = :client
endcustomers = Customer.where("1 = 1")
customers.serializeAvailable some options
customers.serialize
root_key: :clients, # collection root key, default whoud be :customers, false if omit
api_version: "V1", # namesapce of model serializer class
fields: [:id, :name, :updated_at], # array of needed fields
scope: current_user, # user or ability, can be used in serializer meta method
add_metadata: true, # add or not item metadata, default is true if serializer respond_to? :meta
serializer: "ExtendedCustomerSerializer", # custom model serializer class
class_name: "Client", # item model class (can construct serializer class name from it), useful for array of objects
metadata: { limit: 10, offset: 50 }, # collection metadata (:root_key cannot be omitted)
params: { format: 'long' } # any parameters, can be accessed in serializes classYou can override serializers #available_attributes method for providing dynamic attributes
depending on internal serializer's logic.
class CustomerSerializer < Fars::BaseModelSerializer
attributes :id, :name, :data, # attrs
:created_at, :updated_at, # methods
:orders # relations
def created_at
object.created_at.try(:strftime, "%F %H:%M")
end
def updated_at
object.updated_at.try(:strftime, "%F %H:%M")
end
def available_attributes
attributes = [:id, :name, :created_at, :updated_at, :orders]
attributes << :data if scope.can?(:view_data, object)
attributes
end
# _metadata (optional)
def meta
abilities = [:update, :destroy].select { |a| scope.can?(a, object) }
{ abilities: abilities }
end
endArray of instances can by serialized same as relation. In this case default collection's root_key will be constructed from first element class name (can't be empty array) or from povided class name (class_name option).
Provide root_key (false if omit) and serializer (proc, block or custom class)
array = %w{green blue grey}
# with proc
array.serialize root_key: :colors,
serializer: Proc.new { |c| { color: c }
# with block
array.serialize(root_key: :colors) { |c| { color: c } }
# with custom class
class ColorSerializer < Fars::BaseObjectSerializer
def as_json
{ color: object }
end
end
array.serialize(root_key: :colors, serializer: 'ColorSerializer')This will produce:
{ colors: [
{ color: 'green' },
{ color: 'blue' },
{ color: 'grey' }
] }.to_jsonProvide root_key (false if omit) and serializer (proc, block or custom class)
hash = {
'2014-01-01' => { visitors: 23, visits: 114 },
'2014-01-02' => { visitors: 27, visits: 217 }
}
# with proc
hash.serialize root_key: :stats,
serializer: Proc.new { |k, v| { day: k, visitors: v[:visitors] } })
# with block
hash.serialize root_key: :stats do |k, v|
{ day: k, visitors: v[:visitors] }
end
# with custom class
# object in this case is key-value pair
class StatSerializer < Fars::BaseObjectSerializer
def as_json
{ stat_key: object[0], stat_value: object[1] }
end
end
hash.serialize root_key: :stats, serializer: 'StatSerializer'This will produce:
{ stats: [
{ day: '2014-01-01', visitors: 23 },
{ day: '2014-01-02', visitors: 27 }
] }.to_jsonBook = Struct.new(:isbn, :title, :author, :price, :count)
b1 = Book.new('isbn1', 'title1', 'author1', 10, nil)
b2 = Book.new('isbn2', 'title2', 'author2', 20.0, 4)
b3 = Book.new('isbn3', 'title3', 'author3', 30.5, 7)
book = b1
books = [b1, b2, b3]
class BookSerializer < Fars::BaseObjectSerializer
attributes :isbn, :title, :author, # attrs
:price, :count # methods
def price
"%.2f" % object.price
end
def count
object.count.to_i
end
end
# serializes any object with appropriate serializer
BookSerializer.new(book, fields: [:isbn, :title, :price]).to_json
# => { book: { isbn: 'isbn1', title: 'title1', price: '10.00' } }.to_json
# serialize collection
books.serialize(root_key: :books, # can be resolved automatically for non empty array
serializer: 'BookSerializer', # can be resolved automatically for non empty array
fields: [:isbn, :title, :price]) # all by default
# => { books: [
# { book: { isbn: 'isbn1', title: 'title1', price: '10.00' } },
# { book: { isbn: 'isbn2', title: 'title2', price: '20.00' } },
# { book: { isbn: 'isbn3', title: 'title3', price: '30.50' } }
# ] }.to_json- Fork it ( http://github.com/Lightpower/fars/fork )
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request
