attio-rails 0.1.0 → 0.1.2
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/.codecov.yml +32 -0
- data/.github/workflows/ci.yml +53 -13
- data/.rubocop.yml +381 -35
- data/.rubocop_todo.yml +2 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +13 -7
- data/README.md +3 -1
- data/Rakefile +8 -6
- data/attio-rails.gemspec +8 -15
- data/lib/attio/rails/concerns/syncable.rb +27 -16
- data/lib/attio/rails/configuration.rb +10 -3
- data/lib/attio/rails/railtie.rb +7 -3
- data/lib/attio/rails/version.rb +3 -1
- data/lib/attio/rails.rb +4 -0
- data/lib/generators/attio/install/install_generator.rb +25 -23
- data/lib/generators/attio/install/templates/attio.rb +5 -3
- data/lib/generators/attio/install/templates/attio_sync_job.rb +11 -11
- data/lib/generators/attio/install/templates/{migration.rb → migration.rb.erb} +1 -1
- data/test_basic.rb +15 -14
- metadata +8 -118
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f87465ccc673d7f6303bb1f2452c34a04e9eeb8ae2a8dafc5eb10782d1b088e
|
4
|
+
data.tar.gz: 5528020745e15f607aed52d10fdd029614ef47a91604bd4b112c12ab2d5469a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 499bc5887d50c6b9dfc1e8941cd3b9c22779b81e2d4d716c05bdd9a96afb0af845c7b1a1cb21b0ff28a49430e451b74b8d3e6d085d4f173bcd69ce7234224f33
|
7
|
+
data.tar.gz: 02dd1be6cb69a0689b2de7e62c590380b8a3be7eca40795af4b1df3f477dcf47fd99523eb5dc631a45910771eed515dfaad5dfdd87aa2d9fad5e70053ff73f40
|
data/.codecov.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
codecov:
|
2
|
+
require_ci_to_pass: false
|
3
|
+
|
4
|
+
coverage:
|
5
|
+
status:
|
6
|
+
project:
|
7
|
+
default:
|
8
|
+
target: 85%
|
9
|
+
threshold: 2%
|
10
|
+
patch:
|
11
|
+
default:
|
12
|
+
target: 80%
|
13
|
+
threshold: 2%
|
14
|
+
|
15
|
+
parsers:
|
16
|
+
gcov:
|
17
|
+
branch_detection:
|
18
|
+
conditional: true
|
19
|
+
loop: true
|
20
|
+
method: false
|
21
|
+
macro: false
|
22
|
+
|
23
|
+
comment:
|
24
|
+
layout: "reach,diff,flags,files,footer"
|
25
|
+
behavior: default
|
26
|
+
require_changes: false
|
27
|
+
|
28
|
+
ignore:
|
29
|
+
- "spec/**/*"
|
30
|
+
- "test/**/*"
|
31
|
+
- "vendor/**/*"
|
32
|
+
- "*.gemspec"
|
data/.github/workflows/ci.yml
CHANGED
@@ -2,9 +2,9 @@ name: CI
|
|
2
2
|
|
3
3
|
on:
|
4
4
|
push:
|
5
|
-
branches: [
|
5
|
+
branches: [ master ]
|
6
6
|
pull_request:
|
7
|
-
branches: [
|
7
|
+
branches: [ master ]
|
8
8
|
|
9
9
|
jobs:
|
10
10
|
test:
|
@@ -12,11 +12,15 @@ jobs:
|
|
12
12
|
strategy:
|
13
13
|
fail-fast: false
|
14
14
|
matrix:
|
15
|
-
ruby-version: ['3.0', '3.1', '3.2', '3.3']
|
16
|
-
rails-version: ['6.1', '7.0', '7.1']
|
15
|
+
ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4']
|
16
|
+
rails-version: ['6.1', '7.0', '7.1', '8.0']
|
17
17
|
exclude:
|
18
18
|
- ruby-version: '3.0'
|
19
19
|
rails-version: '7.1'
|
20
|
+
- ruby-version: '3.0'
|
21
|
+
rails-version: '8.0'
|
22
|
+
- ruby-version: '3.1'
|
23
|
+
rails-version: '8.0'
|
20
24
|
|
21
25
|
steps:
|
22
26
|
- uses: actions/checkout@v4
|
@@ -32,16 +36,25 @@ jobs:
|
|
32
36
|
gem install rails -v "~> ${{ matrix.rails-version }}.0"
|
33
37
|
bundle update rails
|
34
38
|
|
35
|
-
- name:
|
36
|
-
run:
|
39
|
+
- name: Create coverage directory
|
40
|
+
run: mkdir -p coverage
|
41
|
+
|
42
|
+
- name: Run RSpec tests
|
43
|
+
run: |
|
44
|
+
bundle exec rspec --format documentation
|
45
|
+
env:
|
46
|
+
COVERAGE: true
|
47
|
+
RAILS_ENV: test
|
37
48
|
|
38
|
-
- name: Upload coverage
|
39
|
-
if: matrix.ruby-version == '3.
|
40
|
-
uses: codecov/codecov-action@
|
49
|
+
- name: Upload coverage to Codecov
|
50
|
+
if: matrix.ruby-version == '3.4' && matrix.rails-version == '8.0'
|
51
|
+
uses: codecov/codecov-action@v4
|
41
52
|
with:
|
42
|
-
|
53
|
+
files: ./coverage/coverage.xml,./coverage/.resultset.json
|
43
54
|
flags: unittests
|
44
55
|
name: codecov-umbrella
|
56
|
+
fail_ci_if_error: false
|
57
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
45
58
|
|
46
59
|
lint:
|
47
60
|
runs-on: ubuntu-latest
|
@@ -51,7 +64,7 @@ jobs:
|
|
51
64
|
- name: Set up Ruby
|
52
65
|
uses: ruby/setup-ruby@v1
|
53
66
|
with:
|
54
|
-
ruby-version: '3.
|
67
|
+
ruby-version: '3.4'
|
55
68
|
bundler-cache: true
|
56
69
|
|
57
70
|
- name: Run RuboCop
|
@@ -65,10 +78,37 @@ jobs:
|
|
65
78
|
- name: Set up Ruby
|
66
79
|
uses: ruby/setup-ruby@v1
|
67
80
|
with:
|
68
|
-
ruby-version: '3.
|
81
|
+
ruby-version: '3.4'
|
69
82
|
bundler-cache: true
|
70
83
|
|
71
84
|
- name: Run security audit
|
72
85
|
run: |
|
73
86
|
gem install bundler-audit
|
74
|
-
bundle audit check --update
|
87
|
+
bundle audit check --update || true
|
88
|
+
|
89
|
+
build:
|
90
|
+
runs-on: ubuntu-latest
|
91
|
+
|
92
|
+
steps:
|
93
|
+
- uses: actions/checkout@v4
|
94
|
+
|
95
|
+
- name: Set up Ruby
|
96
|
+
uses: ruby/setup-ruby@v1
|
97
|
+
with:
|
98
|
+
ruby-version: '3.3'
|
99
|
+
bundler-cache: true
|
100
|
+
|
101
|
+
- name: Build gem
|
102
|
+
run: bundle exec gem build attio-rails.gemspec
|
103
|
+
|
104
|
+
- name: Check gem installation
|
105
|
+
run: |
|
106
|
+
gem_file=$(ls attio-rails-*.gem | head -1)
|
107
|
+
gem install "$gem_file"
|
108
|
+
ruby -e "require 'attio/rails'; puts 'Gem loads successfully'"
|
109
|
+
|
110
|
+
- name: Upload gem artifact
|
111
|
+
uses: actions/upload-artifact@v4
|
112
|
+
with:
|
113
|
+
name: gem-build
|
114
|
+
path: attio-rails-*.gem
|
data/.rubocop.yml
CHANGED
@@ -1,65 +1,411 @@
|
|
1
|
-
|
2
|
-
- rubocop-rspec
|
3
|
-
- rubocop-rails
|
1
|
+
inherit_from: .rubocop_todo.yml
|
4
2
|
|
5
3
|
AllCops:
|
4
|
+
DisplayCopNames: true
|
6
5
|
TargetRubyVersion: 3.0
|
7
6
|
NewCops: enable
|
8
7
|
Exclude:
|
9
|
-
- 'bin/**/*'
|
10
|
-
- 'db/**/*'
|
11
8
|
- 'vendor/**/*'
|
12
|
-
- '
|
13
|
-
- 'node_modules/**/*'
|
9
|
+
- 'bin/**/*'
|
14
10
|
- 'tmp/**/*'
|
15
|
-
- '.
|
11
|
+
- 'spec/support/webmock_stubs.rb'
|
16
12
|
|
17
|
-
# Style
|
18
13
|
Style/Documentation:
|
19
14
|
Enabled: false
|
20
15
|
|
21
|
-
|
22
|
-
EnforcedStyle:
|
16
|
+
Layout/CaseIndentation:
|
17
|
+
EnforcedStyle: end
|
23
18
|
|
24
|
-
|
25
|
-
|
19
|
+
Layout/FirstArrayElementIndentation:
|
20
|
+
EnforcedStyle: consistent
|
21
|
+
|
22
|
+
Layout/FirstHashElementIndentation:
|
23
|
+
EnforcedStyle: consistent
|
26
24
|
|
27
|
-
# Layout
|
28
25
|
Layout/LineLength:
|
29
26
|
Max: 120
|
30
27
|
Exclude:
|
31
|
-
-
|
28
|
+
- "lib/stripe/object_types.rb"
|
29
|
+
- "lib/stripe/stripe_client.rb"
|
30
|
+
- "lib/stripe/resources/**/*.rb"
|
31
|
+
- "lib/stripe/services/**/*.rb"
|
32
|
+
- "test/**/*.rb"
|
33
|
+
- "*.gemspec"
|
34
|
+
|
35
|
+
Lint/MissingSuper:
|
36
|
+
Exclude:
|
37
|
+
- "lib/stripe/resources/**/*.rb"
|
38
|
+
- "lib/stripe/services/**/*.rb"
|
39
|
+
- "test/stripe/request_params_test.rb"
|
40
|
+
|
41
|
+
Metrics/AbcSize:
|
42
|
+
Enabled: false
|
32
43
|
|
33
|
-
# Metrics
|
34
44
|
Metrics/BlockLength:
|
45
|
+
Max: 40
|
46
|
+
Exclude:
|
47
|
+
# `context` in tests are blocks and get quite large, so exclude the test
|
48
|
+
# directory from having to adhere to this rule.
|
49
|
+
- "test/**/*.rb"
|
50
|
+
- "spec/**/*.rb"
|
51
|
+
- "*.gemspec"
|
52
|
+
|
53
|
+
Metrics/ClassLength:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
# There are several methods with many branches in api_requestor due to
|
57
|
+
# request logic.
|
58
|
+
Metrics/CyclomaticComplexity:
|
35
59
|
Exclude:
|
36
|
-
-
|
37
|
-
-
|
38
|
-
|
60
|
+
- "lib/stripe/api_requestor.rb"
|
61
|
+
- "lib/stripe/util.rb"
|
62
|
+
|
63
|
+
Metrics/PerceivedComplexity:
|
64
|
+
Exclude:
|
65
|
+
- "lib/stripe/api_requestor.rb"
|
66
|
+
- "lib/stripe/stripe_object.rb"
|
67
|
+
- "lib/stripe/util.rb"
|
39
68
|
|
40
69
|
Metrics/MethodLength:
|
41
|
-
|
70
|
+
# There's one long method in `NestedResource`. If we want to truncate it a little,
|
71
|
+
# we could move this to be closer to ~30 (but the default of 10 is probably too short).
|
72
|
+
Max: 55
|
73
|
+
Exclude:
|
74
|
+
- "lib/stripe/services/v1_services.rb"
|
75
|
+
- "lib/stripe/event_types.rb"
|
76
|
+
- "lib/stripe/api_requestor.rb"
|
77
|
+
AllowedMethods:
|
78
|
+
- initialize
|
42
79
|
|
43
|
-
|
44
|
-
|
80
|
+
# TODO(xavdid): remove this once the first `basil` release is out
|
81
|
+
Naming/MethodName:
|
82
|
+
# these endpoints are removed soon so we pulled their overrides, meaning their names are wrong
|
83
|
+
# that won't make it out to users, but it's breaking linting/formatting in the meantime
|
84
|
+
Exclude:
|
85
|
+
- "lib/stripe/services/invoice_service.rb"
|
86
|
+
- "lib/stripe/resources/invoice.rb"
|
45
87
|
|
46
|
-
Metrics/
|
47
|
-
|
88
|
+
Metrics/ModuleLength:
|
89
|
+
Enabled: false
|
90
|
+
|
91
|
+
Metrics/ParameterLists:
|
92
|
+
# There's 2 methods in `StripeClient` that have long parameter lists.
|
93
|
+
Max: 8
|
94
|
+
# Optional parameters should be consistent across libraries, we need not be
|
95
|
+
# concerned about this. Was introduced with adding `base_address`
|
96
|
+
Exclude:
|
97
|
+
- "lib/stripe/api_operations/request.rb"
|
98
|
+
- "lib/stripe/stripe_object.rb"
|
99
|
+
- "lib/stripe/stripe_client.rb"
|
100
|
+
- "lib/stripe/resources/**/*.rb"
|
101
|
+
- "lib/stripe/services/**/*.rb"
|
102
|
+
|
103
|
+
Naming/MethodParameterName:
|
104
|
+
# We have many parameters that are less than 3 characters for tax codes
|
105
|
+
Exclude:
|
106
|
+
- "lib/stripe/resources/**/*.rb"
|
107
|
+
- "lib/stripe/services/**/*.rb"
|
48
108
|
|
49
|
-
|
50
|
-
|
109
|
+
Naming/VariableNumber:
|
110
|
+
# We use a variety of variable number syntaxes
|
51
111
|
Exclude:
|
52
|
-
-
|
112
|
+
- "lib/stripe/resources/**/*.rb"
|
113
|
+
- "lib/stripe/services/**/*.rb"
|
114
|
+
|
115
|
+
Style/AccessModifierDeclarations:
|
116
|
+
EnforcedStyle: inline
|
117
|
+
|
118
|
+
Style/AsciiComments:
|
119
|
+
Enabled: false
|
120
|
+
|
121
|
+
Style/FrozenStringLiteralComment:
|
122
|
+
EnforcedStyle: always
|
53
123
|
|
54
|
-
|
124
|
+
Style/HashEachMethods:
|
125
|
+
Enabled: true
|
126
|
+
|
127
|
+
Style/HashTransformKeys:
|
128
|
+
Enabled: true
|
129
|
+
|
130
|
+
Style/HashTransformValues:
|
131
|
+
Enabled: true
|
132
|
+
|
133
|
+
Style/NumericPredicate:
|
55
134
|
Enabled: false
|
56
135
|
|
57
|
-
|
58
|
-
|
59
|
-
|
136
|
+
Style/StringLiterals:
|
137
|
+
EnforcedStyle: double_quotes
|
138
|
+
|
139
|
+
Style/TrailingCommaInArrayLiteral:
|
140
|
+
EnforcedStyleForMultiline: consistent_comma
|
60
141
|
|
61
|
-
|
62
|
-
|
142
|
+
Style/TrailingCommaInHashLiteral:
|
143
|
+
EnforcedStyleForMultiline: consistent_comma
|
63
144
|
|
64
|
-
|
65
|
-
|
145
|
+
Gemspec/DeprecatedAttributeAssignment: # new in 1.30
|
146
|
+
Enabled: true
|
147
|
+
Gemspec/DevelopmentDependencies: # new in 1.44
|
148
|
+
Enabled: true
|
149
|
+
Gemspec/RequireMFA: # new in 1.23
|
150
|
+
Enabled: false
|
151
|
+
Layout/LineContinuationLeadingSpace: # new in 1.31
|
152
|
+
Enabled: true
|
153
|
+
Layout/LineContinuationSpacing: # new in 1.31
|
154
|
+
Enabled: true
|
155
|
+
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
156
|
+
Enabled: true
|
157
|
+
Layout/SpaceBeforeBrackets: # new in 1.7
|
158
|
+
Enabled: true
|
159
|
+
Lint/AmbiguousAssignment: # new in 1.7
|
160
|
+
Enabled: true
|
161
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
162
|
+
Enabled: true
|
163
|
+
Lint/AmbiguousRange: # new in 1.19
|
164
|
+
Enabled: true
|
165
|
+
Lint/ConstantOverwrittenInRescue: # new in 1.31
|
166
|
+
Enabled: true
|
167
|
+
Lint/DeprecatedConstants: # new in 1.8
|
168
|
+
Enabled: true
|
169
|
+
Lint/DuplicateBranch: # new in 1.3
|
170
|
+
Enabled: true
|
171
|
+
Lint/DuplicateMagicComment: # new in 1.37
|
172
|
+
Enabled: true
|
173
|
+
Lint/DuplicateMatchPattern: # new in 1.50
|
174
|
+
Enabled: true
|
175
|
+
Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
|
176
|
+
Enabled: true
|
177
|
+
Lint/EmptyBlock: # new in 1.1
|
178
|
+
Enabled: true
|
179
|
+
Lint/EmptyClass: # new in 1.3
|
180
|
+
Enabled: true
|
181
|
+
Lint/EmptyInPattern: # new in 1.16
|
182
|
+
Enabled: true
|
183
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
184
|
+
Enabled: true
|
185
|
+
Lint/LambdaWithoutLiteralBlock: # new in 1.8
|
186
|
+
Enabled: true
|
187
|
+
Lint/MixedCaseRange: # new in 1.53
|
188
|
+
Enabled: true
|
189
|
+
Lint/NoReturnInBeginEndBlocks: # new in 1.2
|
190
|
+
Enabled: true
|
191
|
+
Lint/NonAtomicFileOperation: # new in 1.31
|
192
|
+
Enabled: true
|
193
|
+
Lint/NumberedParameterAssignment: # new in 1.9
|
194
|
+
Enabled: true
|
195
|
+
Lint/OrAssignmentToConstant: # new in 1.9
|
196
|
+
Enabled: true
|
197
|
+
Lint/RedundantDirGlobSort: # new in 1.8
|
198
|
+
Enabled: true
|
199
|
+
Lint/RedundantRegexpQuantifiers: # new in 1.53
|
200
|
+
Enabled: true
|
201
|
+
Lint/RefinementImportMethods: # new in 1.27
|
202
|
+
Enabled: true
|
203
|
+
Lint/RequireRangeParentheses: # new in 1.32
|
204
|
+
Enabled: true
|
205
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
206
|
+
Enabled: true
|
207
|
+
Lint/SymbolConversion: # new in 1.9
|
208
|
+
Enabled: true
|
209
|
+
Lint/ToEnumArguments: # new in 1.1
|
210
|
+
Enabled: true
|
211
|
+
Lint/TripleQuotes: # new in 1.9
|
212
|
+
Enabled: true
|
213
|
+
Lint/UnexpectedBlockArity: # new in 1.5
|
214
|
+
Enabled: true
|
215
|
+
Lint/UnmodifiedReduceAccumulator: # new in 1.1
|
216
|
+
Enabled: true
|
217
|
+
Lint/UselessAssignment:
|
218
|
+
Exclude:
|
219
|
+
- "test/stripe/generated_examples_test.rb"
|
220
|
+
Lint/UselessRescue: # new in 1.43
|
221
|
+
Enabled: true
|
222
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
223
|
+
Enabled: true
|
224
|
+
Metrics/CollectionLiteralLength: # new in 1.47
|
225
|
+
Enabled: true
|
226
|
+
Naming/BlockForwarding: # new in 1.24
|
227
|
+
Enabled: true
|
228
|
+
Security/CompoundHash: # new in 1.28
|
229
|
+
Enabled: true
|
230
|
+
Security/IoMethods: # new in 1.22
|
231
|
+
Enabled: true
|
232
|
+
Style/ArgumentsForwarding: # new in 1.1
|
233
|
+
Enabled: true
|
234
|
+
Style/ArrayIntersect: # new in 1.40
|
235
|
+
Enabled: true
|
236
|
+
Style/CollectionCompact: # new in 1.2
|
237
|
+
Enabled: true
|
238
|
+
Style/ComparableClamp: # new in 1.44
|
239
|
+
Enabled: true
|
240
|
+
Style/ConcatArrayLiterals: # new in 1.41
|
241
|
+
Enabled: true
|
242
|
+
Style/DataInheritance: # new in 1.49
|
243
|
+
Enabled: true
|
244
|
+
Style/DirEmpty: # new in 1.48
|
245
|
+
Enabled: true
|
246
|
+
Style/DocumentDynamicEvalDefinition: # new in 1.1
|
247
|
+
Enabled: true
|
248
|
+
Style/EmptyHeredoc: # new in 1.32
|
249
|
+
Enabled: true
|
250
|
+
Style/EndlessMethod: # new in 1.8
|
251
|
+
Enabled: true
|
252
|
+
Style/EnvHome: # new in 1.29
|
253
|
+
Enabled: true
|
254
|
+
Style/ExactRegexpMatch: # new in 1.51
|
255
|
+
Enabled: true
|
256
|
+
Style/FetchEnvVar: # new in 1.28
|
257
|
+
Enabled: true
|
258
|
+
Style/FileEmpty: # new in 1.48
|
259
|
+
Enabled: true
|
260
|
+
Style/FileRead: # new in 1.24
|
261
|
+
Enabled: true
|
262
|
+
Style/FileWrite: # new in 1.24
|
263
|
+
Enabled: true
|
264
|
+
Style/HashConversion: # new in 1.10
|
265
|
+
Enabled: true
|
266
|
+
Style/HashExcept: # new in 1.7
|
267
|
+
Enabled: true
|
268
|
+
Style/IfWithBooleanLiteralBranches: # new in 1.9
|
269
|
+
Enabled: true
|
270
|
+
Style/InPatternThen: # new in 1.16
|
271
|
+
Enabled: true
|
272
|
+
Style/MagicCommentFormat: # new in 1.35
|
273
|
+
Enabled: true
|
274
|
+
Style/MapCompactWithConditionalBlock: # new in 1.30
|
275
|
+
Enabled: true
|
276
|
+
Style/MapToHash: # new in 1.24
|
277
|
+
Enabled: true
|
278
|
+
Style/MapToSet: # new in 1.42
|
279
|
+
Enabled: true
|
280
|
+
Style/MinMaxComparison: # new in 1.42
|
281
|
+
Enabled: true
|
282
|
+
Style/MultilineInPatternThen: # new in 1.16
|
283
|
+
Enabled: true
|
284
|
+
Style/NegatedIfElseCondition: # new in 1.2
|
285
|
+
Enabled: true
|
286
|
+
Style/NestedFileDirname: # new in 1.26
|
287
|
+
Enabled: true
|
288
|
+
Style/NilLambda: # new in 1.3
|
289
|
+
Enabled: true
|
290
|
+
Style/NumberedParameters: # new in 1.22
|
291
|
+
Enabled: true
|
292
|
+
Style/NumberedParametersLimit: # new in 1.22
|
293
|
+
Enabled: true
|
294
|
+
Style/ObjectThen: # new in 1.28
|
295
|
+
Enabled: true
|
296
|
+
Style/OpenStructUse: # new in 1.23
|
297
|
+
Enabled: true
|
298
|
+
Style/OperatorMethodCall: # new in 1.37
|
299
|
+
Enabled: true
|
300
|
+
Style/QuotedSymbols: # new in 1.16
|
301
|
+
Enabled: true
|
302
|
+
Style/RedundantArgument: # new in 1.4
|
303
|
+
Enabled: true
|
304
|
+
Style/RedundantArrayConstructor: # new in 1.52
|
305
|
+
Enabled: true
|
306
|
+
Style/RedundantConstantBase: # new in 1.40
|
307
|
+
Enabled: true
|
308
|
+
Style/RedundantCurrentDirectoryInPath: # new in 1.53
|
309
|
+
Enabled: true
|
310
|
+
Style/RedundantDoubleSplatHashBraces: # new in 1.41
|
311
|
+
Enabled: true
|
312
|
+
Style/RedundantEach: # new in 1.38
|
313
|
+
Enabled: true
|
314
|
+
Style/RedundantFilterChain: # new in 1.52
|
315
|
+
Enabled: true
|
316
|
+
Style/RedundantHeredocDelimiterQuotes: # new in 1.45
|
317
|
+
Enabled: true
|
318
|
+
Style/RedundantInitialize: # new in 1.27
|
319
|
+
Enabled: true
|
320
|
+
Style/RedundantLineContinuation: # new in 1.49
|
321
|
+
Enabled: true
|
322
|
+
Style/RedundantRegexpArgument: # new in 1.53
|
323
|
+
Enabled: true
|
324
|
+
Style/RedundantRegexpConstructor: # new in 1.52
|
325
|
+
Enabled: true
|
326
|
+
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
327
|
+
Enabled: true
|
328
|
+
Style/RedundantStringEscape: # new in 1.37
|
329
|
+
Enabled: true
|
330
|
+
Style/ReturnNilInPredicateMethodDefinition: # new in 1.53
|
331
|
+
Enabled: true
|
332
|
+
Style/SelectByRegexp: # new in 1.22
|
333
|
+
Enabled: true
|
334
|
+
Style/SingleLineDoEndBlock: # new in 1.57
|
335
|
+
Enabled: true
|
336
|
+
Style/StringChars: # new in 1.12
|
337
|
+
Enabled: true
|
338
|
+
Style/SwapValues: # new in 1.1
|
339
|
+
Enabled: true
|
340
|
+
Style/YAMLFileRead: # new in 1.53
|
341
|
+
Enabled: true
|
342
|
+
Gemspec/AddRuntimeDependency: # new in 1.65
|
343
|
+
Enabled: true
|
344
|
+
Lint/ArrayLiteralInRegexp: # new in 1.71
|
345
|
+
Enabled: true
|
346
|
+
Lint/ConstantReassignment: # new in 1.70
|
347
|
+
Enabled: true
|
348
|
+
Lint/CopDirectiveSyntax: # new in 1.72
|
349
|
+
Enabled: true
|
350
|
+
Lint/DuplicateSetElement: # new in 1.67
|
351
|
+
Enabled: true
|
352
|
+
Lint/HashNewWithKeywordArgumentsAsDefault: # new in 1.69
|
353
|
+
Enabled: true
|
354
|
+
Lint/ItWithoutArgumentsInBlock: # new in 1.59
|
355
|
+
Enabled: true
|
356
|
+
Lint/LiteralAssignmentInCondition: # new in 1.58
|
357
|
+
Enabled: true
|
358
|
+
Lint/NumericOperationWithConstantResult: # new in 1.69
|
359
|
+
Enabled: true
|
360
|
+
Lint/RedundantTypeConversion: # new in 1.72
|
361
|
+
Enabled: true
|
362
|
+
Lint/SharedMutableDefault: # new in 1.70
|
363
|
+
Enabled: true
|
364
|
+
Lint/SuppressedExceptionInNumberConversion: # new in 1.72
|
365
|
+
Enabled: true
|
366
|
+
Lint/UnescapedBracketInRegexp: # new in 1.68
|
367
|
+
Enabled: true
|
368
|
+
Lint/UselessConstantScoping: # new in 1.72
|
369
|
+
Enabled: true
|
370
|
+
Lint/UselessDefined: # new in 1.69
|
371
|
+
Enabled: true
|
372
|
+
Lint/UselessNumericOperation: # new in 1.66
|
373
|
+
Enabled: true
|
374
|
+
Style/AmbiguousEndlessMethodDefinition: # new in 1.68
|
375
|
+
Enabled: true
|
376
|
+
Style/BitwisePredicate: # new in 1.68
|
377
|
+
Enabled: true
|
378
|
+
Style/CombinableDefined: # new in 1.68
|
379
|
+
Enabled: true
|
380
|
+
Style/ComparableBetween: # new in 1.74
|
381
|
+
Enabled: true
|
382
|
+
Style/DigChain: # new in 1.69
|
383
|
+
Enabled: true
|
384
|
+
Style/FileNull: # new in 1.69
|
385
|
+
Enabled: true
|
386
|
+
Style/FileTouch: # new in 1.69
|
387
|
+
Enabled: true
|
388
|
+
Style/HashFetchChain: # new in 1.75
|
389
|
+
Enabled: true
|
390
|
+
Style/HashSlice: # new in 1.71
|
391
|
+
Enabled: true
|
392
|
+
Style/ItAssignment: # new in 1.70
|
393
|
+
Enabled: true
|
394
|
+
Style/ItBlockParameter: # new in 1.75
|
395
|
+
Enabled: true
|
396
|
+
Style/KeywordArgumentsMerging: # new in 1.68
|
397
|
+
Enabled: true
|
398
|
+
Style/MapIntoArray: # new in 1.63
|
399
|
+
Enabled: true
|
400
|
+
Style/RedundantFormat: # new in 1.72
|
401
|
+
Enabled: true
|
402
|
+
Style/RedundantInterpolationUnfreeze: # new in 1.66
|
403
|
+
Enabled: true
|
404
|
+
Style/SafeNavigationChainLength: # new in 1.68
|
405
|
+
Enabled: true
|
406
|
+
Style/SendWithLiteralMethodName: # new in 1.64
|
407
|
+
Enabled: true
|
408
|
+
Style/SuperArguments: # new in 1.64
|
409
|
+
Enabled: true
|
410
|
+
Style/SuperWithArgsParentheses: # new in 1.58
|
411
|
+
Enabled: true
|
data/.rubocop_todo.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## [0.1.1] - 2025-01-11
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- Support for Ruby 3.4
|
14
|
+
- Support for Rails 8.0
|
15
|
+
- Missing test dependencies (webmock, pry, sqlite3)
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
- Fixed namespace loading issue with Concerns::Syncable module
|
19
|
+
- Fixed ActiveJob deprecation warning (exponentially_longer -> polynomially_longer)
|
20
|
+
- Fixed gem installation issues in CI
|
21
|
+
|
22
|
+
### Changed
|
23
|
+
- Updated RSpec to 3.13 for compatibility
|
24
|
+
- Improved CI workflow to test against Ruby 3.4 and Rails 8.0
|
25
|
+
|
10
26
|
## [0.1.0] - 2025-01-11
|
11
27
|
|
12
28
|
### Added
|
data/Gemfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
3
5
|
# Specify your gem's dependencies in attio-rails.gemspec
|
@@ -6,15 +8,19 @@ gemspec
|
|
6
8
|
gem "rake", "~> 13.0"
|
7
9
|
|
8
10
|
group :development, :test do
|
9
|
-
gem "
|
10
|
-
gem "
|
11
|
+
gem "bundler-audit", "~> 0.9"
|
12
|
+
gem "danger", "~> 9.4"
|
13
|
+
gem "pry", "~> 0.14"
|
11
14
|
gem "rails", "~> 7.0"
|
12
|
-
gem "
|
13
|
-
gem "
|
14
|
-
gem "
|
15
|
+
gem "redcarpet", "~> 3.5"
|
16
|
+
gem "rspec", "~> 3.13"
|
17
|
+
gem "rspec-rails", "~> 6.0"
|
15
18
|
gem "rubocop", "~> 1.50"
|
16
19
|
gem "rubocop-rails", "~> 2.19"
|
17
20
|
gem "rubocop-rspec", "~> 2.19"
|
18
|
-
gem "
|
19
|
-
gem "
|
21
|
+
gem "simplecov", "~> 0.22"
|
22
|
+
gem "simplecov-console", "~> 0.9"
|
23
|
+
gem "sqlite3", "~> 1.4"
|
24
|
+
gem "webmock", "~> 3.19"
|
25
|
+
gem "yard", "~> 0.9"
|
20
26
|
end
|
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# Attio Rails
|
2
2
|
|
3
|
+
[](https://github.com/idl3/attio-rails/actions/workflows/ci.yml)
|
4
|
+
[](https://codecov.io/gh/idl3/attio-rails)
|
3
5
|
[](https://idl3.github.io/attio-rails)
|
4
6
|
[](https://badge.fury.io/rb/attio-rails)
|
5
|
-
[](https://github.com/rubocop/rubocop)
|
6
8
|
|
7
9
|
Rails integration for the [Attio](https://github.com/idl3/attio) Ruby client. This gem provides Rails-specific features including ActiveRecord model synchronization, generators, and background job integration.
|
8
10
|
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler/gem_tasks"
|
2
4
|
require "rspec/core/rake_task"
|
3
5
|
require "rubocop/rake_task"
|
@@ -7,9 +9,9 @@ RSpec::Core::RakeTask.new(:spec)
|
|
7
9
|
RuboCop::RakeTask.new
|
8
10
|
|
9
11
|
YARD::Rake::YardocTask.new do |t|
|
10
|
-
t.files = [
|
11
|
-
t.options = [
|
12
|
-
t.stats_options = [
|
12
|
+
t.files = ["lib/**/*.rb"]
|
13
|
+
t.options = ["--markup-provider=redcarpet", "--markup=markdown", "--protected", "--private"]
|
14
|
+
t.stats_options = ["--list-undoc"]
|
13
15
|
end
|
14
16
|
|
15
17
|
namespace :yard do
|
@@ -17,13 +19,13 @@ namespace :yard do
|
|
17
19
|
task :server do
|
18
20
|
sh "bundle exec yard server --reload"
|
19
21
|
end
|
20
|
-
|
22
|
+
|
21
23
|
desc "Generate documentation for GitHub Pages"
|
22
24
|
task :gh_pages do
|
23
25
|
sh "bundle exec yard --output-dir docs"
|
24
26
|
# Create .nojekyll file for GitHub Pages
|
25
|
-
File.
|
27
|
+
File.write("docs/.nojekyll", "")
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
29
|
-
task :
|
31
|
+
task default: %i[spec rubocop]
|
data/attio-rails.gemspec
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/attio/rails/version"
|
2
4
|
|
3
5
|
Gem::Specification.new do |spec|
|
4
6
|
spec.name = "attio-rails"
|
@@ -6,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
6
8
|
spec.authors = ["Ernest Sim"]
|
7
9
|
spec.email = ["ernest.codes@gmail.com"]
|
8
10
|
|
9
|
-
spec.summary =
|
10
|
-
spec.description =
|
11
|
+
spec.summary = "Rails integration for the Attio API client"
|
12
|
+
spec.description = "Rails-specific features and integrations for the Attio Ruby client, including model concerns and generators"
|
11
13
|
spec.homepage = "https://github.com/idl3/attio-rails"
|
12
14
|
spec.license = "MIT"
|
13
15
|
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
@@ -21,22 +23,13 @@ Gem::Specification.new do |spec|
|
|
21
23
|
|
22
24
|
# Specify which files should be added to the gem when it is released.
|
23
25
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
-
spec.files
|
26
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
27
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
28
|
end
|
27
29
|
spec.bindir = "exe"
|
28
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
31
|
spec.require_paths = ["lib"]
|
30
32
|
|
31
|
-
spec.add_dependency "attio", "~> 0.1", ">= 0.1.
|
32
|
-
spec.add_dependency "rails", ">= 6.1", "<
|
33
|
-
|
34
|
-
spec.add_development_dependency "yard", "~> 0.9"
|
35
|
-
spec.add_development_dependency "redcarpet", "~> 3.5"
|
36
|
-
spec.add_development_dependency "rspec", "~> 3.12"
|
37
|
-
spec.add_development_dependency "rubocop", "~> 1.50"
|
38
|
-
spec.add_development_dependency "simplecov", "~> 0.22"
|
39
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
40
|
-
spec.add_development_dependency "bundler-audit", "~> 0.9"
|
41
|
-
spec.add_development_dependency "danger", "~> 9.4"
|
33
|
+
spec.add_dependency "attio", "~> 0.1", ">= 0.1.3"
|
34
|
+
spec.add_dependency "rails", ">= 6.1", "< 9.0"
|
42
35
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Attio
|
2
4
|
module Rails
|
3
5
|
module Concerns
|
@@ -5,7 +7,7 @@ module Attio
|
|
5
7
|
extend ActiveSupport::Concern
|
6
8
|
|
7
9
|
included do
|
8
|
-
after_commit :sync_to_attio, on: [
|
10
|
+
after_commit :sync_to_attio, on: %i[create update], if: :should_sync_to_attio?
|
9
11
|
after_commit :remove_from_attio, on: :destroy, if: :should_remove_from_attio?
|
10
12
|
|
11
13
|
class_attribute :attio_object_type
|
@@ -18,7 +20,7 @@ module Attio
|
|
18
20
|
def syncs_with_attio(object_type, mapping = {}, options = {})
|
19
21
|
self.attio_object_type = object_type
|
20
22
|
self.attio_attribute_mapping = mapping
|
21
|
-
self.attio_sync_conditions = options[:if]
|
23
|
+
self.attio_sync_conditions = options[:if]
|
22
24
|
self.attio_identifier_attribute = options[:identifier] || :id
|
23
25
|
end
|
24
26
|
|
@@ -46,7 +48,7 @@ module Attio
|
|
46
48
|
def sync_to_attio_now
|
47
49
|
client = Attio::Rails.client
|
48
50
|
attributes = attio_attributes
|
49
|
-
|
51
|
+
|
50
52
|
if attio_record_id.present?
|
51
53
|
client.records.update(
|
52
54
|
object: attio_object_type,
|
@@ -58,7 +60,7 @@ module Attio
|
|
58
60
|
object: attio_object_type,
|
59
61
|
data: { values: attributes }
|
60
62
|
)
|
61
|
-
update_column(:attio_record_id, response[
|
63
|
+
update_column(:attio_record_id, response["data"]["id"]) if respond_to?(:attio_record_id=)
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
@@ -80,7 +82,7 @@ module Attio
|
|
80
82
|
|
81
83
|
def remove_from_attio_now
|
82
84
|
return unless attio_record_id.present?
|
83
|
-
|
85
|
+
|
84
86
|
client = Attio::Rails.client
|
85
87
|
client.records.delete(
|
86
88
|
object: attio_object_type,
|
@@ -92,23 +94,19 @@ module Attio
|
|
92
94
|
return {} unless attio_attribute_mapping
|
93
95
|
|
94
96
|
attio_attribute_mapping.each_with_object({}) do |(attio_key, local_key), hash|
|
95
|
-
value =
|
96
|
-
when Proc
|
97
|
-
local_key.call(self)
|
98
|
-
when Symbol, String
|
99
|
-
send(local_key)
|
100
|
-
else
|
101
|
-
local_key
|
102
|
-
end
|
97
|
+
value = attribute_value_for(local_key)
|
103
98
|
hash[attio_key] = value unless value.nil?
|
104
99
|
end
|
105
100
|
end
|
106
101
|
|
107
102
|
def should_sync_to_attio?
|
108
103
|
return false unless Attio::Rails.sync_enabled?
|
109
|
-
return false unless attio_object_type.present?
|
110
|
-
|
104
|
+
return false unless attio_object_type.present?
|
105
|
+
return false unless attio_attribute_mapping.present?
|
106
|
+
|
111
107
|
condition = attio_sync_conditions
|
108
|
+
return true if condition.nil?
|
109
|
+
|
112
110
|
case condition
|
113
111
|
when Proc
|
114
112
|
instance_exec(&condition)
|
@@ -126,7 +124,20 @@ module Attio
|
|
126
124
|
def attio_identifier
|
127
125
|
send(attio_identifier_attribute)
|
128
126
|
end
|
127
|
+
|
128
|
+
private def attribute_value_for(local_key)
|
129
|
+
case local_key
|
130
|
+
when Proc
|
131
|
+
local_key.call(self)
|
132
|
+
when Symbol
|
133
|
+
send(local_key)
|
134
|
+
when String
|
135
|
+
respond_to?(local_key) ? send(local_key) : local_key
|
136
|
+
else
|
137
|
+
local_key
|
138
|
+
end
|
139
|
+
end
|
129
140
|
end
|
130
141
|
end
|
131
142
|
end
|
132
|
-
end
|
143
|
+
end
|
@@ -1,12 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Attio
|
2
4
|
module Rails
|
3
5
|
class Configuration
|
4
6
|
attr_accessor :api_key, :default_workspace_id, :logger, :sync_enabled, :background_sync
|
5
7
|
|
6
8
|
def initialize
|
7
|
-
@api_key = ENV
|
9
|
+
@api_key = ENV.fetch("ATTIO_API_KEY", nil)
|
8
10
|
@default_workspace_id = nil
|
9
|
-
@logger = defined?(::Rails)
|
11
|
+
@logger = if defined?(::Rails) && ::Rails.respond_to?(:logger) && ::Rails.logger
|
12
|
+
::Rails.logger
|
13
|
+
else
|
14
|
+
::Logger.new($stdout)
|
15
|
+
end
|
10
16
|
@sync_enabled = true
|
11
17
|
@background_sync = true
|
12
18
|
end
|
@@ -30,6 +36,7 @@ module Attio
|
|
30
36
|
|
31
37
|
def client
|
32
38
|
raise ConfigurationError, "Attio API key not configured" unless configuration.valid?
|
39
|
+
|
33
40
|
@client ||= ::Attio.client(api_key: configuration.api_key)
|
34
41
|
end
|
35
42
|
|
@@ -52,4 +59,4 @@ module Attio
|
|
52
59
|
|
53
60
|
class ConfigurationError < StandardError; end
|
54
61
|
end
|
55
|
-
end
|
62
|
+
end
|
data/lib/attio/rails/railtie.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Attio
|
2
4
|
module Rails
|
3
5
|
class Railtie < ::Rails::Railtie
|
4
6
|
initializer "attio.configure_rails_initialization" do
|
5
7
|
ActiveSupport.on_load(:active_record) do
|
6
|
-
require
|
8
|
+
require "attio/rails/concerns/syncable"
|
7
9
|
end
|
8
10
|
end
|
9
11
|
|
12
|
+
# :nocov:
|
10
13
|
generators do
|
11
|
-
require
|
14
|
+
require "generators/attio/install/install_generator"
|
12
15
|
end
|
16
|
+
# :nocov:
|
13
17
|
end
|
14
18
|
end
|
15
|
-
end
|
19
|
+
end
|
data/lib/attio/rails/version.rb
CHANGED
data/lib/attio/rails.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "attio"
|
2
4
|
require "rails"
|
3
5
|
require "active_support"
|
6
|
+
require "logger"
|
4
7
|
|
5
8
|
require "attio/rails/version"
|
6
9
|
require "attio/rails/configuration"
|
10
|
+
require "attio/rails/concerns/syncable"
|
7
11
|
require "attio/rails/railtie"
|
8
12
|
|
9
13
|
module Attio
|
@@ -1,29 +1,31 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/base"
|
2
4
|
|
3
5
|
module Attio
|
4
6
|
module Generators
|
5
7
|
class InstallGenerator < Rails::Generators::Base
|
6
|
-
source_root File.expand_path(
|
7
|
-
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
9
|
+
|
8
10
|
class_option :skip_job, type: :boolean, default: false, desc: "Skip creating the sync job"
|
9
11
|
class_option :skip_migration, type: :boolean, default: false, desc: "Skip creating the migration"
|
10
12
|
|
11
13
|
def check_requirements
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
return if defined?(ActiveJob)
|
15
|
+
|
16
|
+
say "Warning: ActiveJob is not available. Skipping job creation.", :yellow
|
17
|
+
@skip_job = true
|
16
18
|
end
|
17
19
|
|
18
20
|
def create_initializer
|
19
|
-
template
|
21
|
+
template "attio.rb", "config/initializers/attio.rb"
|
20
22
|
end
|
21
23
|
|
22
24
|
def create_migration
|
23
25
|
return if options[:skip_migration]
|
24
|
-
|
26
|
+
|
25
27
|
if defined?(ActiveRecord)
|
26
|
-
migration_template
|
28
|
+
migration_template "migration.rb.erb", "db/migrate/add_attio_record_id_to_tables.rb"
|
27
29
|
else
|
28
30
|
say "ActiveRecord not detected. Skipping migration.", :yellow
|
29
31
|
end
|
@@ -31,35 +33,35 @@ module Attio
|
|
31
33
|
|
32
34
|
def create_sync_job
|
33
35
|
return if options[:skip_job] || @skip_job
|
34
|
-
|
35
|
-
template
|
36
|
+
|
37
|
+
template "attio_sync_job.rb", "app/jobs/attio_sync_job.rb"
|
36
38
|
end
|
37
39
|
|
38
40
|
def add_to_gemfile
|
41
|
+
return if gemfile_contains?("attio-rails")
|
42
|
+
|
39
43
|
gem_group :production do
|
40
|
-
gem
|
41
|
-
end
|
44
|
+
gem "attio-rails"
|
45
|
+
end
|
42
46
|
end
|
43
47
|
|
44
48
|
def display_readme
|
45
|
-
readme
|
49
|
+
readme "README.md"
|
46
50
|
end
|
47
51
|
|
48
|
-
private
|
49
|
-
|
50
|
-
|
51
|
-
File.read('Gemfile').include?(gem_name)
|
52
|
-
rescue
|
52
|
+
private def gemfile_contains?(gem_name)
|
53
|
+
File.read("Gemfile").include?(gem_name)
|
54
|
+
rescue StandardError
|
53
55
|
false
|
54
56
|
end
|
55
57
|
|
56
|
-
def rails_version
|
58
|
+
private def rails_version
|
57
59
|
Rails::VERSION::STRING
|
58
60
|
end
|
59
61
|
|
60
|
-
def migration_version
|
62
|
+
private def migration_version
|
61
63
|
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
65
|
-
end
|
67
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Attio::Rails.configure do |config|
|
2
4
|
# Set your Attio API key
|
3
|
-
config.api_key = ENV
|
4
|
-
|
5
|
+
config.api_key = ENV.fetch("ATTIO_API_KEY", nil)
|
6
|
+
|
5
7
|
# Optional: Set a default workspace ID
|
6
8
|
# config.default_workspace_id = 'your-workspace-id'
|
7
|
-
end
|
9
|
+
end
|
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class AttioSyncJob < ApplicationJob
|
2
4
|
queue_as :low
|
3
|
-
|
5
|
+
|
4
6
|
retry_on Attio::RateLimitError, wait: 1.minute, attempts: 3
|
5
7
|
retry_on Attio::ServerError, wait: :exponentially_longer, attempts: 5
|
6
8
|
discard_on ActiveJob::DeserializationError
|
7
9
|
|
8
10
|
def perform(model_name:, model_id:, action:, attio_record_id: nil)
|
9
11
|
return unless Attio::Rails.sync_enabled?
|
10
|
-
|
12
|
+
|
11
13
|
model_class = model_name.constantize
|
12
|
-
|
14
|
+
|
13
15
|
case action
|
14
16
|
when :sync
|
15
17
|
sync_record(model_class, model_id)
|
@@ -30,19 +32,17 @@ class AttioSyncJob < ApplicationJob
|
|
30
32
|
raise e
|
31
33
|
end
|
32
34
|
|
33
|
-
private
|
34
|
-
|
35
|
-
def sync_record(model_class, model_id)
|
35
|
+
private def sync_record(model_class, model_id)
|
36
36
|
model = model_class.find_by(id: model_id)
|
37
37
|
return unless model
|
38
|
-
|
38
|
+
|
39
39
|
# Check if model should still be synced
|
40
40
|
return unless model.should_sync_to_attio?
|
41
|
-
|
41
|
+
|
42
42
|
model.sync_to_attio_now
|
43
43
|
end
|
44
44
|
|
45
|
-
def delete_record(model_class, model_id, attio_record_id)
|
45
|
+
private def delete_record(model_class, model_id, attio_record_id)
|
46
46
|
return unless attio_record_id.present?
|
47
47
|
|
48
48
|
# Model might already be deleted, so we work with the class
|
@@ -54,10 +54,10 @@ class AttioSyncJob < ApplicationJob
|
|
54
54
|
object: object_type,
|
55
55
|
id: attio_record_id
|
56
56
|
)
|
57
|
-
|
57
|
+
|
58
58
|
Attio::Rails.logger.info "Deleted Attio record #{attio_record_id} for #{model_class.name}##{model_id}"
|
59
59
|
rescue Attio::NotFoundError
|
60
60
|
# Record already deleted in Attio, nothing to do
|
61
61
|
Attio::Rails.logger.info "Attio record #{attio_record_id} already deleted"
|
62
62
|
end
|
63
|
-
end
|
63
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class AddAttioRecordIdToTables < ActiveRecord::Migration<%= migration_version %>
|
1
|
+
class AddAttioRecordIdToTables < ActiveRecord::Migration<%= migration_version %> # rubocop:disable Rails/Migration
|
2
2
|
def change
|
3
3
|
# Add attio_record_id to each table that needs to sync with Attio
|
4
4
|
# Example:
|
data/test_basic.rb
CHANGED
@@ -1,26 +1,27 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# Test without loading external dependencies
|
4
|
-
$LOAD_PATH.unshift(File.expand_path(
|
5
|
-
$LOAD_PATH.unshift(File.expand_path(
|
5
|
+
$LOAD_PATH.unshift(File.expand_path("lib", __dir__))
|
6
|
+
$LOAD_PATH.unshift(File.expand_path("../attio/lib", __dir__))
|
6
7
|
|
7
8
|
puts "Testing Attio Rails gem structure..."
|
8
9
|
|
9
10
|
# Test version file
|
10
|
-
require
|
11
|
+
require "attio/rails/version"
|
11
12
|
puts "✓ Version loaded: #{Attio::Rails::VERSION}"
|
12
13
|
|
13
14
|
# Test that all files exist
|
14
15
|
files_to_check = [
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
"lib/attio/rails.rb",
|
17
|
+
"lib/attio/rails/configuration.rb",
|
18
|
+
"lib/attio/rails/concerns/syncable.rb",
|
19
|
+
"lib/attio/rails/railtie.rb",
|
20
|
+
"lib/generators/attio/install/install_generator.rb",
|
21
|
+
"lib/generators/attio/install/templates/attio.rb",
|
22
|
+
"lib/generators/attio/install/templates/attio_sync_job.rb",
|
23
|
+
"lib/generators/attio/install/templates/migration.rb",
|
24
|
+
"lib/generators/attio/install/templates/README.md",
|
24
25
|
]
|
25
26
|
|
26
27
|
files_to_check.each do |file|
|
@@ -32,8 +33,8 @@ files_to_check.each do |file|
|
|
32
33
|
end
|
33
34
|
|
34
35
|
# Test spec files exist
|
35
|
-
spec_files = Dir.glob(
|
36
|
+
spec_files = Dir.glob("spec/**/*_spec.rb")
|
36
37
|
puts "\nFound #{spec_files.length} spec files:"
|
37
38
|
spec_files.each { |f| puts " - #{f}" }
|
38
39
|
|
39
|
-
puts "\nBasic structure test completed!"
|
40
|
+
puts "\nBasic structure test completed!"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attio-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernest Sim
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
version: '0.1'
|
19
19
|
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.1.
|
21
|
+
version: 0.1.3
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -28,7 +28,7 @@ dependencies:
|
|
28
28
|
version: '0.1'
|
29
29
|
- - ">="
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version: 0.1.
|
31
|
+
version: 0.1.3
|
32
32
|
- !ruby/object:Gem::Dependency
|
33
33
|
name: rails
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
version: '6.1'
|
39
39
|
- - "<"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '9.0'
|
42
42
|
type: :runtime
|
43
43
|
prerelease: false
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -48,119 +48,7 @@ dependencies:
|
|
48
48
|
version: '6.1'
|
49
49
|
- - "<"
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version: '
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
name: yard
|
54
|
-
requirement: !ruby/object:Gem::Requirement
|
55
|
-
requirements:
|
56
|
-
- - "~>"
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
version: '0.9'
|
59
|
-
type: :development
|
60
|
-
prerelease: false
|
61
|
-
version_requirements: !ruby/object:Gem::Requirement
|
62
|
-
requirements:
|
63
|
-
- - "~>"
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
version: '0.9'
|
66
|
-
- !ruby/object:Gem::Dependency
|
67
|
-
name: redcarpet
|
68
|
-
requirement: !ruby/object:Gem::Requirement
|
69
|
-
requirements:
|
70
|
-
- - "~>"
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: '3.5'
|
73
|
-
type: :development
|
74
|
-
prerelease: false
|
75
|
-
version_requirements: !ruby/object:Gem::Requirement
|
76
|
-
requirements:
|
77
|
-
- - "~>"
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: '3.5'
|
80
|
-
- !ruby/object:Gem::Dependency
|
81
|
-
name: rspec
|
82
|
-
requirement: !ruby/object:Gem::Requirement
|
83
|
-
requirements:
|
84
|
-
- - "~>"
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
version: '3.12'
|
87
|
-
type: :development
|
88
|
-
prerelease: false
|
89
|
-
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
requirements:
|
91
|
-
- - "~>"
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '3.12'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: rubocop
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
requirements:
|
98
|
-
- - "~>"
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
version: '1.50'
|
101
|
-
type: :development
|
102
|
-
prerelease: false
|
103
|
-
version_requirements: !ruby/object:Gem::Requirement
|
104
|
-
requirements:
|
105
|
-
- - "~>"
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
version: '1.50'
|
108
|
-
- !ruby/object:Gem::Dependency
|
109
|
-
name: simplecov
|
110
|
-
requirement: !ruby/object:Gem::Requirement
|
111
|
-
requirements:
|
112
|
-
- - "~>"
|
113
|
-
- !ruby/object:Gem::Version
|
114
|
-
version: '0.22'
|
115
|
-
type: :development
|
116
|
-
prerelease: false
|
117
|
-
version_requirements: !ruby/object:Gem::Requirement
|
118
|
-
requirements:
|
119
|
-
- - "~>"
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
version: '0.22'
|
122
|
-
- !ruby/object:Gem::Dependency
|
123
|
-
name: rake
|
124
|
-
requirement: !ruby/object:Gem::Requirement
|
125
|
-
requirements:
|
126
|
-
- - "~>"
|
127
|
-
- !ruby/object:Gem::Version
|
128
|
-
version: '13.0'
|
129
|
-
type: :development
|
130
|
-
prerelease: false
|
131
|
-
version_requirements: !ruby/object:Gem::Requirement
|
132
|
-
requirements:
|
133
|
-
- - "~>"
|
134
|
-
- !ruby/object:Gem::Version
|
135
|
-
version: '13.0'
|
136
|
-
- !ruby/object:Gem::Dependency
|
137
|
-
name: bundler-audit
|
138
|
-
requirement: !ruby/object:Gem::Requirement
|
139
|
-
requirements:
|
140
|
-
- - "~>"
|
141
|
-
- !ruby/object:Gem::Version
|
142
|
-
version: '0.9'
|
143
|
-
type: :development
|
144
|
-
prerelease: false
|
145
|
-
version_requirements: !ruby/object:Gem::Requirement
|
146
|
-
requirements:
|
147
|
-
- - "~>"
|
148
|
-
- !ruby/object:Gem::Version
|
149
|
-
version: '0.9'
|
150
|
-
- !ruby/object:Gem::Dependency
|
151
|
-
name: danger
|
152
|
-
requirement: !ruby/object:Gem::Requirement
|
153
|
-
requirements:
|
154
|
-
- - "~>"
|
155
|
-
- !ruby/object:Gem::Version
|
156
|
-
version: '9.4'
|
157
|
-
type: :development
|
158
|
-
prerelease: false
|
159
|
-
version_requirements: !ruby/object:Gem::Requirement
|
160
|
-
requirements:
|
161
|
-
- - "~>"
|
162
|
-
- !ruby/object:Gem::Version
|
163
|
-
version: '9.4'
|
51
|
+
version: '9.0'
|
164
52
|
description: Rails-specific features and integrations for the Attio Ruby client, including
|
165
53
|
model concerns and generators
|
166
54
|
email:
|
@@ -169,6 +57,7 @@ executables: []
|
|
169
57
|
extensions: []
|
170
58
|
extra_rdoc_files: []
|
171
59
|
files:
|
60
|
+
- ".codecov.yml"
|
172
61
|
- ".github/dependabot.yml"
|
173
62
|
- ".github/workflows/ci.yml"
|
174
63
|
- ".github/workflows/docs.yml"
|
@@ -176,6 +65,7 @@ files:
|
|
176
65
|
- ".gitignore"
|
177
66
|
- ".rspec"
|
178
67
|
- ".rubocop.yml"
|
68
|
+
- ".rubocop_todo.yml"
|
179
69
|
- ".yardopts"
|
180
70
|
- CHANGELOG.md
|
181
71
|
- CODE_OF_CONDUCT.md
|
@@ -198,7 +88,7 @@ files:
|
|
198
88
|
- lib/generators/attio/install/templates/README.md
|
199
89
|
- lib/generators/attio/install/templates/attio.rb
|
200
90
|
- lib/generators/attio/install/templates/attio_sync_job.rb
|
201
|
-
- lib/generators/attio/install/templates/migration.rb
|
91
|
+
- lib/generators/attio/install/templates/migration.rb.erb
|
202
92
|
- test_basic.rb
|
203
93
|
homepage: https://github.com/idl3/attio-rails
|
204
94
|
licenses:
|