or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dotnet.mdexpression-factory.mdgo.mdindex.mdjava.mdjavascript-typescript.mdparameter-types.mdpython.mdruby.md

ruby.mddocs/

0

# Ruby Implementation

1

2

Idiomatic Ruby implementation with clean APIs, module-based organization, and full integration with Ruby BDD testing frameworks like Cucumber-Ruby and RSpec.

3

4

## Package Information

5

6

- **Gem Name**: `cucumber-cucumber-expressions`

7

- **Language**: Ruby 2.5+

8

- **Installation**: `gem install cucumber-cucumber-expressions`

9

- **Module**: `Cucumber::CucumberExpressions`

10

11

## Core Imports

12

13

```ruby

14

require 'cucumber-cucumber-expressions'

15

16

# Access classes through module

17

include Cucumber::CucumberExpressions

18

19

# Or use fully qualified names

20

Cucumber::CucumberExpressions::CucumberExpression

21

Cucumber::CucumberExpressions::ParameterType

22

Cucumber::CucumberExpressions::ParameterTypeRegistry

23

```

24

25

## Capabilities

26

27

### Expression Creation and Matching

28

29

Create and match Cucumber expressions with Ruby-style method naming and return patterns.

30

31

```ruby { .api }

32

module Cucumber::CucumberExpressions

33

# Main class for parsing and matching Cucumber expressions

34

class CucumberExpression

35

# Create a new Cucumber expression

36

# @param expression [String] The Cucumber expression string

37

# @param parameter_type_registry [ParameterTypeRegistry] Registry containing parameter types

38

def initialize(expression, parameter_type_registry)

39

end

40

41

# Match text against this expression and extract arguments

42

# @param text [String] Text to match against the expression

43

# @return [Array<Argument>, nil] Array of matched arguments or nil if no match

44

def match(text)

45

end

46

47

# Get the original expression string

48

# @return [String] The source expression

49

def source

50

end

51

52

# Get the compiled regular expression

53

# @return [Regexp] The regex pattern

54

def regexp

55

end

56

57

# String representation of the expression

58

# @return [String] Source expression

59

def to_s

60

end

61

end

62

end

63

```

64

65

**Usage Examples:**

66

67

```ruby

68

require 'cucumber-cucumber-expressions'

69

include Cucumber::CucumberExpressions

70

71

# Create registry with built-in parameter types

72

registry = ParameterTypeRegistry.new

73

74

# Simple integer parameter

75

expr1 = CucumberExpression.new('I have {int} cucumbers', registry)

76

args1 = expr1.match('I have 42 cucumbers')

77

if args1

78

puts args1[0].value # 42 (Integer)

79

end

80

81

# Multiple parameters

82

expr2 = CucumberExpression.new('User {word} has {int} items', registry)

83

args2 = expr2.match('User alice has 42 items')

84

if args2

85

username = args2[0].value # "alice" (String)

86

item_count = args2[1].value # 42 (Integer)

87

puts "User: #{username}, Items: #{item_count}"

88

end

89

90

# Optional text

91

expr3 = CucumberExpression.new('I have {int} cucumber(s)', registry)

92

puts expr3.match('I have 1 cucumber') ? 'matches' : 'no match' # matches

93

puts expr3.match('I have 5 cucumbers') ? 'matches' : 'no match' # matches

94

95

# Alternative text

96

expr4 = CucumberExpression.new('I put it in my belly/stomach', registry)

97

puts expr4.match('I put it in my belly') ? 'matches' : 'no match' # matches

98

puts expr4.match('I put it in my stomach') ? 'matches' : 'no match' # matches

99

100

# String parameters (removes quotes)

101

expr5 = CucumberExpression.new('I say {string}', registry)

102

args5 = expr5.match('I say "hello world"')

103

if args5

104

puts args5[0].value # "hello world" (without quotes)

105

end

106

107

# Expression introspection

108

puts expr1.source # "I have {int} cucumbers"

109

puts expr1.regexp # Compiled regex pattern

110

puts expr1.to_s # "I have {int} cucumbers"

111

```

