runapi-happyhorse 0.2.4 → 0.2.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e0fbd41ba815c6b83de99cd5c32f46981293c448a0e10fa9d5894403f26868f
4
- data.tar.gz: 1b8ed70e59a12339fc45ead0a013cd78d1f3c52eb638faa90d750dcdab603ae4
3
+ metadata.gz: 8420f63d7f99ed90385490503c24de7fcb1057aafe9c7d2e707e0509df9daeb2
4
+ data.tar.gz: 76648efbe65479f2c4c042ae4e5d11b2fc51e8f76c0fe113836f784e797c4f98
5
5
  SHA512:
6
- metadata.gz: 8b4b0986bf2e5c8ac7c1f7488c84237cb85933397a2af5760a254fb845b958a8b6a5b65d3f7353fb3680b35fb1aa0a4f628177423dfc2eb5077c12ca84b975b1
7
- data.tar.gz: 45314c2e79d8f9ff6bee7e53811580dd2654aa94d0d4f80a4fabae768c58bcc7a28ddb3f145293bb20d2c8300f5e026fd70ff696549998109f3a955403bc0277
6
+ metadata.gz: f7e08714a1d7b8ffb5f22ac49c0d652876eeedff7c8e0a460cb9114db6604d9a98c275cb56d8244b46a0602891f62bf2ab9af652afa824476de778dc9ef6acbf
7
+ data.tar.gz: fefb8e30365b1d577314ef2de5dcda68bce75f85125fd0734128a5f648f255a5f2a3bdd26fc1078d637631662265ce7ab49ed197deb071cc1cfbbe5b6411c701
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # HappyHorse API Ruby SDK for RunAPI
2
2
 
3
- The happyhorse ai api Ruby SDK is the language-specific package for HappyHorse on RunAPI. Use this package for text, image, reference-to-video, and edit-video workflows that need JSON request bodies, task status lookup, and consistent RunAPI errors in Ruby.
3
+ The happyhorse ai api Ruby SDK is the language-specific package for HappyHorse on RunAPI. Use this package for text, image, and edit-video workflows that need JSON request bodies, task status lookup, and consistent RunAPI errors in Ruby.
4
4
 
5
5
  ## Install
6
6
 
@@ -15,15 +15,18 @@ require "runapi-happyhorse"
15
15
 
16
16
  client = RunApi::HappyHorse::Client.new
17
17
  video = client.text_to_video.run(
18
- model: "happyhorse-text-to-video",
19
- prompt: "A tiny paper horse gallops through a miniature cardboard city at night.",
20
- resolution: "1080p",
18
+ model: "happyhorse-character",
19
+ prompt: "Character1 walks through a miniature cardboard city at night.",
20
+ reference_image_urls: ["https://cdn.runapi.ai/public/samples/reference-1.jpg"],
21
+ output_resolution: "1080p",
21
22
  aspect_ratio: "16:9",
22
- duration: 5
23
+ duration_seconds: 5
23
24
  )
24
25
  ```
25
26
 
26
- For image-to-video, call `client.image_to_video.run` with `model: "happyhorse-image-to-video"` and exactly one `image_urls` entry. For reference-to-video, call `client.reference_to_video.run` with `model: "happyhorse-reference-to-video"` and 1-9 `reference_image` entries. For edit-video, call `client.edit_video.run` with `model: "happyhorse-video-edit"`, one `video_url`, and optional `reference_image` entries.
27
+ For image-to-video, call `client.image_to_video.run` with `model: "happyhorse-image-to-video"` and exactly one `image_urls` entry. For character-guided text-to-video, call `client.text_to_video.run` with `model: "happyhorse-character"` and 1-9 `reference_image_urls` entries. For edit-video, call `client.edit_video.run` with `model: "happyhorse-edit-video"`, one `video_url`, and optional `reference_image` entries.
28
+
29
+ RunAPI-generated file URLs are temporary. Download and store generated images, videos, audio, or other files in your own durable storage within 7 days; do not treat returned URLs as long-term assets.
27
30
 
28
31
  ## Links
29
32
 
@@ -31,8 +34,8 @@ For image-to-video, call `client.image_to_video.run` with `model: "happyhorse-im
31
34
  - SDK docs: https://runapi.ai/docs#sdk-happyhorse
