prato 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +938 -0
- data/lib/prato/configuration.rb +99 -0
- data/lib/prato/internal/active_record_version.rb +24 -0
- data/lib/prato/internal/join_helper.rb +48 -0
- data/lib/prato/internal/join_helper_legacy.rb +171 -0
- data/lib/prato/internal/lazy_loader_cache.rb +25 -0
- data/lib/prato/internal/pipeline/filtering.rb +277 -0
- data/lib/prato/internal/pipeline/pagination.rb +30 -0
- data/lib/prato/internal/pipeline/serializer.rb +87 -0
- data/lib/prato/internal/pipeline/sorting.rb +78 -0
- data/lib/prato/internal/query_executor.rb +105 -0
- data/lib/prato/internal/query_state.rb +90 -0
- data/lib/prato/internal/specification.rb +101 -0
- data/lib/prato/internal/specification_builder.rb +361 -0
- data/lib/prato/internal/sql_support.rb +118 -0
- data/lib/prato/query/and_filter.rb +13 -0
- data/lib/prato/query/default_parser.rb +148 -0
- data/lib/prato/query/field_resolver.rb +23 -0
- data/lib/prato/query/filter.rb +15 -0
- data/lib/prato/query/or_filter.rb +13 -0
- data/lib/prato/query/parameters.rb +17 -0
- data/lib/prato/query/sort.rb +14 -0
- data/lib/prato/table.rb +39 -0
- data/lib/prato/table_builder.rb +40 -0
- data/lib/prato/types/aggregate_column.rb +93 -0
- data/lib/prato/types/association_column.rb +37 -0
- data/lib/prato/types/direct_column.rb +27 -0
- data/lib/prato/types/expression_column.rb +38 -0
- data/lib/prato/types/ruby_column.rb +31 -0
- data/lib/prato/version.rb +5 -0
- data/lib/prato.rb +66 -0
- metadata +96 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
module Query
|
|
5
|
+
class Parameters
|
|
6
|
+
attr_reader :page, :per_page, :filters, :sorts, :fields
|
|
7
|
+
|
|
8
|
+
def initialize(page: nil, per_page: nil, filters: nil, sorts: nil, fields: nil)
|
|
9
|
+
@page = page
|
|
10
|
+
@per_page = per_page
|
|
11
|
+
@filters = filters
|
|
12
|
+
@sorts = sorts
|
|
13
|
+
@fields = fields
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/prato/table.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
class Table
|
|
5
|
+
def initialize(spec)
|
|
6
|
+
@spec = spec
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def page(scope, params = nil)
|
|
10
|
+
Internal::QueryExecutor.execute(
|
|
11
|
+
scope,
|
|
12
|
+
@spec,
|
|
13
|
+
raw_params: params,
|
|
14
|
+
paginated: true
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def full(scope, params = nil)
|
|
19
|
+
Internal::QueryExecutor.execute(
|
|
20
|
+
scope,
|
|
21
|
+
@spec,
|
|
22
|
+
raw_params: params,
|
|
23
|
+
paginated: false
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def batches(scope, params = nil, batch_size: 1000, &block)
|
|
28
|
+
return enum_for(:batches, scope, params, batch_size: batch_size) unless block
|
|
29
|
+
|
|
30
|
+
Internal::QueryExecutor.execute_in_batches(
|
|
31
|
+
scope,
|
|
32
|
+
@spec,
|
|
33
|
+
raw_params: params,
|
|
34
|
+
batch_size: batch_size,
|
|
35
|
+
&block
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
class TableBuilder
|
|
5
|
+
|
|
6
|
+
attr_reader :spec_builder
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@spec_builder = Internal::SpecificationBuilder.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def column(*args, **kwargs)
|
|
13
|
+
@spec_builder.inner_column(*args, **kwargs)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ruby_column(*args, **kwargs, &block)
|
|
17
|
+
@spec_builder.inner_ruby_column(*args, **kwargs, &block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def query_column(*args, **kwargs)
|
|
21
|
+
@spec_builder.inner_query_column(*args, **kwargs)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def section(id, &block)
|
|
25
|
+
raise ArgumentError, "Section requires a block" unless block_given?
|
|
26
|
+
raise ArgumentError, "Section block must not accept arguments" unless block.parameters.empty?
|
|
27
|
+
|
|
28
|
+
@spec_builder.inner_section(id, &block)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ruby_loader(id, **kwargs, &block)
|
|
32
|
+
@spec_builder.inner_ruby_loader(id, **kwargs, &block)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def configure(config = nil, **overrides)
|
|
36
|
+
resolved_config = Configuration.with_settings(config, **overrides)
|
|
37
|
+
@spec_builder.inner_config(resolved_config)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
module Types
|
|
5
|
+
class AggregateColumn
|
|
6
|
+
attr_reader :arel_node, :format, :filter
|
|
7
|
+
|
|
8
|
+
def initialize(aggregate_function, aggregate_accessor, format: nil, filter: nil)
|
|
9
|
+
@accessor = Array(aggregate_accessor)
|
|
10
|
+
@aggregate_function = aggregate_function
|
|
11
|
+
@format = format
|
|
12
|
+
@filter = filter
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def resolve_arel!(base_model, display_id)
|
|
16
|
+
association_path = @aggregate_function == :count ? @accessor : @accessor[0..-2]
|
|
17
|
+
aggregate_field = @aggregate_function == :count ? nil : @accessor[-1]
|
|
18
|
+
|
|
19
|
+
reflections = resolve_reflections(base_model, association_path)
|
|
20
|
+
base_table = base_model.arel_table
|
|
21
|
+
aliased_tables = reflections.each_with_index.map do |reflection, index|
|
|
22
|
+
Arel::Table.new(reflection.klass.table_name, as: "prato_agg_#{index}_#{reflection.klass.table_name}")
|
|
23
|
+
end
|
|
24
|
+
target_table = aliased_tables.last
|
|
25
|
+
|
|
26
|
+
subquery = target_table.project(aggregate_expression(target_table, @aggregate_function, aggregate_field))
|
|
27
|
+
|
|
28
|
+
(reflections.length - 1).downto(1) do |i|
|
|
29
|
+
ref = reflections[i]
|
|
30
|
+
source_table = aliased_tables[i - 1]
|
|
31
|
+
subquery = subquery.join(source_table).on(
|
|
32
|
+
association_condition(ref, source_table, aliased_tables[i])
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
first_ref = reflections.first
|
|
37
|
+
subquery = subquery.where(
|
|
38
|
+
association_condition(first_ref, base_table, aliased_tables.first)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
@arel_node = Arel::Nodes::Grouping.new(subquery)
|
|
42
|
+
@sql_alias = display_id.to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def sql_node_for(_scope)
|
|
46
|
+
@arel_node
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def select_node
|
|
50
|
+
Arel::Nodes::As.new(@arel_node, Arel.sql(@sql_alias))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def extract_value(record, _)
|
|
54
|
+
record[@sql_alias]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def resolve_reflections(base_model, path)
|
|
60
|
+
current_model = base_model
|
|
61
|
+
path.map do |assoc_name|
|
|
62
|
+
reflection = current_model.reflect_on_association(assoc_name)
|
|
63
|
+
raise ArgumentError, "Unknown association '#{assoc_name}' on #{current_model}" unless reflection
|
|
64
|
+
|
|
65
|
+
current_model = reflection.klass
|
|
66
|
+
reflection
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def association_condition(reflection, source_table, target_table)
|
|
71
|
+
if reflection.macro == :belongs_to
|
|
72
|
+
source_table[reflection.foreign_key].eq(
|
|
73
|
+
target_table[reflection.active_record_primary_key]
|
|
74
|
+
)
|
|
75
|
+
else
|
|
76
|
+
target_table[reflection.foreign_key].eq(
|
|
77
|
+
source_table[reflection.active_record_primary_key]
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def aggregate_expression(table, aggregate_function, aggregate_field)
|
|
83
|
+
case aggregate_function
|
|
84
|
+
when :count then Arel.star.count
|
|
85
|
+
when :sum then Arel::Nodes::NamedFunction.new("COALESCE", [table[aggregate_field].sum, 0])
|
|
86
|
+
when :avg then table[aggregate_field].average
|
|
87
|
+
when :min then table[aggregate_field].minimum
|
|
88
|
+
when :max then table[aggregate_field].maximum
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
module Types
|
|
5
|
+
class AssociationColumn
|
|
6
|
+
attr_reader :association_path, :format, :filter
|
|
7
|
+
|
|
8
|
+
def initialize(accessor, format: nil, filter: nil)
|
|
9
|
+
@association_path = accessor[0..-2].map(&:to_sym).freeze
|
|
10
|
+
@attribute_name = accessor[-1].to_sym
|
|
11
|
+
@format = format
|
|
12
|
+
@filter = filter
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def resolve_arel!(base_model, _display_id)
|
|
16
|
+
current_model = base_model
|
|
17
|
+
|
|
18
|
+
@association_path.each do |assoc_name|
|
|
19
|
+
reflection = current_model.reflect_on_association(assoc_name)
|
|
20
|
+
raise ArgumentError, "Unknown association '#{assoc_name}' on #{current_model}" unless reflection
|
|
21
|
+
|
|
22
|
+
current_model = reflection.klass
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def sql_node_for(scope)
|
|
27
|
+
table = Internal::SqlSupport.table_for(scope, @association_path)
|
|
28
|
+
table[@attribute_name]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def extract_value(record, _ruby_data)
|
|
32
|
+
target = @association_path.reduce(record) { |obj, assoc| obj&.public_send(assoc) }
|
|
33
|
+
target&.[](@attribute_name)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
module Types
|
|
5
|
+
class DirectColumn
|
|
6
|
+
attr_reader :format, :filter
|
|
7
|
+
|
|
8
|
+
def initialize(accessor, format: nil, filter: nil)
|
|
9
|
+
@attribute_name = accessor.is_a?(Array) ? accessor.first : accessor
|
|
10
|
+
@format = format
|
|
11
|
+
@filter = filter
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def resolve_arel!(base_model, _display_id)
|
|
15
|
+
@arel_node = base_model.arel_table[@attribute_name]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def sql_node_for(_scope)
|
|
19
|
+
@arel_node
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def extract_value(record, _ruby_data)
|
|
23
|
+
record[@attribute_name]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
module Types
|
|
5
|
+
class ExpressionColumn
|
|
6
|
+
attr_reader :arel_node, :format, :filter
|
|
7
|
+
|
|
8
|
+
def initialize(expression, format: nil, filter: nil)
|
|
9
|
+
@expression = expression
|
|
10
|
+
@format = format
|
|
11
|
+
@filter = filter
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def resolve_arel!(base_model, display_id)
|
|
15
|
+
expression_sql = if @expression.is_a?(Symbol)
|
|
16
|
+
base_model.public_send(@expression)
|
|
17
|
+
else
|
|
18
|
+
@expression
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
@sql_alias = display_id.to_s
|
|
22
|
+
@arel_node = Arel::Nodes::Grouping.new(Arel.sql(expression_sql))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def sql_node_for(_scope)
|
|
26
|
+
@arel_node
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def select_node
|
|
30
|
+
Arel::Nodes::As.new(@arel_node, Arel.sql(@sql_alias))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def extract_value(record, _)
|
|
34
|
+
record[@sql_alias]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Prato
|
|
4
|
+
module Types
|
|
5
|
+
class RubyColumn
|
|
6
|
+
attr_reader :loader, :filter, :includes
|
|
7
|
+
|
|
8
|
+
def initialize(loader, key:, filter: nil, includes: nil)
|
|
9
|
+
@loader = loader
|
|
10
|
+
@key = key || :id
|
|
11
|
+
@filter = filter
|
|
12
|
+
@includes = includes
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def extract_value(record, ruby_data)
|
|
16
|
+
key_value = case @key
|
|
17
|
+
when Proc
|
|
18
|
+
@key.call(record)
|
|
19
|
+
when Array
|
|
20
|
+
@key.reduce(record) { |obj, method| obj.public_send(method) }
|
|
21
|
+
when Symbol
|
|
22
|
+
record.public_send(@key)
|
|
23
|
+
else
|
|
24
|
+
@key
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
ruby_data[@loader]&.[](key_value)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/prato.rb
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "prato/version"
|
|
4
|
+
|
|
5
|
+
require_relative "prato/query/filter"
|
|
6
|
+
require_relative "prato/query/sort"
|
|
7
|
+
require_relative "prato/query/and_filter"
|
|
8
|
+
require_relative "prato/query/or_filter"
|
|
9
|
+
require_relative "prato/query/parameters"
|
|
10
|
+
require_relative "prato/query/field_resolver"
|
|
11
|
+
require_relative "prato/query/default_parser"
|
|
12
|
+
|
|
13
|
+
require_relative "prato/configuration"
|
|
14
|
+
|
|
15
|
+
require_relative "prato/types/association_column"
|
|
16
|
+
require_relative "prato/types/direct_column"
|
|
17
|
+
require_relative "prato/types/expression_column"
|
|
18
|
+
require_relative "prato/types/aggregate_column"
|
|
19
|
+
require_relative "prato/types/ruby_column"
|
|
20
|
+
|
|
21
|
+
require_relative "prato/internal/active_record_version"
|
|
22
|
+
require_relative "prato/internal/lazy_loader_cache"
|
|
23
|
+
|
|
24
|
+
if Prato::Internal::ActiveRecordVersion.legacy?
|
|
25
|
+
require_relative "prato/internal/join_helper_legacy"
|
|
26
|
+
else
|
|
27
|
+
require_relative "prato/internal/join_helper"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
require_relative "prato/internal/sql_support"
|
|
31
|
+
require_relative "prato/internal/query_state"
|
|
32
|
+
require_relative "prato/internal/specification"
|
|
33
|
+
require_relative "prato/internal/specification_builder"
|
|
34
|
+
|
|
35
|
+
require_relative "prato/internal/pipeline/filtering"
|
|
36
|
+
require_relative "prato/internal/pipeline/pagination"
|
|
37
|
+
require_relative "prato/internal/pipeline/serializer"
|
|
38
|
+
require_relative "prato/internal/pipeline/sorting"
|
|
39
|
+
|
|
40
|
+
require_relative "prato/table"
|
|
41
|
+
require_relative "prato/table_builder"
|
|
42
|
+
require_relative "prato/internal/query_executor"
|
|
43
|
+
|
|
44
|
+
module Prato
|
|
45
|
+
extend self
|
|
46
|
+
|
|
47
|
+
def table(base_model, &block)
|
|
48
|
+
raise ArgumentError, "Prato.table requires a block" unless block_given?
|
|
49
|
+
raise ArgumentError, "Prato.table block must not accept arguments" unless block.parameters.empty?
|
|
50
|
+
|
|
51
|
+
builder = TableBuilder.new
|
|
52
|
+
builder.instance_exec(&block)
|
|
53
|
+
|
|
54
|
+
spec = builder.spec_builder.build(base_model)
|
|
55
|
+
|
|
56
|
+
Table.new(spec)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def setup(&block)
|
|
60
|
+
if block_given?
|
|
61
|
+
Configuration.configure(&block)
|
|
62
|
+
else
|
|
63
|
+
Configuration.new
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: prato
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Valter Santos
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '5.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '5.0'
|
|
26
|
+
description: "Prato is a library that simplifies the backend code required to support
|
|
27
|
+
queryable data, \nby mapping parameters onto a table structure, \nallowing Prato
|
|
28
|
+
to invoke Active Record methods like `.where`, `.order`, `.joins`, `.pluck` and
|
|
29
|
+
others.\n\nThe immediate use case for this is fetching data for tables in the frontend,
|
|
30
|
+
\nand with a simple *Prato* table, it becomes trivial to provide any kind of filtering
|
|
31
|
+
/ sorting / pagination operations \nover an Active Record relation.\n"
|
|
32
|
+
email:
|
|
33
|
+
- valter@trecitano.com
|
|
34
|
+
executables: []
|
|
35
|
+
extensions: []
|
|
36
|
+
extra_rdoc_files: []
|
|
37
|
+
files:
|
|
38
|
+
- CHANGELOG.md
|
|
39
|
+
- LICENSE.txt
|
|
40
|
+
- README.md
|
|
41
|
+
- lib/prato.rb
|
|
42
|
+
- lib/prato/configuration.rb
|
|
43
|
+
- lib/prato/internal/active_record_version.rb
|
|
44
|
+
- lib/prato/internal/join_helper.rb
|
|
45
|
+
- lib/prato/internal/join_helper_legacy.rb
|
|
46
|
+
- lib/prato/internal/lazy_loader_cache.rb
|
|
47
|
+
- lib/prato/internal/pipeline/filtering.rb
|
|
48
|
+
- lib/prato/internal/pipeline/pagination.rb
|
|
49
|
+
- lib/prato/internal/pipeline/serializer.rb
|
|
50
|
+
- lib/prato/internal/pipeline/sorting.rb
|
|
51
|
+
- lib/prato/internal/query_executor.rb
|
|
52
|
+
- lib/prato/internal/query_state.rb
|
|
53
|
+
- lib/prato/internal/specification.rb
|
|
54
|
+
- lib/prato/internal/specification_builder.rb
|
|
55
|
+
- lib/prato/internal/sql_support.rb
|
|
56
|
+
- lib/prato/query/and_filter.rb
|
|
57
|
+
- lib/prato/query/default_parser.rb
|
|
58
|
+
- lib/prato/query/field_resolver.rb
|
|
59
|
+
- lib/prato/query/filter.rb
|
|
60
|
+
- lib/prato/query/or_filter.rb
|
|
61
|
+
- lib/prato/query/parameters.rb
|
|
62
|
+
- lib/prato/query/sort.rb
|
|
63
|
+
- lib/prato/table.rb
|
|
64
|
+
- lib/prato/table_builder.rb
|
|
65
|
+
- lib/prato/types/aggregate_column.rb
|
|
66
|
+
- lib/prato/types/association_column.rb
|
|
67
|
+
- lib/prato/types/direct_column.rb
|
|
68
|
+
- lib/prato/types/expression_column.rb
|
|
69
|
+
- lib/prato/types/ruby_column.rb
|
|
70
|
+
- lib/prato/version.rb
|
|
71
|
+
homepage: https://prato.trecitano.com/
|
|
72
|
+
licenses:
|
|
73
|
+
- MIT
|
|
74
|
+
metadata:
|
|
75
|
+
allowed_push_host: https://rubygems.org
|
|
76
|
+
homepage_uri: https://prato.trecitano.com/
|
|
77
|
+
source_code_uri: https://github.com/trecitano/prato
|
|
78
|
+
changelog_uri: https://github.com/trecitano/prato/releases
|
|
79
|
+
rdoc_options: []
|
|
80
|
+
require_paths:
|
|
81
|
+
- lib
|
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - ">="
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: 2.4.0
|
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
|
+
requirements:
|
|
89
|
+
- - ">="
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: '0'
|
|
92
|
+
requirements: []
|
|
93
|
+
rubygems_version: 4.0.6
|
|
94
|
+
specification_version: 4
|
|
95
|
+
summary: Filter, sort, and paginate Active Record queries from a table definition.
|
|
96
|
+
test_files: []
|