112

113

### Parameter Type Definition

114

115

Define custom parameter types with Ruby-style APIs and flexible transformation blocks.

116

117

```ruby { .api }

118

module Cucumber::CucumberExpressions

119

# Defines a parameter type with name, patterns, and transformer

120

class ParameterType

121

# Pattern for illegal parameter names

122

ILLEGAL_PARAMETER_NAME_PATTERN = /([\[\]()$.|?*+])/.freeze

123

124

# Pattern for unescaping characters

125

UNESCAPE_PATTERN = /(\\([\[$.|?*+\]]))/.freeze

126

127

# Create a new parameter type

128

# @param name [String] Name used in expressions

129

# @param regexp [Regexp, Array<Regexp>, String, Array<String>] Pattern(s) to match

130

# @param type [Class] Ruby class for the result type

131

# @param transformer [Proc] Block to transform matched strings

132

# @param use_for_snippets [Boolean] Whether to use for snippet generation

133

# @param prefer_for_regexp_match [Boolean] Whether to prefer for regexp matches

134

def initialize(name, regexp, type, transformer, use_for_snippets, prefer_for_regexp_match)

135

end

136

137

# Check if parameter type name is valid

138

# @param type_name [String] Name to validate

139

# @raises [CucumberExpressions::CucumberExpressionError] if invalid

140

def self.check_parameter_type_name(type_name)

141

end

142

143

# Test if parameter type name is valid

144

# @param type_name [String] Name to test

145

# @return [Boolean] true if valid

146

def self.is_valid_parameter_type_name(type_name)

147

end

148

149

# Transform matched groups to target type

150

# @param self_obj [Object] Context object for transformation

151

# @param group_values [Array<String>] Matched string groups

152

# @return [Object] Transformed value

153

def transform(self_obj, group_values)

154

end

155

156

# Compare parameter types for sorting (implements Comparable)

157

# @param other [ParameterType] Other parameter type to compare

158

# @return [Integer] Comparison result (-1, 0, 1)

159

def <=>(other)

160

end

161

162

# Attribute readers

163

attr_reader :name, :type, :transformer, :use_for_snippets, :prefer_for_regexp_match, :regexps

164

end

165

end

166

```

167

168

**Usage Examples:**

169

170

