Rails now provides pattern matching support for ActiveModel
source link: https://blog.saeloun.com/2022/06/08/rails-pattern-matching-support-for-activemodel
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Rails now provides pattern matching support for ActiveModel
Jun 8, 2022 , by Keshav Biswa
2 minute read
The most important feature that was released in Ruby 2.7 was Pattern Matching. This feature is common in most functional programming languages such as Scala, Elixir, etc.
In Ruby, Pattern matching is the way to recognize a pattern of data
and execute some actions if the data matches the pattern.
Pattern matching in Ruby is performed using the case
statement
wherein the keyword in
is used instead of when
to match patterns.
An example of pattern matching in Ruby,
case ['apple', 'mango', 'orange', 'guava']
in ['mango', 'apple', 'orange', 'guava']
puts "Fruits in incorrect order"
in ['apple', 'mango', 'orange', 'guava']
puts "Fruits in correct order"
end
#=> "Fruits in the correct order"
case [1, 2, 3, 4]
in [1, 3, *other_numbers]
puts "Incorrect match"
in [1, *other_numbers]
puts "Correct match"
puts other_numbers
end
#=> "Correct match"
#=> 2
#=> 3
#=> 4
point = { x: 1, y: 2, z: 3 }
case point
in { x:, y:, z: }
puts "The points are #{x}, #{y}, #{z}"
else
puts "The pattern are not matched correctly"
end
#=> "The points are 1, 2, 3"
This feature was introduced in 2.7 and the Ruby community loves this feature as it makes the code more readable. Rails will now allow the same pattern matching feature against ActiveModel (also ActiveRecord) objects.
To understand how this could help the Rails codebase, let’s take an example of a User model with the following attributes-
- preferred_full_name
- first_name
- last_name
class User
include ActiveModel::AttributeMethods
attr_accessor :type, :preferred_full_name, :first_name, :last_name
end
We need to define a method to get a User’s full name but with the following conditions
- If
type
is “Employer”, then return “Name not required” - If
type
is “Employee” andpreferred_full_name
is given then return thepreferred_full_name
- If
type
is “Employee” andfirst_name
andlast_name
is given, then return the full name withfirst_name
and thelast_name
- If none of these scenarios are matched, return “Name not found”
Before
Before it’s latest version, the following code was used to create this method-
def get_employee_name(user)
if user[:type] == "Employer"
return "Name not required"
elsif user[:type] == "Employee"
if user[:preferred_full_name]
return user[:preferred_full_name]
elsif user[:first_name] && user[:last_name]
return "#{user[:first_name]} #{user[:last_name]}"
end
end
return "Name not found"
end
After
After the latest Rails version is released, the above method can become more readable using Pattern Matching.
def get_employee_name(user)
case user
in { type: "Employer" }
return "Name not required"
in { type: "Employee", preferred_full_name: }
return preferred_full_name
in { first_name:, last_name: }
return "#{first_name} #{last_name}"
else
return "Name not found"
end
end
user = User.new(type: "Employer", preferred_full_name: "Smith John", first_name: "John", last_name: "Smith")
get_employee(user) #=> "Name not required"
user = User.new(type: "Employee", preferred_full_name: "Smith John", first_name: "John", last_name: "Smith")
get_employee(user) #=> "Smith John"
user = User.new(type: "Employee", first_name: "John", last_name: "Smith")
get_employee(user) #=> "John Smith"
user = User.new(type: "Employee")
get_employee(user) #=> "Name not found"
The above method makes the code more readable and easy to understand. This enhancement helps a lot in writing methods with complex logic much easier.
Note: The enhancement is yet to be released in the official Rails version
Check out the PR for more details.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK