How does Selenium's Ruby client spell a locator such as an id, compared with Java's By?
answer
- Ruby prefers a hash to an object
- The key names the strategy
- No By factory call appears at all
- Look for css: rather than cssSelector
- Predicates end in a question mark
basics
~10 sRuby passes a hash whose key names the strategy: find_element(id: 'term-average'). There is no locator object to build, unlike Java's By.id, and the two-positional form find_element(:id, 'term-average') also works.
solid answer
~30 sThe Ruby client takes the strategy as a keyword and the target as its value: `driver.find_element(id: 'term-average')`, `driver.find_elements(css: '.grade-row')`, `driver.find_element(xpath: "//h1")`. The accepted keys mirror the standard strategies in snake_case - `id`, `name`, `class_name`, `tag_name`, `css`, `xpath`, `link_text`, `partial_link_text` - and the older positional pair `find_element(:id, 'term-average')` still works. Java instead builds an object with `By.id("term-average")` and passes it as one argument. The rest of the Ruby dialect follows the same instinct: `element.text` rather than `getText()`, `element.displayed?` rather than `isDisplayed()`, and `driver.manage.timeouts.implicit_wait = 5` as an assignment rather than a call.
code
ruby · 14 linesrequire 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.navigate.to 'https://school.example/report-cards'
average = driver.find_element(id: 'term-average')
rows = driver.find_elements(css: '.grade-row')
puts average.text if average.displayed?
puts rows.size
ensure
driver.quit
endgo deeper
Recognise the hash form when you see it and be able to write the everyday keys: id, name, css, xpath. Recall that Ruby booleans end in a question mark.
Explain that the key plays the role of Java's By factory, that the positional symbol form is equivalent, and that Ruby's wait takes a block rather than a condition object.
Show you can read a Ruby sample fluently enough to lift its intent into whatever binding your suite uses, and that you know a mistyped key fails only at run time.
Judge whether letting one team write in a different binding is worth the loss of shared helpers and review fluency, and what has to be common if you allow it.
## The keyword form Selenium's Ruby client spells a locator as a **hash argument** whose key names the strategy and whose value is the target: ```ruby average = driver.find_element(id: 'term-average') rows = driver.find_elements(css: '.grade-row') header = driver.find_element(xpath: "//h1[contains(., 'Report card')]") ``` There is no locator object to build. The key `id:` plays the part Java gives to `By.id(...)` and Python gives to the `By.ID` constant, and the value is the same selector string you would write anywhere else. The Ruby client also accepts the two-positional form, `driver.find_element(:id, 'term-average')`, which is the same pair written as a symbol and a string; the keyword form is what you will see in current samples and documentation. ## Which keys the client accepts The keys mirror the standard lookup strategies, in Ruby's snake_case: - `id:` and `name:` - `class_name:` and `tag_name:` - `css:` and `xpath:` - `link_text:` and `partial_link_text:` Note `css:` rather than Java's `cssSelector` or Python's `CSS_SELECTOR` - the shortest spelling of the three, and the one that trips a Java reader copying a selector across. ## The rest of the Ruby dialect The locator is the most visible difference, but a Ruby sample looks unfamiliar for four more reasons, all of them naming conventions rather than behaviour: - **snake_case everywhere.** `find_element`, `find_elements`, `send_keys`, `current_url`, `page_source`, `window_handles`. - **No `get` prefix on readers.** Java's `getText()` is `element.text`; `getTitle()` is `driver.title`; `getCurrentUrl()` is `driver.current_url`. - **Question marks on booleans.** `element.displayed?`, `element.enabled?`, `element.selected?` - Ruby's convention for predicate methods, matching Java's `isDisplayed()`, Python's `is_displayed()` and C#'s `Displayed` property. - **Attribute assignment for settings.** A timeout is set, not called: `driver.manage.timeouts.implicit_wait = 5`, where Java writes `driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5))`. Ruby also drops the empty parentheses on `manage` and `timeouts`. Waits follow the same instinct. Ruby builds `Selenium::WebDriver::Wait.new(timeout: 10)` - the timeout again a keyword, in seconds - and `until` takes a **block** whose truthy return value ends the wait: ```ruby wait = Selenium::WebDriver::Wait.new(timeout: 10) wait.until { driver.find_element(id: 'term-average').displayed? } ``` Where Java hands `until` a condition object built by a factory, Ruby hands it a block of ordinary code. That is the single biggest shape difference between a Java sample and a Ruby one, and it is why a Ruby wait rarely mentions any condition helper at all. ## Reading a Ruby sample as a Java engineer | Java | Ruby | |---|---| | `driver.findElement(By.id("term-average"))` | `driver.find_element(id: 'term-average')` | | `element.getText()` | `element.text` | | `element.isDisplayed()` | `element.displayed?` | | `driver.getCurrentUrl()` | `driver.current_url` | | `driver.navigate().to(url)` | `driver.navigate.to url` | | `new WebDriverWait(driver, Duration.ofSeconds(10)).until(cond)` | `Wait.new(timeout: 10).until { ... }` | | `driver.quit()` | `driver.quit` | Reading down the right-hand column, the pattern is consistent: shorter names, no ceremony, and Ruby's own conventions applied to an API that is otherwise the same one. ## Two ways to write the same Ruby locator The keyword form is the current idiom, but the client also accepts the pair positionally, and both turn up in samples you may be handed: ```ruby driver.find_element(id: 'term-average') # keyword form driver.find_element(:id, 'term-average') # positional pair ``` The positional form is the one that maps most directly onto the other bindings: the symbol `:id` sits exactly where Python puts `By.ID` and where Java puts the strategy half of `By.id(...)`. Reading it that way makes the family resemblance obvious, because every binding is naming a strategy and giving it a value, and only the syntax around that pair changes. - Prefer the keyword form in new Ruby code; it is what current documentation and samples use. - Recognise the positional form when you meet it, particularly in older suites. - Expect `find_elements` to take exactly the same two shapes as `find_element`. ## Where the keyword form helps, and where it hides something 1. It reads well and it is hard to get the argument order wrong, because there is no order - the key says what it is. 2. It makes a locator awkward to pass around as a value: a Ruby page object usually keeps the selector string in a constant and rebuilds the hash at each call site, or stores the hash itself. 3. It gives no compile-time protection at all, so a mistyped key such as `idd:` surfaces only when the line runs. Java's factory method would not have compiled. None of this changes what the browser does with the report card. It changes how quickly you can read somebody else's sample and translate it into the binding your suite actually uses.
- What does Ruby's wait take where Java takes an ExpectedCondition?A block. `Selenium::WebDriver::Wait.new(timeout: 10).until { driver.find_element(id: 'term-average').displayed? }` runs ordinary Ruby code and finishes when the block returns something truthy. Java instead passes a condition object built by a factory, which is why Ruby samples rarely name any condition helper.
- How does Ruby spell an implicit timeout?As an assignment: `driver.manage.timeouts.implicit_wait = 5`, in seconds. Java calls a method, `driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5))`; Python calls `driver.implicitly_wait(5)`; C# assigns a TimeSpan to the `ImplicitWait` property. Same setting, four spellings.
saying these in an interview costs you the question
- Thinks Ruby needs a By object built by a factory
- Assumes only the positional form works, never keywords
- Calls displayed instead of Ruby's displayed? predicate
- Expects get-prefixed readers such as get_text in Ruby
- Hands Ruby's wait a condition object instead of a block