```ruby

171

require 'cucumber-cucumber-expressions'

172

include Cucumber::CucumberExpressions

173

174

# Simple enum-like parameter type

175

color_type = ParameterType.new(

176

'color',

177

/red|green|blue|yellow/,

178

String,

179

->(color) { color.upcase },

180

true, # use_for_snippets

181

false # prefer_for_regexp_match

182

)

183

184

# Custom object parameter type

185

class Point

186

attr_reader :x, :y

187

188

def initialize(x, y)

189

@x = x.to_i

190

@y = y.to_i

191

end

192

193

def to_s

194

"(#{@x}, #{@y})"

195

end

196

end

197

198

point_type = ParameterType.new(

199

'point',

200

/\((-?\d+),\s*(-?\d+)\)/,

201

Point,

202

->(x, y) { Point.new(x, y) },

203

true,

204

false

205

)

206

207

# Date parameter type with validation

208

require 'date'

209

210

date_type = ParameterType.new(

211

'date',

212

/(\d{4})-(\d{2})-(\d{2})/,

213

Date,

214

lambda do |year, month, day|

215

year_i = year.to_i

216

month_i = month.to_i

217

day_i = day.to_i

218

219

raise ArgumentError, "Invalid month: #{month_i}" unless (1..12).include?(month_i)

220

raise ArgumentError, "Invalid day: #{day_i}" unless (1..31).include?(day_i)

221

222

Date.new(year_i, month_i, day_i)

223

end,

224

true,

225

false

226

)

227

228

# Money parameter type with BigDecimal

229

require 'bigdecimal'

230

231

class Money

232

attr_reader :amount, :currency

233

234

def initialize(amount, currency)

235

@amount = BigDecimal(amount.to_s)

236

@currency = currency.upcase

237

end

238

239

def to_s

240

"#{@amount} #{@currency}"

241

end

242

end

243

244

money_type = ParameterType.new(

245

'money',

246

/\$(\d+(?:\.\d{2})?) (USD|EUR|GBP)/,

247

Money,

248

->(amount, currency) { Money.new(amount, currency) },

249

true,

250

false

251

)

252

253

# User type with hash return

254

user_type = ParameterType.new(

255

'user',

256

/(\w+):(\d+):([^:]+)/,

257

Hash,

258

lambda do |name, age, email|

259

{

260

name: name,

261

age: age.to_i,

262

email: email

263

}

264

end,

265

true,

266

false

267

)

268

269

# Register and use parameter types

270

registry = ParameterTypeRegistry.new

271

registry.define_parameter_type(color_type)

272

registry.define_parameter_type(point_type)

273

registry.define_parameter_type(date_type)

274

registry.define_parameter_type(money_type)

275

registry.define_parameter_type(user_type)

276

277

# Use in expressions

278

color_expr = CucumberExpression.new('I have a {color} car', registry)

279

result = color_expr.match('I have a red car')

280

puts result[0].value # "RED"

281

282

point_expr = CucumberExpression.new('Move to {point}', registry)

283

result = point_expr.match('Move to (10, -5)')

284

point = result[0].value

285

puts "Point: #{point}" # "Point: (10, -5)"

286

puts "X: #{point.x}, Y: #{point.y}" # "X: 10, Y: -5"

287

288

date_expr = CucumberExpression.new('Meeting on {date}', registry)

289

result = date_expr.match('Meeting on 2023-12-25')

290

date = result[0].value

291

puts date.strftime('%B %d, %Y') # "December 25, 2023"

292

293

money_expr = CucumberExpression.new('Price is {money}', registry)

294

result = money_expr.match('Price is $29.99 USD')

295

money = result[0].value

296

puts money # "29.99 USD"

297

puts money.amount.class # BigDecimal

298

299

user_expr = CucumberExpression.new('Create {user}', registry)

300

result = user_expr.match('Create alice:25:alice@example.com')

301

user = result[0].value

302

puts "User: #{user[:name]}, Age: #{user[:age]}, Email: #{user[:email]}"

303

```

304

305

### Parameter Type Registry

306

307

Ruby-style registry with snake_case method names and Enumerable support.

308

309

```ruby { .api }

310

module Cucumber::CucumberExpressions

311

# Registry for managing parameter types

312

class ParameterTypeRegistry

313

# Create a new parameter type registry with built-in types

314

def initialize

315

end

316

317

# Look up parameter type by name

318

# @param name [String] Name of parameter type

319

# @return [ParameterType, nil] Parameter type or nil if not found

320

def lookup_by_type_name(name)

321

end

322

323

# Look up parameter type by regular expression pattern

324

# @param parameter_type_regexp [String] Regular expression to match

325

# @param expression_regexp [Regexp] Full expression regexp

326

# @param text [String] Text being matched

327

# @return [ParameterType, nil] Matching parameter type or nil

328

def lookup_by_regexp(parameter_type_regexp, expression_regexp, text)

329

end

330

331

# Register a new parameter type

332

# @param parameter_type [ParameterType] Parameter type to register

333

def define_parameter_type(parameter_type)

334

end

335

336

# Get all registered parameter types

337

# @return [Array<ParameterType>] List of parameter types

338

def parameter_types

339

end

340

end

341

end

342

```

343

344

**Usage Examples:**

345

346

