actionset 0.5.4 → 0.6.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 +4 -4
- data/actionset.gemspec +2 -3
- data/lib/action_set.rb +11 -12
- data/lib/action_set/attribute_value.rb +155 -0
- data/lib/action_set/helpers/pagination/total_pages_for_helper.rb +1 -1
- metadata +5 -6
- data/lib/action_set/instruction/value.rb +0 -154
- data/lib/action_set/version.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee8a50300e9e0918965a3c32ec78d1f740233add
|
4
|
+
data.tar.gz: 27789ef2fb5e1ff75f1a58ca0bc29c0f4d6fb938
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66d724b335536136cd5ac2efdcaf644cf9586ae7f837a51dbf9acf8da6042b664ad9a1da5307f3b8c9f8e6c8ac3e7d031199dc893ad7baf5c04856302435a554
|
7
|
+
data.tar.gz: 304690a7e523c824c230349eeced3bf0871adb9bcb98614cc538960982e564612f16a72301440df0ddf45c2ebb5935e31b903677d2ab6f71b6f8d70d32e56b9d
|
data/actionset.gemspec
CHANGED
@@ -2,11 +2,10 @@
|
|
2
2
|
|
3
3
|
lib = File.expand_path('../lib', __FILE__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require 'action_set/version'
|
6
5
|
|
7
6
|
Gem::Specification.new do |spec|
|
8
7
|
spec.name = 'actionset'
|
9
|
-
spec.version =
|
8
|
+
spec.version = '0.6.0'
|
10
9
|
spec.authors = ['Stephen Margheim']
|
11
10
|
spec.email = ['stephen.margheim@gmail.com']
|
12
11
|
|
@@ -22,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
22
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
22
|
spec.require_paths = ['lib']
|
24
23
|
|
25
|
-
spec.add_dependency 'activeset', '>= 0.
|
24
|
+
spec.add_dependency 'activeset', '>= 0.7.1'
|
26
25
|
spec.add_dependency 'activesupport', '>= 4.0.2'
|
27
26
|
spec.add_dependency 'railties'
|
28
27
|
|
data/lib/action_set.rb
CHANGED
@@ -5,8 +5,7 @@ require 'active_support/core_ext/object/blank'
|
|
5
5
|
require 'active_support/lazy_load_hooks'
|
6
6
|
require 'active_set'
|
7
7
|
|
8
|
-
|
9
|
-
require_relative './action_set/instruction/value'
|
8
|
+
require_relative './action_set/attribute_value'
|
10
9
|
require_relative './action_set/helpers/helper_methods'
|
11
10
|
|
12
11
|
module ActionSet
|
@@ -44,19 +43,19 @@ module ActionSet
|
|
44
43
|
def export_set(set)
|
45
44
|
return send_file(set, export_set_options(request.format)) if set.is_a?(String) && File.file?(set)
|
46
45
|
active_set = ensure_active_set(set)
|
47
|
-
|
48
|
-
send_data(
|
46
|
+
exported_data = active_set.export(export_structure)
|
47
|
+
send_data(exported_data, export_set_options(request.format))
|
49
48
|
end
|
50
49
|
|
51
50
|
private
|
52
51
|
|
53
52
|
def filter_structure(set)
|
54
53
|
filter_params.flatten_keys.reject { |_, v| v.blank? }.each_with_object({}) do |(keypath, value), memo|
|
55
|
-
instruction = ActiveSet::
|
54
|
+
instruction = ActiveSet::AttributeInstruction.new(keypath, value)
|
56
55
|
item_with_value = set.find { |i| !instruction.value_for(item: i).nil? }
|
57
56
|
item_value = instruction.value_for(item: item_with_value)
|
58
|
-
typecast_value =
|
59
|
-
|
57
|
+
typecast_value = ActionSet::AttributeValue.new(value)
|
58
|
+
.cast(to: item_value.class)
|
60
59
|
|
61
60
|
memo[keypath] = typecast_value
|
62
61
|
end
|
@@ -66,10 +65,10 @@ module ActionSet
|
|
66
65
|
paginate_params.transform_values(&:to_i)
|
67
66
|
end
|
68
67
|
|
69
|
-
def
|
68
|
+
def export_structure
|
70
69
|
{}.tap do |struct|
|
71
|
-
struct[:format] =
|
72
|
-
columns_params =
|
70
|
+
struct[:format] = export_params[:format] || request.format.symbol
|
71
|
+
columns_params = export_params[:columns]&.map do |column|
|
73
72
|
Hash[column&.map do |k, v|
|
74
73
|
is_literal_value = ->(key) { key.to_s == 'value*' }
|
75
74
|
key = is_literal_value.(k) ? 'value' : k
|
@@ -93,8 +92,8 @@ module ActionSet
|
|
93
92
|
params.fetch(:paginate, {}).to_unsafe_hash
|
94
93
|
end
|
95
94
|
|
96
|
-
def
|
97
|
-
params.fetch(:
|
95
|
+
def export_params
|
96
|
+
params.fetch(:export, {}).to_unsafe_hash
|
98
97
|
end
|
99
98
|
|
100
99
|
def export_set_options(format)
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionSet
|
4
|
+
class AttributeValue
|
5
|
+
attr_reader :raw
|
6
|
+
|
7
|
+
def initialize(value)
|
8
|
+
@raw = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def cast(to:)
|
12
|
+
adapters.reduce(nil) do |_, adapter|
|
13
|
+
mayble_value_or_nil = adapter.new(@raw, to).process
|
14
|
+
next if mayble_value_or_nil.nil?
|
15
|
+
return mayble_value_or_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
@raw
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def adapters
|
24
|
+
[ActiveModelAdapter, PlainRubyAdapter, BooleanAdapter, TimeWithZoneAdapter]
|
25
|
+
end
|
26
|
+
|
27
|
+
class PlainRubyAdapter
|
28
|
+
def initialize(raw, target)
|
29
|
+
@raw = raw
|
30
|
+
@target = target
|
31
|
+
end
|
32
|
+
|
33
|
+
def process
|
34
|
+
return @raw if @raw.is_a? @target
|
35
|
+
possible_values.find { |v| v.is_a? @target }
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def possible_values
|
41
|
+
possible_typecasters.map { |m| typecast(m) }
|
42
|
+
.compact
|
43
|
+
end
|
44
|
+
|
45
|
+
def possible_typecasters
|
46
|
+
@possible_typecasters ||= String.instance_methods
|
47
|
+
.map(&:to_s)
|
48
|
+
.select { |m| m.start_with? 'to_' }
|
49
|
+
.reject { |m| %[to_v8].include? m }
|
50
|
+
end
|
51
|
+
|
52
|
+
def typecast(method_name)
|
53
|
+
@raw.send(method_name)
|
54
|
+
rescue
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class ActiveModelAdapter
|
60
|
+
begin
|
61
|
+
require 'active_model/type'
|
62
|
+
rescue LoadError
|
63
|
+
require 'active_record/type'
|
64
|
+
end
|
65
|
+
|
66
|
+
def initialize(raw, target)
|
67
|
+
@raw = raw
|
68
|
+
@target = target
|
69
|
+
end
|
70
|
+
|
71
|
+
def process
|
72
|
+
return @raw if @raw.is_a? @target
|
73
|
+
possible_values.find { |v| v.is_a? @target }
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def possible_values
|
79
|
+
possible_typecasters.map { |m| typecast(m, @raw) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def possible_typecasters
|
83
|
+
@possible_typecasters ||= type_class.constants
|
84
|
+
.map(&:to_s)
|
85
|
+
.select { |t| can_typecast?(t) }
|
86
|
+
.reject { |t| t == 'Time' }
|
87
|
+
.map { |t| init_typecaster(t) }
|
88
|
+
.compact
|
89
|
+
end
|
90
|
+
|
91
|
+
def typecast(to_type, value)
|
92
|
+
return to_type.type_cast(value) if to_type.respond_to? :type_cast
|
93
|
+
to_type.cast(value)
|
94
|
+
end
|
95
|
+
|
96
|
+
def can_typecast?(const_name)
|
97
|
+
typecasting_class = type_class.const_get(const_name)
|
98
|
+
typecasting_class.instance_methods.include?(:cast) ||
|
99
|
+
typecasting_class.instance_methods.include?(:type_cast)
|
100
|
+
end
|
101
|
+
|
102
|
+
def init_typecaster(const_name)
|
103
|
+
type_class.const_get(const_name).new
|
104
|
+
rescue
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def type_class
|
109
|
+
ActiveModel::Type
|
110
|
+
rescue NameError
|
111
|
+
ActiveRecord::Type
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class BooleanAdapter
|
116
|
+
def initialize(raw, target)
|
117
|
+
@raw = raw
|
118
|
+
@target = target
|
119
|
+
end
|
120
|
+
|
121
|
+
def process
|
122
|
+
return if @raw.is_a? @target
|
123
|
+
return unless @target.eql?(TrueClass) || @target.eql?(FalseClass)
|
124
|
+
# ActiveModel::Type::Boolean is too expansive in its casting; will get false positives
|
125
|
+
to_bool
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def to_bool
|
131
|
+
return @raw if @raw.is_a?(TrueClass) || @raw.is_a?(FalseClass)
|
132
|
+
return true if %w[true yes 1 t].include? @raw.to_s.downcase
|
133
|
+
return false if %w[false no 0 f].include? @raw.to_s.downcase
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class TimeWithZoneAdapter
|
139
|
+
def initialize(raw, target)
|
140
|
+
@raw = raw
|
141
|
+
@target = target
|
142
|
+
end
|
143
|
+
|
144
|
+
def process
|
145
|
+
return if @raw.is_a? @target
|
146
|
+
return unless @target.eql?(ActiveSupport::TimeWithZone)
|
147
|
+
time_value = ActiveModelAdapter.new(@raw, Time).process
|
148
|
+
|
149
|
+
return unless time_value.is_a?(Time)
|
150
|
+
return time_value unless time_value.respond_to?(:in_time_zone)
|
151
|
+
time_value.in_time_zone
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -7,7 +7,7 @@ module Pagination
|
|
7
7
|
include Pagination::PageSizeForHelper
|
8
8
|
|
9
9
|
def pagination_total_pages_for(set)
|
10
|
-
total_set_size = set.
|
10
|
+
total_set_size = set.instructions.dig(:paginate, :count)
|
11
11
|
return 1 if total_set_size == 0
|
12
12
|
|
13
13
|
(total_set_size.to_f / pagination_page_size_for(set)).ceil
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionset
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Margheim
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activeset
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.7.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.7.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -227,6 +227,7 @@ files:
|
|
227
227
|
- bin/setup
|
228
228
|
- config.ru
|
229
229
|
- lib/action_set.rb
|
230
|
+
- lib/action_set/attribute_value.rb
|
230
231
|
- lib/action_set/helpers/export/path_for_helper.rb
|
231
232
|
- lib/action_set/helpers/helper_methods.rb
|
232
233
|
- lib/action_set/helpers/pagination/current_page_description_for_helper.rb
|
@@ -247,8 +248,6 @@ files:
|
|
247
248
|
- lib/action_set/helpers/sort/link_for_helper.rb
|
248
249
|
- lib/action_set/helpers/sort/next_direction_for_helper.rb
|
249
250
|
- lib/action_set/helpers/sort/path_for_helper.rb
|
250
|
-
- lib/action_set/instruction/value.rb
|
251
|
-
- lib/action_set/version.rb
|
252
251
|
homepage: https://github.com/fractaledmind/actionset
|
253
252
|
licenses:
|
254
253
|
- MIT
|
@@ -1,154 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActionSet
|
4
|
-
module Instruction
|
5
|
-
class Value
|
6
|
-
attr_reader :raw
|
7
|
-
|
8
|
-
def initialize(value)
|
9
|
-
@raw = value
|
10
|
-
end
|
11
|
-
|
12
|
-
def cast(to:)
|
13
|
-
adapters.map do |adapter|
|
14
|
-
value = adapter.new(@raw, to).process
|
15
|
-
return value unless value.nil?
|
16
|
-
end.compact.first || @raw
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def adapters
|
22
|
-
[ActiveModelAdapter, PlainRubyAdapter, BooleanAdapter, TimeWithZoneAdapter]
|
23
|
-
end
|
24
|
-
|
25
|
-
class PlainRubyAdapter
|
26
|
-
def initialize(raw, target)
|
27
|
-
@raw = raw
|
28
|
-
@target = target
|
29
|
-
end
|
30
|
-
|
31
|
-
def process
|
32
|
-
return @raw if @raw.is_a? @target
|
33
|
-
possible_values.find { |v| v.is_a? @target }
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def possible_values
|
39
|
-
possible_typecasters.map { |m| typecast(m) }
|
40
|
-
.compact
|
41
|
-
end
|
42
|
-
|
43
|
-
def possible_typecasters
|
44
|
-
@possible_typecasters ||= String.instance_methods
|
45
|
-
.map(&:to_s)
|
46
|
-
.select { |m| m.starts_with? 'to_' }
|
47
|
-
.reject { |m| %[to_v8].include? m }
|
48
|
-
end
|
49
|
-
|
50
|
-
def typecast(method_name)
|
51
|
-
@raw.send(method_name)
|
52
|
-
rescue
|
53
|
-
nil
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
class ActiveModelAdapter
|
58
|
-
begin
|
59
|
-
require 'active_model/type'
|
60
|
-
rescue LoadError
|
61
|
-
require 'active_record/type'
|
62
|
-
end
|
63
|
-
|
64
|
-
def initialize(raw, target)
|
65
|
-
@raw = raw
|
66
|
-
@target = target
|
67
|
-
end
|
68
|
-
|
69
|
-
def process
|
70
|
-
return @raw if @raw.is_a? @target
|
71
|
-
possible_values.find { |v| v.is_a? @target }
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def possible_values
|
77
|
-
possible_typecasters.map { |m| typecast(m, @raw) }
|
78
|
-
end
|
79
|
-
|
80
|
-
def possible_typecasters
|
81
|
-
@possible_typecasters ||= type_class.constants
|
82
|
-
.map(&:to_s)
|
83
|
-
.select { |t| can_typecast?(t) }
|
84
|
-
.reject { |t| t == 'Time' }
|
85
|
-
.map { |t| init_typecaster(t) }
|
86
|
-
.compact
|
87
|
-
end
|
88
|
-
|
89
|
-
def typecast(to_type, value)
|
90
|
-
return to_type.type_cast(value) if to_type.respond_to? :type_cast
|
91
|
-
to_type.cast(value)
|
92
|
-
end
|
93
|
-
|
94
|
-
def can_typecast?(const_name)
|
95
|
-
typecasting_class = type_class.const_get(const_name)
|
96
|
-
typecasting_class.instance_methods.include?(:cast) ||
|
97
|
-
typecasting_class.instance_methods.include?(:type_cast)
|
98
|
-
end
|
99
|
-
|
100
|
-
def init_typecaster(const_name)
|
101
|
-
type_class.const_get(const_name).new
|
102
|
-
rescue
|
103
|
-
nil
|
104
|
-
end
|
105
|
-
|
106
|
-
def type_class
|
107
|
-
ActiveModel::Type
|
108
|
-
rescue NameError
|
109
|
-
ActiveRecord::Type
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
class BooleanAdapter
|
114
|
-
def initialize(raw, target)
|
115
|
-
@raw = raw
|
116
|
-
@target = target
|
117
|
-
end
|
118
|
-
|
119
|
-
def process
|
120
|
-
return if @raw.is_a? @target
|
121
|
-
return unless @target.eql?(TrueClass) || @target.eql?(FalseClass)
|
122
|
-
# ActiveModel::Type::Boolean is too expansive in its casting; will get false positives
|
123
|
-
to_bool
|
124
|
-
end
|
125
|
-
|
126
|
-
private
|
127
|
-
|
128
|
-
def to_bool
|
129
|
-
return @raw if @raw.is_a?(TrueClass) || @raw.is_a?(FalseClass)
|
130
|
-
return true if %w[true yes 1 t].include? @raw.to_s.downcase
|
131
|
-
return false if %w[false no 0 f].include? @raw.to_s.downcase
|
132
|
-
nil
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
class TimeWithZoneAdapter
|
137
|
-
def initialize(raw, target)
|
138
|
-
@raw = raw
|
139
|
-
@target = target
|
140
|
-
end
|
141
|
-
|
142
|
-
def process
|
143
|
-
return if @raw.is_a? @target
|
144
|
-
return unless @target.eql?(ActiveSupport::TimeWithZone)
|
145
|
-
time_value = ActiveModelAdapter.new(@raw, Time).process
|
146
|
-
|
147
|
-
return unless time_value.is_a?(Time)
|
148
|
-
return time_value unless time_value.respond_to?(:in_time_zone)
|
149
|
-
time_value.in_time_zone
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|