32
35
  - Product docs: https://runapi.ai/docs#happyhorse
33
36
  - Image-to-video pricing and rate limits: https://runapi.ai/models/happyhorse/image-to-video
34
- - Reference-to-video pricing and rate limits: https://runapi.ai/models/happyhorse/reference-to-video
35
- - Edit-video pricing and rate limits: https://runapi.ai/models/happyhorse/video-edit
37
+ - Character pricing and rate limits: https://runapi.ai/models/happyhorse/character
38
+ - Edit-video pricing and rate limits: https://runapi.ai/models/happyhorse/edit-video
36
39
  - Pricing and rate limits: https://runapi.ai/models/happyhorse/text-to-video
37
40
  - Provider comparison: https://runapi.ai/providers/alibaba
38
41
  - Full catalog: https://runapi.ai/models
@@ -2,17 +2,25 @@
2
2
 
3
3
  module RunApi
4
4
  module HappyHorse
5
- class Client
6
- attr_reader :text_to_video, :image_to_video, :reference_to_video, :edit_video
5
+ # HappyHorse video generation and editing API client.
6
+ #
7
+ # @example
8
+ # client = RunApi::HappyHorse::Client.new(api_key: "your-api-key")
9
+ # result = client.text_to_video.run(
10
+ # model: "happyhorse-text-to-video", prompt: "A horse galloping across a sunset beach"
11
+ # )
12
+ class Client < RunApi::Core::Client
13
+ # @return [Resources::TextToVideo] Text-to-video generation with optional character consistency.
14
+ attr_reader :text_to_video
15
+ # @return [Resources::ImageToVideo] Image-to-video animation from a first-frame image.
16
+ attr_reader :image_to_video
17
+ # @return [Resources::EditVideo] Video editing with text prompts and reference images.
18
+ attr_reader :edit_video
7
19
 
8
20
  def initialize(api_key: nil, **options)
9
- @api_key = Core::Auth.resolve_api_key(api_key)
10
-
11
- client_options = Core::ClientOptions.new(api_key: @api_key, **options)
12
- http = client_options.http_client || Core::HttpClient.new(client_options)
21
+ super
13
22
  @text_to_video = Resources::TextToVideo.new(http)
14
23
  @image_to_video = Resources::ImageToVideo.new(http)
15
- @reference_to_video = Resources::ReferenceToVideo.new(http)
16
24
  @edit_video = Resources::EditVideo.new(http)
17
25
  end
18
26
  end
@@ -3,6 +3,8 @@
3
3
  module RunApi
4
4
  module HappyHorse
5
5
  module Resources
6
+ # HappyHorse edit-video resource.
7
+ # Transform an existing video with a text prompt and optional reference images.
6
8
  class EditVideo
7
9
  include RunApi::Core::ResourceHelpers
8
10
 
@@ -16,17 +18,29 @@ module RunApi
16
18
  @http = http
17
19
  end
18
20
 
21
+ # Create an edit-video task and wait until complete.
22
+ #
23
+ # @param params [Hash] edit-video parameters
24
+ # @return [RunApi::HappyHorse::Types::CompletedEditVideoResponse] completed task with videos
19
25
  def run(**params)
20
26
  task = create(**params)
21
27
  poll_until_complete { get(task.id) }
22
28
  end
23
29
 
30
+ # Create an edit-video task.
31
+ #
32
+ # @param params [Hash] edit-video parameters
33
+ # @return [RunApi::HappyHorse::Types::EditVideoResponse] task creation result with id
24
34
  def create(**params)
25
35
  params = compact_params(params)
26
36
  validate_params!(params)
27
37
  request(:post, ENDPOINT, body: params)
28
38
  end
29
39
 
40
+ # Get edit-video task status by task ID.
41
+ #
42
+ # @param id [String] task ID
43
+ # @return [RunApi::HappyHorse::Types::EditVideoResponse] current task status
30
44
  def get(id)
