Skip to content

Commit

Permalink
Massive overhaul to responder and adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
voltechs committed Jan 24, 2017
1 parent 94aa4f2 commit b563c9c
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 171 deletions.
2 changes: 1 addition & 1 deletion data_tables-responder.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']

spec.add_dependency 'active_model_serializers', '~> 0.10.0'
spec.add_dependency 'active_model_serializers', '~> 0.10.4'
spec.add_dependency 'count_estimate'

spec.add_development_dependency 'bundler', '~> 1.12'
Expand Down
11 changes: 0 additions & 11 deletions lib/data_tables-responder.rb

This file was deleted.

43 changes: 43 additions & 0 deletions lib/data_tables/active_model_serializers/adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
require 'active_model_serializers'

module DataTables
module ActiveModelSerializers
class Adapter < ::ActiveModelSerializers::Adapter::Json
extend ActiveSupport::Autoload
autoload :Pagination
autoload :Meta

def serializable_hash(options = nil)
options = serialization_options(options)

serialized_hash = {
data: ::ActiveModelSerializers::Adapter::Attributes.new(serializer, instance_options).serializable_hash(options)
}
serialized_hash[meta_key] = meta unless meta.blank?
serialized_hash.merge!(pagination) unless pagination.blank?

self.class.transform_key_casing!(serialized_hash, instance_options)
end

def meta_key
instance_options.fetch(:meta_key, 'meta'.freeze)
end

protected

def pagination
Pagination.new(serializer).as_h
end

def meta
{
sql: serializer.object.to_sql
}.merge(instance_options.fetch(:meta, {}))
# }.merge(Meta.new(@serializer))
end
end
end
end

# Register adapter manually (due to namespacing)
ActiveModelSerializers::Adapter.register(:dt, DataTables::ActiveModelSerializers::Adapter)
28 changes: 28 additions & 0 deletions lib/data_tables/active_model_serializers/adapter/meta.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module ActiveModelSerializers
module Adapter
class DataTables

class Meta
def initialize(serializer)
@object = serializer.object
@scope = serializer.scope

# Use the return value of the block unless it is nil.
if serializer._meta.respond_to?(:call)
@value = instance_eval(&serializer._meta)
else
@value = serializer._meta
end
end

def as_json
@value
end

protected

attr_reader :object, :scope
end
end
end
end
22 changes: 22 additions & 0 deletions lib/data_tables/active_model_serializers/adapter/pagination.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module DataTables
module ActiveModelSerializers
class Adapter
class Pagination

attr_reader :collection

def initialize(serializer)
@collection = serializer.object
end

def as_h
{
recordsTotal: collection&.total_entries&.to_i,
recordsFiltered: @collection&.unscope(:limit, :offset)&.count_estimate&.to_i
}
end

end
end
end
end
56 changes: 56 additions & 0 deletions lib/data_tables/active_model_serializers/register_dt_renderer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# In controllers, use `render dt: model` rather than `render json: model, adapter: :dt`.
#
# For example, in a controller action, we can:
# respond_to do |format|
# format.dt { render dt: model }
# end
#
# or
#
# render dt: model
#
# No wrapper format needed as it does not apply (i.e. no `wrap_parameters format: [dt]`)
module DataTables
module ActiveModelSerializers
MEDIA_TYPE = 'application/json'.freeze
HEADERS = {
response: { 'CONTENT_TYPE'.freeze => MEDIA_TYPE },
request: { 'ACCEPT'.freeze => MEDIA_TYPE }
}.freeze

def self.install
# actionpack/lib/action_dispatch/http/mime_types.rb
Mime::Type.register_alias MEDIA_TYPE, :dt, %w( text/plain text/x-json application/jsonrequest application/dt application/datatable )

# if Rails::VERSION::MAJOR >= 5
# ActionDispatch::Request.parameter_parsers[:dt] = parser
# else
# ActionDispatch::ParamsParser::DEFAULT_PARSERS[Mime[:dt]] = parser
# end

::ActionController::Renderers.add :dt do |json, options|
json = serialize_dt(json, options).to_json(options) unless json.is_a?(String)
self.content_type ||= Mime[:dt]
self.response_body = json
end
end

