client-data-adapter
Table of Contents
- Introduction
- Install
- Usage
define_adapteradapter-
with- Merge Methods
- Pass Arguments
- Use Return
- Read Methods Inside
link_onelink_many
Introduction
For unify data formats to transfer to clients.
Install
gem install client-data-adapteror in Gemfile
gem 'client-data-adapter'Usage
define_adapter
Include library to model and use define_adapter to define the adapter.
# book.rb
include ClientDataAdapter
define_adapter do
# define your adapter here.
# ...
endadapter
adapter method define the main adapter, should return a Hash.
# ...
define_adapter do
adapter do
{
id: id,
title: title,
}
end
endIn elsewhere
# ...
@book = Book.new(id: 1, title: 'My Book')
@book.adapter # => { id: 1, title: 'My Book' } with
And you probably need some complex calculation or related some other class, they maybe need some cost and is unnecessary to load everywhere.
So we need use them on-demand.
# ...
define_adapter do
adapter do
{
id: id,
title: title,
}
end
with :my_complex_calc do
'something complex'
end
endThen
# ...
@book = Book.new(id: 1, title: 'My Book')
@book.adapter(:my_complex_calc)
# => { id: 1, title: 'My Book', my_complex_calc: 'something complex' }Merge Methods
And you can merge any instance method of original class to the adapter result, such as
# book.rb
def full_title
"<#{title}>"
endThen you can use adapter like this
# ...
@book.adapter(:full_title)
# => { id: 1, title: 'My Book', full_title: '<My Book>' }It will set the method name as the key, and returns as the value.
But notice that if method name is repeated, will trigger the one inside the adapter.
Pass Arguments
Sometimes we need pass some arguments to deal different case, you can write like this
@book.adapter(foo: [:bar, :baz])Arguments with Hash will consider the key as the method name,
and values as arguments.
To work with the method like this
def foo(*args)
args.join(',')
endor this
with :foo do |*args|
args.join(',')
endThe result will be
@book.adapter(foo: [:bar, :baz])
# => { id: 1, title: 'My Book', foo: 'bar,baz' }Use Return
You can use return in adapter block to flow control.
# ...
with :id do
return 'i have no id' unless id
id
endIt is works.
Read Methods Inside
If you define something inside the adapter, you can't read it directly.
# book.rb
define_adapter do
# ...
with :my_method do
'invoke me please!'
end
end@book.my_method # => ERROR! No MethodSince that adapter differentiate the namespace with the original class to make naming more flexible.
It create a wrapper for the adapter named AdapterWrapper,
and exposed by the instance method adapter_wrapper.
@book.adapter_wrapper.class # => Book::AdapterWrapperAnd you can read the adapter internal method via it.
@book.adapter_wrapper.my_method # => workshmm... but i'm not very recommend you to use it by this way, if you need some method works alone, maybe you should define it in the original class.
link_one
This method is a syntactic sugar of with, seems like
with :my_link do |*args|
my_link.adapter(*args)
endis equal with
link_one :my_linkIt usual used in one-to-one relationship like belongs_to in rails.
For example
# book.rb
belongs_to :book_shelf
define_adapter do
link_one :book_shelf
# ...
end# book_shelf.rb
define_adapter do
adapter do
{
id: id,
desc: desc,
}
end
endThen
@book.adapter(:book_shelf)
# => { id: 1, title: 'My Book', book_shelf: @book.book_shelf.adapter }Of course you can pass some arguments, and if you have several links, can also used in nested.
# ...
@book.adapter(book_shelf: [:foo, library: :bar])
# => { ..., book_shelf: { ..., foo: ..., library: { ..., bar: ... } } }And can define many links once.
# ...
link_one :my_link1, :my_link2link_many
Okay, this method is similar with link_one but multiple.
If use with to implement likes
with :my_links do |*args|
my_links.map { |link| link.adapter(*args) }
endUsual used in one-to-many relationship, such as has_many in rails.
For example
# book.rb
has_many :categories
define_adapter do
link_many :categories
# ...
end@book.adapter(:categories)
# => { id: 1, title: 'My Book', categories: @book.categories.map(&:adapter) }Support multiple arguments and other usage, detail above.