31
45
  request(:get, "#{ENDPOINT}/#{id}")
32
46
  end
@@ -36,14 +50,14 @@ module RunApi
36
50
  def validate_params!(params)
37
51
  raise Core::ValidationError, "model is required" unless param(params, :model) == Types::EDIT_VIDEO_MODEL
38
52
  raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
39
- raise Core::ValidationError, "video_url is required" unless param(params, :video_url)
53
+ raise Core::ValidationError, "source_video_url is required" unless param(params, :source_video_url)
40
54
 
41
- reference_image = param(params, :reference_image)
42
- if reference_image && (!reference_image.is_a?(Array) || !REFERENCE_IMAGE_RANGE.cover?(reference_image.size))
43
- raise Core::ValidationError, "reference_image must include at most #{REFERENCE_IMAGE_RANGE.max} entries"
55
+ reference_image_urls = param(params, :reference_image_urls)
56
+ if reference_image_urls && (!reference_image_urls.is_a?(Array) || !REFERENCE_IMAGE_RANGE.cover?(reference_image_urls.size))
57
+ raise Core::ValidationError, "reference_image_urls must include at most #{REFERENCE_IMAGE_RANGE.max} entries"
44
58
  end
45
59
 
46
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
60
+ validate_optional!(params, :output_resolution, Types::OUTPUT_RESOLUTIONS)
47
61
  validate_optional!(params, :audio_setting, Types::AUDIO_SETTINGS)
48
62
  validate_integer_range!(params, :seed, Types::SEED_RANGE)
49
63
  end
@@ -52,8 +66,7 @@ module RunApi
52
66
  value = param(params, key)
53
67
  return unless value
54
68
 
55
- integer = Integer(value, exception: false)
56
- return if integer && range.cover?(integer)
69
+ return if value.is_a?(Integer) && range.cover?(value)
57
70
 
58
71
  raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
59
72
  end
@@ -3,6 +3,8 @@
3
3
  module RunApi
4
4
  module HappyHorse
5
5
  module Resources
6
+ # HappyHorse image-to-video resource.
7
+ # Animate a still first-frame image into video, guided by an optional text prompt.
6
8
  class ImageToVideo
7
9
  include RunApi::Core::ResourceHelpers
8
10
 
@@ -10,23 +12,34 @@ module RunApi
10
12
 
11
13
  RESPONSE_CLASS = Types::ImageToVideoResponse
12
14
  COMPLETED_RESPONSE_CLASS = Types::CompletedImageToVideoResponse
13
- IMAGE_URLS_MAX = 1
14
15
 
15
16
  def initialize(http)
16
17
  @http = http
17
18
  end
18
19
 
20
+ # Create an image-to-video task and wait until complete.
21
+ #
22
+ # @param params [Hash] image-to-video parameters
23
+ # @return [RunApi::HappyHorse::Types::CompletedImageToVideoResponse] completed task with videos
19
24
  def run(**params)
20
25
  task = create(**params)
21
26
  poll_until_complete { get(task.id) }
22
27
  end
23
28
 
29
+ # Create an image-to-video task.
30
+ #
31
+ # @param params [Hash] image-to-video parameters
32
+ # @return [RunApi::HappyHorse::Types::ImageToVideoResponse] task creation result with id
24
33
  def create(**params)
25
34
  params = compact_params(params)
26
35
  validate_params!(params)
27
36
  request(:post, ENDPOINT, body: params)
28
37
  end
29
38
 
39
+ # Get image-to-video task status by task ID.
40
+ #
41
+ # @param id [String] task ID
42
+ # @return [RunApi::HappyHorse::Types::ImageToVideoResponse] current task status
30
43
  def get(id)
31
44
  request(:get, "#{ENDPOINT}/#{id}")
32
45
  end
@@ -35,13 +48,10 @@ module RunApi
35
48
 
36
49
  def validate_params!(params)