```ruby

347

registry = ParameterTypeRegistry.new

348

349

# Check built-in types

350

int_type = registry.lookup_by_type_name('int')

351

puts int_type.name # "int"

352

puts int_type.type # Integer

353

354

# Iterate over all parameter types

355

registry.parameter_types.each do |param_type|

356

puts "#{param_type.name}: #{param_type.regexps.join(', ')}"

357

end

358

359

# Define and retrieve custom type

360

uuid_type = ParameterType.new(

361

'uuid',

362

/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/,

363

String,

364

->(uuid) { uuid.upcase },

365

true,

366

false

367

)

368

369

registry.define_parameter_type(uuid_type)

370

retrieved = registry.lookup_by_type_name('uuid')

371

puts retrieved == uuid_type # true

372

373

# Registry acts as a collection

374

parameter_count = registry.parameter_types.size

375

puts "Total parameter types: #{parameter_count}"

376

```

377

378

### Expression Generation

379

380

Generate Cucumber expressions from example text with Ruby-style APIs.

381

382

```ruby { .api }

383

module Cucumber::CucumberExpressions

384

# Generates Cucumber expressions from example text

385

class CucumberExpressionGenerator

386

# Create generator with parameter type registry

387

# @param parameter_type_registry [ParameterTypeRegistry] Registry containing parameter types

388

def initialize(parameter_type_registry)

389

end

390

391

# Generate expressions from example text

392

# @param text [String] Example text to generate expressions from

393

# @return [Array<GeneratedExpression>] Array of generated expressions

394

def generate_expressions(text)

395

end

396

end

397

398

# Generated expression with metadata

399

class GeneratedExpression

400

# Create generated expression

401

# @param expression_template [String] Template with parameter placeholders

402

# @param parameter_types [Array<ParameterType>] Parameter types in order

403

def initialize(expression_template, parameter_types)

404

end

405

406

# Get the generated expression source

407

# @return [String] Expression string

408

def source

409

end

410

411

# Get parameter names for code generation

412

# @return [Array<String>] Parameter names

413

def parameter_names

414

end

415

416

# Get parameter types in declaration order

417

# @return [Array<ParameterType>] Parameter types

418

def parameter_types

419

end

420

end

421

end

422

```

423

424

**Usage Examples:**

425

426

```ruby

427

registry = ParameterTypeRegistry.new

428

generator = CucumberExpressionGenerator.new(registry)

429

430

# Generate from text with numbers

431

expressions = generator.generate_expressions('I have 42 cucumbers')

432

puts expressions[0].source # "I have {int} cucumbers"

433

puts expressions[0].parameter_names # ["int"]

434

435

# Generate from text with strings

436

expressions = generator.generate_expressions('I select "Premium Plan" option')

437

puts expressions[0].source # "I select {string} option"

438

439

# Generate from complex text

440

expressions = generator.generate_expressions('User alice with age 25 has balance 123.45')

441

expressions.each_with_index do |expr, index|

442

puts "Option #{index + 1}: #{expr.source}"

443

puts "Parameters: #{expr.parameter_types.map(&:name).join(', ')}"

444

end

445

446

# Generate step definition template

447

expressions = generator.generate_expressions('Order contains 5 items')

448

best = expressions[0]

449

puts "Given(/^#{best.source}$/) do |#{best.parameter_names.join(', ')}|"

450

puts " # Implementation here"

451

puts "end"

452

453

# With parameter type hints

454

param_hints = best.parameter_types.map { |pt| ruby_type_hint(pt) }

455

puts "\n# With type hints:"

456

puts "Given(/^#{best.source}$/) do |#{best.parameter_names.zip(param_hints).map { |name, type| "#{name} # #{type}" }.join(', ')}|"

457

puts " # Implementation here"

458

puts "end"

459

460

def ruby_type_hint(param_type)

461

case param_type.name

462

when 'int' then 'Integer'

463

when 'float' then 'Float'

464

when 'string', 'word' then 'String'

465

else param_type.type.name

466

end

467

end

468

```