module ControllerSupport
def serialize_dt(resource, options)
options[:adapter] = :dt
options.fetch(:serialization_context) do
options[:serialization_context] = ::ActiveModelSerializers::SerializationContext.new(request)
end
# Magic happens here
resource = DataTables::Responder.respond(resource, request.params)
get_serializer(resource, options)
end
end
end
end

DataTables::ActiveModelSerializers.install

ActiveSupport.on_load(:action_controller) do
include DataTables::ActiveModelSerializers::ControllerSupport
end
100 changes: 0 additions & 100 deletions lib/data_tables/adapter.rb

This file was deleted.

21 changes: 6 additions & 15 deletions lib/data_tables/modules/pagination.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
require 'count_estimate'

module DataTables
module Modules
class Pagination
MissingSerializationContextError = Class.new(KeyError)
FIRST_PAGE = 1

attr_reader :collection, :context

def initialize(collection, adapter_options)
def initialize(collection, request_parameters)
@collection = collection
@adapter_options = adapter_options
@context = adapter_options.fetch(:serialization_context) do
fail MissingSerializationContextError, <<-EOF.freeze
Datatables::Pagination requires a ActiveModelSerializers::SerializationContext.
Please pass a ':serialization_context' option or
override CollectionSerializer#paginated? to return 'false'.
EOF
end
@request_parameters = request_parameters
end

def paginate
start = (request_parameters[:start] || '0').to_i
length = (request_parameters[:length] || '10').to_i
start = (@request_parameters[:start] || '0').to_i
length = (@request_parameters[:length] || '10').to_i
page = (start / length) + 1
@collection = @collection.paginate(page: page, per_page: length, total_entries: records_total)
end
Expand All @@ -46,9 +40,6 @@ def records_filtered

private

def request_parameters
@request_parameters ||= context.request_parameters
end
end
end
end
26 changes: 7 additions & 19 deletions lib/data_tables/modules/search.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
module DataTables
module Modules
class Search
MissingSerializationContextError = Class.new(KeyError)

attr_reader :collection, :context

def initialize(collection, adapter_options)
def initialize(collection, request_parameters)
@collection = collection
@adapter_options = adapter_options
@context = adapter_options.fetch(:serialization_context) do
fail MissingSerializationContextError, <<-EOF.freeze
Datatables::Search requires a ActiveModelSerializers::SerializationContext.
Please pass a ':serialization_context' option or
override CollectionSerializer#searchable? to return 'false'.
EOF
end
@request_parameters = request_parameters
end

def search
default_search = request_parameters.dig(:search, :value)
default_search = @request_parameters.dig(:search, :value)

model = @collection.try(:model) || @collection
arel_table = model.arel_table
columns = searchable_columns(default_search)

searches = DataTables.flat_keys_to_nested columns
searches = DataTables::Responder.flat_keys_to_nested columns

search_by = build_search(model, searches)

Expand All @@ -42,11 +34,11 @@ def build_search(model, searches)
assoc = model.reflect_on_association(column)
assoc_klass = assoc.klass

outer_join = join_type.new(assoc_klass.arel_table,
join = join_type.new(assoc_klass.arel_table,
Arel::Nodes::On.new(
model.arel_table[assoc.foreign_key].eq(assoc_klass.arel_table[assoc.active_record_primary_key])
))
@collection = @collection.joins(outer_join)
@collection = @collection.joins(join)
queries << build_search(assoc_klass, query).reduce(:and)
else
col_s = column.to_s
Expand All @@ -73,7 +65,7 @@ def build_search(model, searches)

def searchable_columns(default_search)
@searchable_columns = {}
request_parameters[:columns]&.inject(@searchable_columns) do |a, b|
@request_parameters[:columns]&.inject(@searchable_columns) do |a, b|
if (b[:searchable] && b[:data].present?)
if ((value = b.dig(:search, :value).present? ? b.dig(:search, :value) : default_search).present?)
a[b[:data]] = value
Expand All @@ -87,10 +79,6 @@ def searchable_columns(default_search)

private

def request_parameters
@request_parameters ||= context.request_parameters
end

end
end
end
Loading

0 comments on commit b563c9c

Please sign in to comment.