💡 See the code for this post on the 🔗 core-models branch.
After creating our database structure in the previous chapter, it’s time to add logic to our models. The models are the core of our application, handling data validation and relationships.
Let’s start with the Webhook
model. This model needs to:
Here’s how I implemented these requirements:
class Webhook < ApplicationRecord
has_many :webhook_requests, dependent: :destroy
validates :uuid, presence: true, uniqueness: true
validates :expired_at, presence: true
before_validation :set_uuid, on: :create
def expired?
Time.current.to_date > expired_at
end
private
def set_uuid
self.uuid = SecureRandom.uuid if uuid.blank?
end
end
A few interesting things about this model:
has_many
relationship tells Rails that one webhook can have multiple webhook requestsdependent: :destroy
ensures all related webhook requests are deleted when we delete a webhookbefore_validation
callback to automatically set the UUID when creating a new webhookexpired?
method helps us check if a webhook can still receive requestsNext, I built the WebhookRequest
model to store incoming HTTP requests. This model needs to:
Here’s the implementation:
class WebhookRequest < ApplicationRecord
belongs_to :webhook
# Convert headers and query params to JSON before saving
before_save :ensure_json_format
private
def ensure_json_format
self.headers = headers.to_json unless headers.is_a?(String)
self.query_params = query_params.to_json unless query_params.is_a?(String)
end
end
The interesting parts of this model:
belongs_to :webhook
sets up the relationship with the parent webhookensure_json_format
callback makes sure our headers and query parameters are stored as JSON stringsLet’s test our models in the Rails console:
# Create a new webhook that expires in 7 days
webhook = Webhook.create!(expired_at: 7.days.from_now)
# Create a webhook request
request = webhook.webhook_requests.create!(
ip: "127.0.0.1",
url: "https://webhookdump.link/abc123",
method: "POST",
host: "webhookdump.link",
headers: {"Content-Type" => "application/json"},
query_params: {"key" => "value"},
payload: '{"message": "Hello World"}'
)
# Check if it worked
puts "Webhook UUID: #{webhook.uuid}"
puts "Request count: #{webhook.webhook_requests.count}"
puts "Is expired? #{webhook.expired?}"
With these models in place, our application can now:
In the next chapter, we’ll build the controllers to handle incoming webhook requests and display them to users.
Stay tuned! 🚀