469

470

### Other Key Classes

471

472

Supporting classes with Ruby conventions and patterns.

473

474

```ruby { .api }

475

module Cucumber::CucumberExpressions

476

# Represents a matched argument from an expression

477

class Argument

478

# Create argument with group and parameter type

479

# @param group [Group] Matched group from regex

480

# @param parameter_type [ParameterType] Parameter type for transformation

481

def initialize(group, parameter_type)

482

end

483

484

# Get the transformed value

485

# @return [Object] Transformed value

486

def value

487

end

488

489

# Get the matched group

490

# @return [Group] Group with position and text

491

def group

492

end

493

494

# Get the parameter type

495

# @return [ParameterType] Parameter type used for transformation

496

def parameter_type

497

end

498

end

499

500

# Regular expression implementation of expression interface

501

class RegularExpression

502

# Create regular expression

503

# @param regexp [Regexp] Regular expression pattern

504

# @param parameter_type_registry [ParameterTypeRegistry] Registry for parameter types

505

def initialize(regexp, parameter_type_registry)

506

end

507

508

# Match text against regular expression

509

# @param text [String] Text to match

510

# @return [Array<Argument>, nil] Array of arguments or nil if no match

511

def match(text)

512

end

513

514

# Get the source pattern

515

# @return [String] Source pattern

516

def source

517

end

518

519

# Get the regular expression

520

# @return [Regexp] Regex pattern

521

def regexp

522

end

523

end

524

525

# Factory for creating expressions with automatic type detection

526

class ExpressionFactory

527

# Create expression factory with parameter type registry

528

# @param parameter_type_registry [ParameterTypeRegistry] Registry for parameter types

529

def initialize(parameter_type_registry)

530

end

531

532

# Create expression from string or regex

533

# @param expression [String, Regexp] Expression to create

534

# @return [CucumberExpression, RegularExpression] Expression instance

535

def create_expression(expression)

536

end

537

end

538

end

539

```

540

541

**Usage Examples:**

542

543

```ruby

544

# Argument extraction

545

registry = ParameterTypeRegistry.new

546

expr = CucumberExpression.new('User {word} has {int} items', registry)

547

548

args = expr.match('User alice has 42 items')

549

if args

550

# Access values and metadata

551

username = args[0].value # "alice"

552

item_count = args[1].value # 42

553

554

# Parameter type information

555

puts args[0].parameter_type.name # "word"

556

puts args[1].parameter_type.name # "int"

557

558

# Group information

559

puts args[0].group.value # "alice"

560

puts args[0].group.start # position in text

561

puts args[0].group.end # end position

562

end

563

564

# Expression factory

565

factory = ExpressionFactory.new(registry)

566

567

# Create Cucumber expression

568

cucumber_expr = factory.create_expression('I have {int} items')

569

puts cucumber_expr.class # CucumberExpression

570

571

# Create regular expression

572

regex_expr = factory.create_expression(/^I have (\d+) items$/)

573

puts regex_expr.class # RegularExpression

574

575

# Both respond to same interface

576

puts cucumber_expr.source

577

puts regex_expr.source

578

```

579

580

### Built-in Parameter Types

581

582

Ruby implementation provides built-in parameter types with appropriate Ruby type conversion.

583

584

```ruby { .api }

585

# Built-in parameter types in Ruby implementation:

586

587

{int} # Converts to Integer

588

{float} # Converts to Float

589

{word} # Returns as String (single word)

590

{string} # Returns as String (removes quotes)

591

{bigdecimal} # Converts to BigDecimal

592

{double} # Converts to Float (64-bit)

593

{biginteger} # Converts to Integer (Ruby integers are arbitrary precision)

594

{byte} # Converts to Integer (8-bit range)

595

{short} # Converts to Integer (16-bit range)

596

{long} # Converts to Integer (64-bit range)

597

{} # Anonymous - returns as String

598

```

