imagekitio-rails 1.0.0.beta.1
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/CONTRIBUTING.md +107 -0
- data/LICENSE +201 -0
- data/README.md +81 -0
- data/lib/active_storage/service/image_kit_service.rb +15 -0
- data/lib/imagekit/rails/active_storage/blob_deletion_callback.rb +75 -0
- data/lib/imagekit/rails/active_storage/service.rb +360 -0
- data/lib/imagekit/rails/active_storage.rb +9 -0
- data/lib/imagekit/rails/configuration.rb +103 -0
- data/lib/imagekit/rails/helper.rb +338 -0
- data/lib/imagekit/rails/railtie.rb +26 -0
- data/lib/imagekit/rails/version.rb +9 -0
- data/lib/imagekitio-rails.rb +84 -0
- metadata +158 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_storage/service'
|
|
4
|
+
require 'tempfile'
|
|
5
|
+
|
|
6
|
+
module Imagekit
|
|
7
|
+
module Rails
|
|
8
|
+
module ActiveStorage
|
|
9
|
+
# Active Storage service for ImageKit
|
|
10
|
+
#
|
|
11
|
+
# Stores files in ImageKit and provides URL generation with transformations
|
|
12
|
+
#
|
|
13
|
+
# Configuration in config/storage.yml:
|
|
14
|
+
#
|
|
15
|
+
# imagekit:
|
|
16
|
+
# service: ImageKit
|
|
17
|
+
#
|
|
18
|
+
# Note: url_endpoint, public_key, and private_key are read from
|
|
19
|
+
# the global Imagekit::Rails.configuration (config/initializers/imagekit.rb)
|
|
20
|
+
#
|
|
21
|
+
# The Active Storage 'key' is used as the complete file path in ImageKit.
|
|
22
|
+
# Active Storage generates unique keys that include any necessary folder structure.
|
|
23
|
+
#
|
|
24
|
+
# All files are uploaded as public files in ImageKit.
|
|
25
|
+
class Service < ::ActiveStorage::Service
|
|
26
|
+
attr_reader :client, :url_endpoint, :public_key, :private_key
|
|
27
|
+
|
|
28
|
+
def initialize(url_endpoint: nil, public_key: nil, private_key: nil, **)
|
|
29
|
+
super()
|
|
30
|
+
|
|
31
|
+
# Use provided values or fall back to global configuration
|
|
32
|
+
config = Imagekit::Rails.configuration
|
|
33
|
+
@url_endpoint = url_endpoint || config.url_endpoint
|
|
34
|
+
@public_key = public_key || config.public_key
|
|
35
|
+
@private_key = private_key || config.private_key
|
|
36
|
+
|
|
37
|
+
@client = Imagekitio::Client.new(
|
|
38
|
+
private_key: @private_key
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Upload a file to ImageKit
|
|
43
|
+
#
|
|
44
|
+
# @param key [String] The complete path for the file in ImageKit (e.g., "uploads/abc123xyz")
|
|
45
|
+
# @param io [IO] The file content to upload
|
|
46
|
+
# @param checksum [String, nil] Optional MD5 checksum for integrity verification
|
|
47
|
+
# @param filename [String, nil] Optional filename to use
|
|
48
|
+
# @return [void]
|
|
49
|
+
# @raise [ActiveStorage::IntegrityError] If upload fails
|
|
50
|
+
# @note The ImageKit file_id is automatically stored in the blob's metadata after successful upload.
|
|
51
|
+
# This enables automatic deletion when the blob is purged.
|
|
52
|
+
def upload(key, io, checksum: nil, filename: nil, **)
|
|
53
|
+
instrument :upload, key: key, checksum: checksum do
|
|
54
|
+
# Read the file content
|
|
55
|
+
content = io.read
|
|
56
|
+
io.rewind if io.respond_to?(:rewind)
|
|
57
|
+
|
|
58
|
+
# Extract folder and filename from the key
|
|
59
|
+
# The key is the complete path: "folder/subfolder/filename"
|
|
60
|
+
folder_path = ::File.dirname(key)
|
|
61
|
+
file_name = filename || ::File.basename(key)
|
|
62
|
+
|
|
63
|
+
# Build upload parameters
|
|
64
|
+
upload_params = {
|
|
65
|
+
file: content,
|
|
66
|
+
file_name: file_name,
|
|
67
|
+
use_unique_file_name: false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Only include folder if there is one (don't pass nil or '.')
|
|
71
|
+
upload_params[:folder] = folder_path unless folder_path == '.'
|
|
72
|
+
|
|
73
|
+
# Upload to ImageKit - the key determines the full path
|
|
74
|
+
response = @client.files.upload(**upload_params)
|
|
75
|
+
|
|
76
|
+
# Store the file_id in blob metadata for future deletion
|
|
77
|
+
store_file_id_in_blob_metadata(key, response.file_id) if response.respond_to?(:file_id) && response.file_id
|
|
78
|
+
end
|
|
79
|
+
rescue Imagekitio::Errors::Error => e
|
|
80
|
+
raise ::ActiveStorage::IntegrityError, "Upload failed: #{e.message}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Download file content from ImageKit
|
|
84
|
+
#
|
|
85
|
+
# @param key [String] The unique identifier for the file
|
|
86
|
+
# @yield [chunk] Streams file content in chunks if block given
|
|
87
|
+
# @yieldparam chunk [String] A chunk of the file content
|
|
88
|
+
# @return [String, void] The complete file content if no block given, void if block given
|
|
89
|
+
def download(key, &block)
|
|
90
|
+
if block_given?
|
|
91
|
+
instrument :streaming_download, key: key do
|
|
92
|
+
stream(key, &block)
|
|
93
|
+
end
|
|
94
|
+
else
|
|
95
|
+
instrument :download, key: key do
|
|
96
|
+
url = url_for_key(key)
|
|
97
|
+
response = Net::HTTP.get_response(URI(url))
|
|
98
|
+
response.body
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Override open to skip checksum verification for ImageKit
|
|
104
|
+
#
|
|
105
|
+
# ImageKit may serve optimized versions of files (format conversion, compression, etc.),
|
|
106
|
+
# which causes the checksum to differ from the originally uploaded file.
|
|
107
|
+
# This is safe because:
|
|
108
|
+
# 1. ImageKit is a trusted CDN service
|
|
109
|
+
# 2. Files are served over HTTPS
|
|
110
|
+
# 3. The optimization is intentional behavior
|
|
111
|
+
#
|
|
112
|
+
# Note: This method is called by ActiveStorage when processing variants or
|
|
113
|
+
# when blob.open is called (e.g., for image processing).
|
|
114
|
+
#
|
|
115
|
+
# @param key [String] The unique identifier for the file
|
|
116
|
+
# @param checksum [String] The expected checksum (ignored for ImageKit)
|
|
117
|
+
# @param name [String, Array] Basename for the temporary file (can be string or [basename, extension])
|
|
118
|
+
# @param tmpdir [String, nil] Directory for the temporary file
|
|
119
|
+
# @yield [tempfile] Provides access to the downloaded file
|
|
120
|
+
# @yieldparam tempfile [Tempfile] The temporary file containing downloaded content
|
|
121
|
+
# @return [void]
|
|
122
|
+
def open(key, checksum:, name: 'ActiveStorage-', tmpdir: nil, **)
|
|
123
|
+
instrument :open, key: key, checksum: checksum do
|
|
124
|
+
# Create a temporary file to download into
|
|
125
|
+
# ActiveStorage may pass name as a string or array [basename, extension]
|
|
126
|
+
tempfile = Tempfile.open(name, tmpdir || Dir.tmpdir, binmode: true)
|
|
127
|
+
|
|
128
|
+
begin
|
|
129
|
+
# Download the file without checksum verification
|
|
130
|
+
download(key) do |chunk|
|
|
131
|
+
tempfile.write(chunk)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
tempfile.rewind
|
|
135
|
+
|
|
136
|
+
# Yield the tempfile to the caller
|
|
137
|
+
yield tempfile
|
|
138
|
+
ensure
|
|
139
|
+
# Always clean up the tempfile
|
|
140
|
+
tempfile.close!
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Download a byte range from the file
|
|
146
|
+
#
|
|
147
|
+
# @param key [String] The unique identifier for the file
|
|
148
|
+
# @param range [Range] The byte range to download
|
|
149
|
+
# @return [String] The requested chunk of file content
|
|
150
|
+
def download_chunk(key, range)
|
|
151
|
+
instrument :download_chunk, key: key, range: range do
|
|
152
|
+
url = url_for_key(key)
|
|
153
|
+
uri = URI(url)
|
|
154
|
+
|
|
155
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
|
156
|
+
request = Net::HTTP::Get.new(uri)
|
|
157
|
+
request['Range'] = "bytes=#{range.begin}-#{range.end}"
|
|
158
|
+
response = http.request(request)
|
|
159
|
+
response.body
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Delete a file from ImageKit
|
|
165
|
+
#
|
|
166
|
+
# @param key [String] The unique identifier for the file
|
|
167
|
+
# @return [void]
|
|
168
|
+
# @note This method is called by Active Storage after the blob record is already deleted
|
|
169
|
+
# from the database, making it impossible to retrieve the file_id from metadata.
|
|
170
|
+
# Actual deletion is handled automatically by a before_destroy callback on the blob,
|
|
171
|
+
# which runs before the blob is destroyed and has access to the file_id in metadata.
|
|
172
|
+
# This method is a no-op that exists only to satisfy the Active Storage service interface.
|
|
173
|
+
def delete(key)
|
|
174
|
+
# No-op: Deletion is handled by BlobDeletionCallback before the blob is destroyed
|
|
175
|
+
# This method is called after blob deletion, so we can't access metadata here
|
|
176
|
+
::Rails.logger.debug { "ImageKit delete called for key: #{key} (handled by before_destroy callback)" } if defined?(::Rails)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Delete multiple files from ImageKit by prefix
|
|
180
|
+
#
|
|
181
|
+
# @param prefix [String] The prefix path to delete (e.g., "uploads/2024/")
|
|
182
|
+
# @return [void]
|
|
183
|
+
# @note This method is rarely used by Active Storage. Individual file deletions
|
|
184
|
+
# are handled automatically by a before_destroy callback on each blob.
|
|
185
|
+
# This method is called after blobs are already deleted from the database,
|
|
186
|
+
# so it cannot access blob metadata. This is a no-op that exists only to satisfy
|
|
187
|
+
# the Active Storage service interface.
|
|
188
|
+
def delete_prefixed(prefix)
|
|
189
|
+
# No-op: Deletion is handled by BlobDeletionCallback on individual blobs
|
|
190
|
+
# This method is called after blobs are deleted, so we can't access metadata
|
|
191
|
+
return unless defined?(::Rails)
|
|
192
|
+
|
|
193
|
+
::Rails.logger.debug do
|
|
194
|
+
"ImageKit delete_prefixed called for prefix: #{prefix} (handled by before_destroy callback on individual blobs)"
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Check if a file exists in ImageKit
|
|
199
|
+
#
|
|
200
|
+
# @param key [String] The unique identifier for the file
|
|
201
|
+
# @return [Boolean]
|
|
202
|
+
# @note Makes an API call to ImageKit to verify the file exists.
|
|
203
|
+
# Requires the imagekit_file_id to be stored in blob metadata.
|
|
204
|
+
def exist?(key)
|
|
205
|
+
instrument :exist, key: key do |payload|
|
|
206
|
+
blob = find_blob_by_key(key)
|
|
207
|
+
|
|
208
|
+
# If blob doesn't exist or has no file_id, file doesn't exist
|
|
209
|
+
if blob.nil? || !blob.metadata.key?('imagekit_file_id')
|
|
210
|
+
payload[:exist] = false
|
|
211
|
+
payload[:reason] = blob.nil? ? 'blob_not_found' : 'file_id_missing'
|
|
212
|
+
next false
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
file_id = blob.metadata['imagekit_file_id']
|
|
216
|
+
|
|
217
|
+
begin
|
|
218
|
+
# Try to get file details from ImageKit
|
|
219
|
+
@client.files.get(file_id)
|
|
220
|
+
payload[:exist] = true
|
|
221
|
+
true
|
|
222
|
+
rescue Imagekitio::Errors::Error => e
|
|
223
|
+
# File not found or other error
|
|
224
|
+
payload[:exist] = false
|
|
225
|
+
payload[:error] = e.message
|
|
226
|
+
false
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Generate a URL for the file
|
|
232
|
+
#
|
|
233
|
+
# @param key [String] The unique identifier for the file
|
|
234
|
+
# @param transformation [Array<Hash>, nil] ImageKit transformations
|
|
235
|
+
# @return [String] The generated URL for the file
|
|
236
|
+
# @see https://www.gemdocs.org/gems/imagekitio/4.0.0/Imagekitio/Models/Transformation.html Transformation options
|
|
237
|
+
def url(key, transformation: nil, **)
|
|
238
|
+
instrument :url, key: key do |payload|
|
|
239
|
+
generated_url = url_for_key(key, transformation: transformation)
|
|
240
|
+
payload[:url] = generated_url
|
|
241
|
+
generated_url
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
private
|
|
246
|
+
|
|
247
|
+
# Build a URL for a file key with optional transformations
|
|
248
|
+
#
|
|
249
|
+
# @param key [String] The file path in ImageKit
|
|
250
|
+
# @param transformation [Array<Hash>, nil] Optional transformations
|
|
251
|
+
# @return [String] The complete ImageKit URL
|
|
252
|
+
# @private
|
|
253
|
+
def url_for_key(key, transformation: nil)
|
|
254
|
+
# The key is the complete file path in ImageKit
|
|
255
|
+
src_options = Imagekitio::Models::SrcOptions.new(
|
|
256
|
+
src: key,
|
|
257
|
+
url_endpoint: @url_endpoint,
|
|
258
|
+
transformation: transformation || []
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
@client.helper.build_url(src_options)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Stream file content in chunks
|
|
265
|
+
#
|
|
266
|
+
# @param key [String] The file path in ImageKit
|
|
267
|
+
# @yield [chunk] Yields each chunk of the file content
|
|
268
|
+
# @yieldparam chunk [String] A chunk of file content
|
|
269
|
+
# @return [void]
|
|
270
|
+
# @private
|
|
271
|
+
def stream(key, &block)
|
|
272
|
+
url = url_for_key(key)
|
|
273
|
+
uri = URI(url)
|
|
274
|
+
|
|
275
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
|
276
|
+
request = Net::HTTP::Get.new(uri)
|
|
277
|
+
http.request(request) do |response|
|
|
278
|
+
response.read_body(&block)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Instrument an operation for Active Support notifications
|
|
284
|
+
#
|
|
285
|
+
# @param operation [Symbol] The operation name (e.g., :upload, :download)
|
|
286
|
+
# @param payload [Hash] Additional data to include in the notification
|
|
287
|
+
# @yield Block to execute with instrumentation
|
|
288
|
+
# @return [Object] The result of the yielded block
|
|
289
|
+
# @private
|
|
290
|
+
def instrument(operation, payload = {}, &)
|
|
291
|
+
ActiveSupport::Notifications.instrument(
|
|
292
|
+
"service_#{operation}.active_storage",
|
|
293
|
+
payload.merge(service: service_name),
|
|
294
|
+
&
|
|
295
|
+
)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Return the service name for Active Storage instrumentation
|
|
299
|
+
#
|
|
300
|
+
# @return [Symbol] The service name (:imagekit)
|
|
301
|
+
# @private
|
|
302
|
+
def service_name
|
|
303
|
+
:imagekit
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Find a blob by its key
|
|
307
|
+
#
|
|
308
|
+
# @param key [String] The blob key
|
|
309
|
+
# @return [ActiveStorage::Blob, nil] The blob or nil if not found
|
|
310
|
+
# @private
|
|
311
|
+
def find_blob_by_key(key)
|
|
312
|
+
return nil unless defined?(::ActiveStorage::Blob)
|
|
313
|
+
|
|
314
|
+
::ActiveStorage::Blob.find_by(key: key, service_name: service_name.to_s)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# Find all blobs with keys starting with the given prefix
|
|
318
|
+
#
|
|
319
|
+
# @param prefix [String] The key prefix
|
|
320
|
+
# @return [ActiveRecord::Relation<ActiveStorage::Blob>] The matching blobs
|
|
321
|
+
# @private
|
|
322
|
+
def find_blobs_by_prefix(prefix)
|
|
323
|
+
return [] unless defined?(::ActiveStorage::Blob)
|
|
324
|
+
|
|
325
|
+
::ActiveStorage::Blob.where(service_name: service_name.to_s)
|
|
326
|
+
.where('key LIKE ?', "#{sanitize_sql_like(prefix)}%")
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Sanitize string for use in SQL LIKE pattern
|
|
330
|
+
#
|
|
331
|
+
# @param string [String] The string to sanitize
|
|
332
|
+
# @return [String] The sanitized string
|
|
333
|
+
# @private
|
|
334
|
+
def sanitize_sql_like(string)
|
|
335
|
+
string.gsub(/[\\_%]/) { |match| "\\#{match}" }
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Store the ImageKit file_id in the blob's metadata
|
|
339
|
+
#
|
|
340
|
+
# @param key [String] The blob key
|
|
341
|
+
# @param file_id [String] The ImageKit file_id
|
|
342
|
+
# @return [void]
|
|
343
|
+
# @private
|
|
344
|
+
def store_file_id_in_blob_metadata(key, file_id)
|
|
345
|
+
return unless defined?(::ActiveStorage::Blob)
|
|
346
|
+
|
|
347
|
+
# Find the blob by key - it should exist since upload is called after blob creation
|
|
348
|
+
blob = ::ActiveStorage::Blob.find_by(key: key, service_name: service_name.to_s)
|
|
349
|
+
|
|
350
|
+
# Update the metadata column to include the file_id
|
|
351
|
+
# Use update_column to skip callbacks and validations
|
|
352
|
+
blob&.update_column(:metadata, blob.metadata.merge('imagekit_file_id' => file_id))
|
|
353
|
+
rescue StandardError => e
|
|
354
|
+
# Log the error but don't fail the upload
|
|
355
|
+
::Rails.logger.warn("Failed to store ImageKit file_id for key #{key}: #{e.message}") if defined?(::Rails)
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Imagekit
|
|
4
|
+
module Rails
|
|
5
|
+
# Configuration class for ImageKit Rails integration
|
|
6
|
+
#
|
|
7
|
+
# This class stores all the configuration settings needed for ImageKit to work.
|
|
8
|
+
# By default, it reads from environment variables, but can be customized via the configure block.
|
|
9
|
+
#
|
|
10
|
+
# @example Basic configuration
|
|
11
|
+
# Imagekit::Rails.configure do |config|
|
|
12
|
+
# config.private_key = 'your_private_key'
|
|
13
|
+
# config.public_key = 'your_public_key'
|
|
14
|
+
# config.url_endpoint = 'https://ik.imagekit.io/your_imagekit_id'
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# @example Using environment variables (default)
|
|
18
|
+
# # .env file
|
|
19
|
+
# IMAGEKIT_PRIVATE_KEY=private_xxx
|
|
20
|
+
# IMAGEKIT_PUBLIC_KEY=public_xxx
|
|
21
|
+
# IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/your_imagekit_id
|
|
22
|
+
#
|
|
23
|
+
# @see https://github.com/imagekit-developer/imagekit-ruby ImageKit Ruby SDK
|
|
24
|
+
class Configuration
|
|
25
|
+
# @!attribute [rw] private_key
|
|
26
|
+
# @return [String, nil] ImageKit private key for authentication (default: ENV['IMAGEKIT_PRIVATE_KEY'])
|
|
27
|
+
# @!attribute [rw] public_key
|
|
28
|
+
# @return [String, nil] ImageKit public key for client-side operations (default: ENV['IMAGEKIT_PUBLIC_KEY'])
|
|
29
|
+
# @!attribute [rw] url_endpoint
|
|
30
|
+
# @return [String, nil] ImageKit URL endpoint (default: ENV['IMAGEKIT_URL_ENDPOINT'])
|
|
31
|
+
# @!attribute [rw] transformation_position
|
|
32
|
+
# @return [Symbol] Position of transformation params in URL (:query or :path, default: :query)
|
|
33
|
+
# @!attribute [rw] responsive
|
|
34
|
+
# @return [Boolean] Enable responsive image generation (default: true)
|
|
35
|
+
# @!attribute [rw] device_breakpoints
|
|
36
|
+
# @return [Array<Integer>] Breakpoints for device-based responsive images (default: [640, 750, 828, 1080, 1200, 1920, 2048, 3840])
|
|
37
|
+
# @!attribute [rw] image_breakpoints
|
|
38
|
+
# @return [Array<Integer>] Breakpoints for content-based responsive images (default: [16, 32, 48, 64, 96, 128, 256, 384])
|
|
39
|
+
attr_accessor :private_key, :public_key, :url_endpoint, :transformation_position,
|
|
40
|
+
:responsive, :device_breakpoints, :image_breakpoints
|
|
41
|
+
|
|
42
|
+
def initialize
|
|
43
|
+
@private_key = ENV['IMAGEKIT_PRIVATE_KEY']
|
|
44
|
+
@public_key = ENV['IMAGEKIT_PUBLIC_KEY']
|
|
45
|
+
@url_endpoint = ENV['IMAGEKIT_URL_ENDPOINT']
|
|
46
|
+
@transformation_position = :query
|
|
47
|
+
@responsive = true
|
|
48
|
+
@device_breakpoints = [640, 750, 828, 1080, 1200, 1920, 2048, 3840]
|
|
49
|
+
@image_breakpoints = [16, 32, 48, 64, 96, 128, 256, 384]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns the ImageKit client instance
|
|
53
|
+
#
|
|
54
|
+
# The client is initialized lazily and cached for reuse.
|
|
55
|
+
# It uses the configured private_key.
|
|
56
|
+
#
|
|
57
|
+
# @return [Imagekitio::Client] The ImageKit SDK client
|
|
58
|
+
# @see https://www.gemdocs.org/gems/imagekitio/4.0.0/Imagekitio/Client.html ImageKit Client docs
|
|
59
|
+
def client
|
|
60
|
+
@client ||= Imagekitio::Client.new(
|
|
61
|
+
private_key: private_key
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class << self
|
|
67
|
+
attr_writer :configuration
|
|
68
|
+
|
|
69
|
+
# Returns the current configuration instance
|
|
70
|
+
#
|
|
71
|
+
# @return [Configuration] The current configuration
|
|
72
|
+
def configuration
|
|
73
|
+
@configuration ||= Configuration.new
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Configure ImageKit Rails settings
|
|
77
|
+
#
|
|
78
|
+
# @example
|
|
79
|
+
# Imagekit::Rails.configure do |config|
|
|
80
|
+
# config.private_key = 'your_private_key'
|
|
81
|
+
# config.public_key = 'your_public_key'
|
|
82
|
+
# config.url_endpoint = 'https://ik.imagekit.io/your_imagekit_id'
|
|
83
|
+
# config.transformation_position = :path
|
|
84
|
+
# config.responsive = false
|
|
85
|
+
# end
|
|
86
|
+
#
|
|
87
|
+
# @yield [Configuration] The configuration instance to modify
|
|
88
|
+
# @return [void]
|
|
89
|
+
def configure
|
|
90
|
+
yield(configuration)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Reset configuration to default values
|
|
94
|
+
#
|
|
95
|
+
# This creates a new Configuration instance with default values from environment variables.
|
|
96
|
+
#
|
|
97
|
+
# @return [Configuration] The new configuration instance
|
|
98
|
+
def reset_configuration!
|
|
99
|
+
@configuration = Configuration.new
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|