37
50
  raise Core::ValidationError, "model is required" unless param(params, :model) == Types::IMAGE_TO_VIDEO_MODEL
51
+ raise Core::ValidationError, "first_frame_image_url is required" unless param(params, :first_frame_image_url)
38
52
 
39
- image_urls = param(params, :image_urls)
40
- raise Core::ValidationError, "image_urls is required" unless image_urls.is_a?(Array) && image_urls.any?
41
- raise Core::ValidationError, "image_urls supports at most #{IMAGE_URLS_MAX} entry" if image_urls.size > IMAGE_URLS_MAX
42
-
43
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
44
- validate_integer_range!(params, :duration, Types::DURATION_RANGE)
53
+ validate_optional!(params, :output_resolution, Types::OUTPUT_RESOLUTIONS)
54
+ validate_integer_range!(params, :duration_seconds, Types::DURATION_RANGE)
45
55
  validate_integer_range!(params, :seed, Types::SEED_RANGE)
46
56
  end
47
57
 
@@ -49,8 +59,7 @@ module RunApi
49
59
  value = param(params, key)
50
60
  return unless value
51
61
 
52
- integer = Integer(value, exception: false)
53
- return if integer && range.cover?(integer)
62
+ return if value.is_a?(Integer) && range.cover?(value)
54
63
 
55
64
  raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
56
65
  end
@@ -3,6 +3,8 @@
3
3
  module RunApi
4
4
  module HappyHorse
5
5
  module Resources
6
+ # HappyHorse text-to-video resource.
7
+ # Generate video from a text prompt, with optional character consistency via happyhorse-character.
6
8
  class TextToVideo
7
9
  include RunApi::Core::ResourceHelpers
8
10
 
@@ -10,22 +12,35 @@ module RunApi
10
12
 
11
13
  RESPONSE_CLASS = Types::TextToVideoResponse
12
14
  COMPLETED_RESPONSE_CLASS = Types::CompletedTextToVideoResponse
15
+ REFERENCE_IMAGE_URLS_RANGE = (1..9)
13
16
 
14
17
  def initialize(http)
15
18
  @http = http
16
19
  end
17
20
 
21
+ # Create a text-to-video task and wait until complete.
22
+ #
23
+ # @param params [Hash] text-to-video parameters
24
+ # @return [RunApi::HappyHorse::Types::CompletedTextToVideoResponse] completed task with videos
18
25
  def run(**params)
19
26
  task = create(**params)
20
27
  poll_until_complete { get(task.id) }
21
28
  end
22
29
 
30
+ # Create a text-to-video task.
31
+ #
32
+ # @param params [Hash] text-to-video parameters
33
+ # @return [RunApi::HappyHorse::Types::TextToVideoResponse] task creation result with id
23
34
  def create(**params)
24
35
  params = compact_params(params)
25
36
  validate_params!(params)
26
37
  request(:post, ENDPOINT, body: params)
27
38
  end
28
39
 
40
+ # Get text-to-video task status by task ID.
41
+ #
42
+ # @param id [String] task ID
43
+ # @return [RunApi::HappyHorse::Types::TextToVideoResponse] current task status
29
44
  def get(id)
30
45
  request(:get, "#{ENDPOINT}/#{id}")
31
46
  end
@@ -33,12 +48,22 @@ module RunApi
33
48
  private
34
49
 
35
50
  def validate_params!(params)
36
- raise Core::ValidationError, "model is required" unless param(params, :model) == Types::TEXT_TO_VIDEO_MODEL
51
+ model = param(params, :model)
52
+ raise Core::ValidationError, "model is required" unless Types::TEXT_TO_VIDEO_MODELS.include?(model)
37
53
  raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
38
54
 