599

600

**Usage Examples:**

601

602

```ruby

603

require 'bigdecimal'

604

605

registry = ParameterTypeRegistry.new

606

607

# Test all built-in types

608

expr = CucumberExpression.new(

609

'Values: {int} {float} {word} {string} {bigdecimal}',

610

registry

611

)

612

613

args = expr.match('Values: 42 3.14 hello "world test" 123.456789')

614

if args

615

puts "int: #{args[0].value} (#{args[0].value.class})" # 42 (Integer)

616

puts "float: #{args[1].value} (#{args[1].value.class})" # 3.14 (Float)

617

puts "word: #{args[2].value} (#{args[2].value.class})" # hello (String)

618

puts "string: #{args[3].value} (#{args[3].value.class})" # world test (String)

619

puts "bigdecimal: #{args[4].value} (#{args[4].value.class})" # 123.456789 (BigDecimal)

620

end

621

```

622

623

### Integration with Ruby Testing Frameworks

624

625

Common patterns for integrating with Cucumber-Ruby, RSpec, and other Ruby BDD frameworks.

626

627

```ruby

628

# Cucumber-Ruby integration

629

require 'cucumber'

630

require 'cucumber-cucumber-expressions'

631

632

# Set up parameter types in env.rb or support file

633

Before do

634

@registry = Cucumber::CucumberExpressions::ParameterTypeRegistry.new

635

636

# Custom parameter types

637

color_type = Cucumber::CucumberExpressions::ParameterType.new(

638

'color',

639

/red|green|blue/,

640

String,

641

->(color) { color.upcase },

642

true,

643

false

644

)

645

@registry.define_parameter_type(color_type)

646

end

647

648

# Step definitions using built-in types

649

Given(/^I have (\d+) cucumbers$/) do |count|

650

# count is passed as string, convert manually

651

@cucumber_count = count.to_i

652

end

653

654

# Or use Cucumber-Ruby's built-in parameter type system

655

Given('I have {int} cucumbers') do |count|

656

# count is already converted to Integer

657

@cucumber_count = count

658

end

659

660

Given('I have a {color} car') do |color|

661

# color is converted using custom parameter type

662

@car_color = color

663

end

664

665

# RSpec integration example

666

require 'rspec'

667

require 'cucumber-cucumber-expressions'

668

669

RSpec.describe 'Cucumber Expressions' do

670

let(:registry) { Cucumber::CucumberExpressions::ParameterTypeRegistry.new }

671

672

it 'matches parameters correctly' do

673

expr = Cucumber::CucumberExpressions::CucumberExpression.new(

674

'User {word} has {int} items',

675

registry

676

)

677

678

args = expr.match('User alice has 42 items')

679

680

expect(args).not_to be_nil

681

expect(args[0].value).to eq('alice')

682

expect(args[1].value).to eq(42)

683

expect(args[1].value).to be_a(Integer)

684

end

685

end

686

687

# Custom matcher for RSpec

688

RSpec::Matchers.define :match_expression do |text|

689

match do |expression|

690

@result = expression.match(text)

691

!@result.nil?

692

end

693

694

failure_message do |expression|

695

"expected #{expression.source} to match '#{text}'"

696

end

697

698

chain :with_arguments do |*expected_args|

699

@expected_args = expected_args

700

end

701

702

match do |expression|

703

@result = expression.match(text)

704

return false if @result.nil?

705

706

if @expected_args

707

actual_args = @result.map(&:value)

708

actual_args == @expected_args

709

else

710

true

711

end

712

end

713

end

714

715

# Usage:

716

# expect(expression).to match_expression('User alice has 42 items').with_arguments('alice', 42)

717

```

718

719

The Ruby implementation provides idiomatic Ruby APIs with flexible parameter types, clean method naming, and seamless integration with Ruby BDD testing frameworks while maintaining full compatibility with the Cucumber Expressions specification.