activerecord-lookml 0.2.1 → 0.3.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/CHANGELOG.md +6 -1
- data/README.md +65 -8
- data/lib/active_record/lookml.rb +4 -1
- data/lib/active_record/lookml/array_field.rb +21 -0
- data/lib/active_record/lookml/block.rb +29 -0
- data/lib/active_record/lookml/core.rb +40 -135
- data/lib/active_record/lookml/field.rb +15 -0
- data/lib/active_record/lookml/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22e877c5df61744d96c9ae907254ffbb3b41c7ef05a950784a79314be5ed88d5
|
4
|
+
data.tar.gz: 5db79293a902a2a9aef8679b7f339fe28a3bf2b4f052428d46ac7b35450e07da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55c559b73d85f62c9ce2a641d6fdc17cf99ba87b4c761789a56ebc32ca0f362b450beb27960483c425c895e0f7fea99fe2be6f0bb9e0e406942277dd7910dd40
|
7
|
+
data.tar.gz: 6e849f35450be8afb6e7d007917ca6169e8f12f6c0c4051daeba5a1e4610c5f4ef484d4f0b6e9f7e44fc874c7bc9855426dda7f91cae44c519352475a62a8724
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -16,14 +16,27 @@ end
|
|
16
16
|
|
17
17
|
## Usage
|
18
18
|
|
19
|
-
### ActiveRecord
|
19
|
+
### Generate LookML view from ActiveRecord class
|
20
20
|
|
21
|
-
Suppose you have ActiveRecord class
|
21
|
+
Suppose you have ActiveRecord class as below:
|
22
22
|
|
23
23
|
```ruby
|
24
|
-
|
24
|
+
ActiveRecord::Schema.define(version: 2021_05_26_103300) do
|
25
|
+
create_table "pulse_onboarding_statuses", force: :cascade do |t|
|
26
|
+
t.bigint "user_id", null: false
|
27
|
+
t.bigint "company_id", null: false
|
28
|
+
t.integer "member_tutorial_state"
|
29
|
+
t.boolean "completed", default: false, null: false
|
30
|
+
t.datetime "created_at", precision: 6, null: false
|
31
|
+
t.datetime "updated_at", precision: 6, null: false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class PulseOnboardingStatus < ActiveRecord::Base
|
25
38
|
MEMBER_TUTORIAL_STATE_ENUM_HASH = {
|
26
|
-
|
39
|
+
explain_condition_survey: 0,
|
27
40
|
ask_condition: 1,
|
28
41
|
explain_high_fives: 2,
|
29
42
|
try_high_fives: 3,
|
@@ -37,15 +50,31 @@ end
|
|
37
50
|
You can generate LookML dimension as below.
|
38
51
|
|
39
52
|
```
|
40
|
-
|
53
|
+
> puts PulseOnboardingStatus.to_lookml
|
54
|
+
view: pulse_onboarding_statuses {
|
55
|
+
sql_table_name: `wantedly-1371.rdb.pulse_pulse_onboarding_statuses`;;
|
56
|
+
|
57
|
+
dimension: id {
|
58
|
+
type: number
|
59
|
+
primary_key: yes
|
60
|
+
sql: ${TABLE}.id ;;
|
61
|
+
}
|
41
62
|
|
42
|
-
|
63
|
+
dimension: user_id {
|
64
|
+
type: number
|
65
|
+
sql: ${TABLE}.user_id ;;
|
66
|
+
}
|
67
|
+
|
68
|
+
dimension: company_id {
|
69
|
+
type: number
|
70
|
+
sql: ${TABLE}.company_id ;;
|
71
|
+
}
|
43
72
|
|
44
73
|
dimension: member_tutorial_state {
|
45
74
|
case: {
|
46
|
-
|
75
|
+
when: {
|
47
76
|
sql: ${TABLE}.member_tutorial_state = 0 ;;
|
48
|
-
label: "
|
77
|
+
label: "explain_condition_survey"
|
49
78
|
}
|
50
79
|
when: {
|
51
80
|
sql: ${TABLE}.member_tutorial_state = 1 ;;
|
@@ -66,6 +95,34 @@ $ ./bin/rails c
|
|
66
95
|
|
67
96
|
}
|
68
97
|
}
|
98
|
+
|
99
|
+
dimension: completed {
|
100
|
+
type: yesno
|
101
|
+
sql: ${TABLE}.completed ;;
|
102
|
+
}
|
103
|
+
|
104
|
+
dimension_group: created_at {
|
105
|
+
type: time
|
106
|
+
sql: ${TABLE}.created_at ;;
|
107
|
+
}
|
108
|
+
|
109
|
+
dimension_group: updated_at {
|
110
|
+
type: time
|
111
|
+
sql: ${TABLE}.updated_at ;;
|
112
|
+
}
|
113
|
+
|
114
|
+
set: detail {
|
115
|
+
fields: [
|
116
|
+
id,
|
117
|
+
user_id,
|
118
|
+
company_id,
|
119
|
+
member_tutorial_state,
|
120
|
+
completed,
|
121
|
+
created_at_time,
|
122
|
+
updated_at_time
|
123
|
+
]
|
124
|
+
}
|
125
|
+
}
|
69
126
|
```
|
70
127
|
|
71
128
|
## Development
|
data/lib/active_record/lookml.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'active_support/all'
|
2
|
-
require
|
2
|
+
require 'active_record/lookml/version'
|
3
|
+
require 'active_record/lookml/block'
|
4
|
+
require 'active_record/lookml/field'
|
5
|
+
require 'active_record/lookml/array_field'
|
3
6
|
|
4
7
|
module ActiveRecord
|
5
8
|
module LookML
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module LookML
|
3
|
+
class ArrayField
|
4
|
+
def initialize(name:, values:)
|
5
|
+
@name = name
|
6
|
+
@values = values
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_lookml(indent_level: 0)
|
10
|
+
indent = ' ' * indent_level
|
11
|
+
lookml = "#{indent}#{@name}: [\n"
|
12
|
+
lookml << @values.map do |value|
|
13
|
+
"#{indent} #{value}"
|
14
|
+
end.join(",\n")
|
15
|
+
lookml << "\n"
|
16
|
+
lookml << "#{indent}]\n"
|
17
|
+
lookml
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module LookML
|
3
|
+
class Block
|
4
|
+
def initialize(type:, name:)
|
5
|
+
@type = type
|
6
|
+
@name = name
|
7
|
+
@fields = []
|
8
|
+
yield(self) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(new_field)
|
12
|
+
@fields << new_field
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_lookml(indent_level: 0)
|
16
|
+
indent = ' ' * indent_level
|
17
|
+
lookml = "#{indent}#{@type}:"
|
18
|
+
lookml << " #{@name}" if @name
|
19
|
+
lookml << " {\n"
|
20
|
+
@fields.each_with_index do |field, index|
|
21
|
+
lookml << "\n" if index > 0 && field.is_a?(Block)
|
22
|
+
lookml << field.to_lookml(indent_level: indent_level + 1)
|
23
|
+
end
|
24
|
+
lookml << "#{indent}}\n"
|
25
|
+
lookml
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -4,157 +4,62 @@ module ActiveRecord
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
module ClassMethods
|
7
|
-
# Generates LookML dimension from ruby hash.
|
8
|
-
#
|
9
|
-
# Input format:
|
10
|
-
#
|
11
|
-
# {"manager_tutorial_state"=>
|
12
|
-
# {"start_tutorial"=>0,
|
13
|
-
# "explain_condition_survay"=>1,
|
14
|
-
# "ask_condition"=>2,
|
15
|
-
# "explain_high_fives"=>3,
|
16
|
-
# "try_high_fives"=>4,
|
17
|
-
# "request_members_to_get_started"=>5,
|
18
|
-
# "done_announce_to_member"=>6,
|
19
|
-
# "done_tutorial"=>7}}
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# Output format:
|
23
|
-
#
|
24
|
-
# dimension: manager_tutorial_state {
|
25
|
-
# case: {
|
26
|
-
# when: {
|
27
|
-
# sql: ${TABLE}.manager_tutorial_state = 0 ;;
|
28
|
-
# label: "start_tutorial"
|
29
|
-
# }
|
30
|
-
# when: {
|
31
|
-
# sql: ${TABLE}.manager_tutorial_state = 1 ;;
|
32
|
-
# label: "explain_condition_survay"
|
33
|
-
# }
|
34
|
-
# when: {
|
35
|
-
# sql: ${TABLE}.manager_tutorial_state = 2 ;;
|
36
|
-
# label: "ask_condition"
|
37
|
-
# }
|
38
|
-
# when: {
|
39
|
-
# sql: ${TABLE}.manager_tutorial_state = 3 ;;
|
40
|
-
# label: "explain_high_fives"
|
41
|
-
# }
|
42
|
-
# when: {
|
43
|
-
# sql: ${TABLE}.manager_tutorial_state = 4 ;;
|
44
|
-
# label: "try_high_fives"
|
45
|
-
# }
|
46
|
-
# when: {
|
47
|
-
# sql: ${TABLE}.manager_tutorial_state = 5 ;;
|
48
|
-
# label: "request_members_to_get_started"
|
49
|
-
# }
|
50
|
-
# when: {
|
51
|
-
# sql: ${TABLE}.manager_tutorial_state = 6 ;;
|
52
|
-
# label: "done_announce_to_member"
|
53
|
-
# }
|
54
|
-
# when: {
|
55
|
-
# sql: ${TABLE}.manager_tutorial_state = 7 ;;
|
56
|
-
# label: "done_tutorial"
|
57
|
-
# }
|
58
|
-
# }
|
59
|
-
# }
|
60
|
-
# @see https://github.com/rails/rails/blob/master/activerecord/lib/active_record/enum.rb
|
61
|
-
def enum_to_lookml
|
62
|
-
defined_enums.map do |name, enum_values|
|
63
|
-
when_lines_lookml = enum_values.map do |label, value|
|
64
|
-
<<-LOOKML
|
65
|
-
when: {
|
66
|
-
sql: ${TABLE}.#{name} = #{value} ;;
|
67
|
-
label: "#{label}"
|
68
|
-
}
|
69
|
-
LOOKML
|
70
|
-
end.join
|
71
|
-
|
72
|
-
<<-LOOKML
|
73
|
-
dimension: #{name} {
|
74
|
-
case: {
|
75
|
-
#{when_lines_lookml}
|
76
|
-
}
|
77
|
-
}
|
78
|
-
LOOKML
|
79
|
-
end.join("\n")
|
80
|
-
end
|
81
|
-
|
82
7
|
def to_lookml(table_name_prefix: 'wantedly-1371.rdb.pulse_')
|
83
|
-
dimensions_lookml = attribute_types.map do |attribute, type|
|
84
|
-
attribute_type_to_dimension_lookml(attribute, type)
|
85
|
-
end.join("\n")
|
86
|
-
|
87
8
|
fields = attribute_types.map do |attribute, type|
|
88
9
|
attribute_type_to_set_detail_field(attribute, type)
|
89
10
|
end.compact
|
90
|
-
fields_lookml = fields.map { |field| " #{field}" }.join(",\n")
|
91
11
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
#{fields_lookml}
|
96
|
-
]
|
97
|
-
}
|
98
|
-
LOOKML
|
99
|
-
|
100
|
-
<<-LOOKML
|
101
|
-
view: pulse_onboarding_statuses {
|
102
|
-
sql_table_name: `#{table_name_prefix}#{table_name}`;;
|
12
|
+
set_block = Block.new(type: "set", name: "detail") do |b|
|
13
|
+
b << ArrayField.new(name: "fields", values: fields)
|
14
|
+
end
|
103
15
|
|
104
|
-
|
105
|
-
#{
|
106
|
-
|
16
|
+
Block.new(type: "view", name: "pulse_onboarding_statuses") do |b|
|
17
|
+
b << Field.new(name: "sql_table_name", value: "`#{table_name_prefix}#{table_name}`;;")
|
18
|
+
attribute_types.each do |attribute, type|
|
19
|
+
b << attribute_type_to_block(attribute, type)
|
20
|
+
end
|
21
|
+
b << set_block
|
22
|
+
end.to_lookml
|
107
23
|
end
|
108
24
|
|
109
25
|
private
|
110
|
-
def
|
26
|
+
def attribute_type_to_block(attribute, type)
|
111
27
|
case type
|
112
28
|
when ActiveModel::Type::Integer
|
113
|
-
|
114
|
-
type: "number"
|
115
|
-
|
116
|
-
sql: "${TABLE}.#{attribute} ;;"
|
117
|
-
|
118
|
-
|
119
|
-
params_lookml = params.map { |k, v| " #{k}: #{v}" }.join("\n")
|
120
|
-
|
121
|
-
<<-LOOKML
|
122
|
-
dimension: #{attribute} {
|
123
|
-
#{params_lookml}
|
124
|
-
}
|
125
|
-
LOOKML
|
29
|
+
Block.new(type: "dimension", name: attribute) do |b|
|
30
|
+
b << Field.new(name: "type", value: "number")
|
31
|
+
b << Field.new(name: "primary_key", value: "yes") if attribute == "id"
|
32
|
+
b << Field.new(name: "sql", value: "${TABLE}.#{attribute} ;;")
|
33
|
+
end
|
126
34
|
when ActiveModel::Type::Boolean
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
35
|
+
Block.new(type: "dimension", name: attribute) do |b|
|
36
|
+
b << Field.new(name: "type", value: "yesno")
|
37
|
+
b << Field.new(name: "sql", value: "${TABLE}.#{attribute} ;;")
|
38
|
+
end
|
39
|
+
when ActiveModel::Type::String
|
40
|
+
Block.new(type: "dimension", name: attribute) do |b|
|
41
|
+
b << Field.new(name: "type", value: "string")
|
42
|
+
b << Field.new(name: "sql", value: "${TABLE}.#{attribute} ;;")
|
43
|
+
end
|
133
44
|
when ActiveRecord::Type::DateTime, ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
}
|
139
|
-
LOOKML
|
45
|
+
Block.new(type: "dimension_group", name: attribute) do |b|
|
46
|
+
b << Field.new(name: "type", value: "time")
|
47
|
+
b << Field.new(name: "sql", value: "${TABLE}.#{attribute} ;;")
|
48
|
+
end
|
140
49
|
when ActiveRecord::Enum::EnumType
|
50
|
+
# @see https://github.com/rails/rails/blob/master/activerecord/lib/active_record/enum.rb
|
141
51
|
enum_values = defined_enums[attribute]
|
142
|
-
when_lines_lookml = enum_values.map do |label, value|
|
143
|
-
<<-LOOKML
|
144
|
-
when: {
|
145
|
-
sql: ${TABLE}.#{attribute} = #{value} ;;
|
146
|
-
label: "#{label}"
|
147
|
-
}
|
148
|
-
LOOKML
|
149
|
-
end.join
|
150
52
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
53
|
+
Block.new(type: "dimension", name: attribute) do |b|
|
54
|
+
b << Block.new(type: "case", name: nil) do |b|
|
55
|
+
enum_values.map do |label, value|
|
56
|
+
b << Block.new(type: "when", name: nil) do |b|
|
57
|
+
b << Field.new(name: "sql", value: "${TABLE}.#{attribute} = #{value} ;;")
|
58
|
+
b << Field.new(name: "label", value: "\"#{label}\"")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
158
63
|
else
|
159
64
|
raise "Unknown attribute type: #{attribute} #{type.class}"
|
160
65
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-lookml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yoshinori Kawasaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -86,7 +86,10 @@ files:
|
|
86
86
|
- bin/console
|
87
87
|
- bin/setup
|
88
88
|
- lib/active_record/lookml.rb
|
89
|
+
- lib/active_record/lookml/array_field.rb
|
90
|
+
- lib/active_record/lookml/block.rb
|
89
91
|
- lib/active_record/lookml/core.rb
|
92
|
+
- lib/active_record/lookml/field.rb
|
90
93
|
- lib/active_record/lookml/version.rb
|
91
94
|
- lib/activerecord-lookml.rb
|
92
95
|
homepage: https://github.com/wantedly/activerecord-lookml
|