39
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
55
+ reference_image_urls = param(params, :reference_image_urls)
56
+ if model == Types::CHARACTER_MODEL
57
+ unless reference_image_urls.is_a?(Array) && REFERENCE_IMAGE_URLS_RANGE.cover?(reference_image_urls.size)
58
+ raise Core::ValidationError, "reference_image_urls must include between #{REFERENCE_IMAGE_URLS_RANGE.min} and #{REFERENCE_IMAGE_URLS_RANGE.max} entries"
59
+ end
60
+ elsif reference_image_urls
61
+ raise Core::ValidationError, "reference_image_urls is only supported for #{Types::CHARACTER_MODEL}"
62
+ end
63
+
64
+ validate_optional!(params, :output_resolution, Types::OUTPUT_RESOLUTIONS)
40
65
  validate_optional!(params, :aspect_ratio, Types::ASPECT_RATIOS)
41
- validate_integer_range!(params, :duration, Types::DURATION_RANGE)
66
+ validate_integer_range!(params, :duration_seconds, Types::DURATION_RANGE)
42
67
  validate_integer_range!(params, :seed, Types::SEED_RANGE)
43
68
  end
44
69
 
@@ -46,8 +71,7 @@ module RunApi
46
71
  value = param(params, key)
47
72
  return unless value
48
73
 
49
- integer = Integer(value, exception: false)
50
- return if integer && range.cover?(integer)
74
+ return if value.is_a?(Integer) && range.cover?(value)
51
75
 
52
76
  raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
53
77
  end
@@ -2,17 +2,28 @@
2
2
 
3
3
  module RunApi
4
4
  module HappyHorse
5
+ # Type definitions and constants for HappyHorse video generation and editing.
5
6
  module Types
7
+ # Standard text-to-video model.
6
8
  TEXT_TO_VIDEO_MODEL = "happyhorse-text-to-video"
9
+ # Character-consistent model; requires 1-9 reference_image_urls.
10
+ CHARACTER_MODEL = "happyhorse-character"
11
+ # All text-to-video model variants.
12
+ TEXT_TO_VIDEO_MODELS = [TEXT_TO_VIDEO_MODEL, CHARACTER_MODEL].freeze
7
13
  IMAGE_TO_VIDEO_MODEL = "happyhorse-image-to-video"
8
- REFERENCE_TO_VIDEO_MODEL = "happyhorse-reference-to-video"
9
- EDIT_VIDEO_MODEL = "happyhorse-video-edit"
10
- RESOLUTIONS = %w[720p 1080p].freeze
14
+ EDIT_VIDEO_MODEL = "happyhorse-edit-video"
15
+ # Output resolution options. Defaults to 1080p.
16
+ OUTPUT_RESOLUTIONS = %w[720p 1080p].freeze
17
+ # Aspect ratio options. Defaults to 16:9.
11
18
  ASPECT_RATIOS = %w[16:9 9:16 1:1 4:3 3:4].freeze
12
- AUDIO_SETTINGS = %w[auto origin].freeze
19
+ # Audio handling for video editing: "auto" lets the model decide, "original" preserves source audio.
20
+ AUDIO_SETTINGS = %w[auto original].freeze
21
+ # Duration range in seconds (3-15). Defaults to 5.
13
22
  DURATION_RANGE = (3..15)
23
+ # Reproducibility seed range.
14
24
  SEED_RANGE = (0..2_147_483_647)
15
25
 
26
+ # A generated video file with a download URL.
16
27
  class MediaUrl < RunApi::Core::BaseModel
17
28
  optional :url, String
18
29
  end
@@ -24,14 +35,14 @@ module RunApi
24
35
  optional :error, String
25
36
  end
26
37
 
38
+ # Narrowed response returned by +run()+ once polling observes +status: "completed"+.
39
+ # +videos+ is required so consumers never have to null-check it on a successful task.
27
40
  class CompletedTextToVideoResponse < TextToVideoResponse
28
41
  required :videos, [-> { MediaUrl }]
29
42
  end
30
43
 
31
44
  ImageToVideoResponse = TextToVideoResponse
32
45
  CompletedImageToVideoResponse = CompletedTextToVideoResponse
33
- ReferenceToVideoResponse = TextToVideoResponse
34
- CompletedReferenceToVideoResponse = CompletedTextToVideoResponse
35
46
  EditVideoResponse = TextToVideoResponse
36
47
  CompletedEditVideoResponse = CompletedTextToVideoResponse
37
48
  end
@@ -4,7 +4,6 @@ require "runapi/core"
4
4
  require_relative "happyhorse/types"
5
5
  require_relative "happyhorse/resources/edit_video"
6
6
  require_relative "happyhorse/resources/image_to_video"
7
- require_relative "happyhorse/resources/reference_to_video"
8
7
  require_relative "happyhorse/resources/text_to_video"
9
8
  require_relative "happyhorse/client"
10
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: runapi-happyhorse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - RunAPI
@@ -15,18 +15,17 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.2.4
18
+ version: 0.2.6
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.2.4
25
+ version: 0.2.6
26
26
  description: The happyhorse ai api Ruby SDK is the language-specific package for HappyHorse
27
- on RunAPI. Use this package for text, image, reference-to-video, and edit-video
28
- workflows that need JSON request bodies, task status lookup, and consistent RunAPI
29
- errors in Ruby.
27
+ on RunAPI. Use this package for text, image, and edit-video workflows that need
28
+ JSON request bodies, task status lookup, and consistent RunAPI errors in Ruby.
30
29
  email:
31
30
  - contact@runapi.ai
32
31
  executables: []
@@ -41,7 +40,6 @@ files:
41
40
  - lib/runapi/happyhorse/client.rb
42
41
  - lib/runapi/happyhorse/resources/edit_video.rb
43
42
  - lib/runapi/happyhorse/resources/image_to_video.rb
44
- - lib/runapi/happyhorse/resources/reference_to_video.rb
45
43
  - lib/runapi/happyhorse/resources/text_to_video.rb
46
44
  - lib/runapi/happyhorse/types.rb
47
45
  homepage: https://runapi.ai/models/happyhorse
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RunApi
4
- module HappyHorse
5
- module Resources
6
- class ReferenceToVideo
7
- include RunApi::Core::ResourceHelpers
8
-
9
- ENDPOINT = "/api/v1/happyhorse/reference_to_video"
10
-
11
- RESPONSE_CLASS = Types::ReferenceToVideoResponse
12
- COMPLETED_RESPONSE_CLASS = Types::CompletedReferenceToVideoResponse
13
- REFERENCE_IMAGE_RANGE = (1..9)
14
-
15
- def initialize(http)
16
- @http = http
17
- end
18
-
19
- def run(**params)
20
- task = create(**params)
21
- poll_until_complete { get(task.id) }
22
- end
23
-
24
- def create(**params)
25
- params = compact_params(params)
26
- validate_params!(params)
27
- request(:post, ENDPOINT, body: params)
28
- end
29
-
30
- def get(id)
31
- request(:get, "#{ENDPOINT}/#{id}")
32
- end
33
-
34
- private
35
-
36
- def validate_params!(params)
37
- raise Core::ValidationError, "model is required" unless param(params, :model) == Types::REFERENCE_TO_VIDEO_MODEL
38
- raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
39
-
40
- reference_image = param(params, :reference_image)
41
- unless reference_image.is_a?(Array) && REFERENCE_IMAGE_RANGE.cover?(reference_image.size)
42
- raise Core::ValidationError, "reference_image must include between #{REFERENCE_IMAGE_RANGE.min} and #{REFERENCE_IMAGE_RANGE.max} entries"
43
- end
44
-
45
- validate_optional!(params, :resolution, Types::RESOLUTIONS)
46
- validate_optional!(params, :aspect_ratio, Types::ASPECT_RATIOS)
47
- validate_integer_range!(params, :duration, Types::DURATION_RANGE)
48
- validate_integer_range!(params, :seed, Types::SEED_RANGE)
49
- end
50
-
51
- def validate_integer_range!(params, key, range)
52
- value = param(params, key)
53
- return unless value
54
-
55
- integer = Integer(value, exception: false)
56
- return if integer && range.cover?(integer)
57
-
58
- raise Core::ValidationError, "#{key} must be an integer between #{range.min} and #{range.max}"
59
- end
60
- end
61
- end
62
- end
63
- end