Class: BetterService::Repository::BaseRepository

Inherits:
Object
  • Object
show all
Defined in:
lib/better_service/repository/base_repository.rb

Overview

BaseRepository - Generic repository pattern for data access

Provides a clean abstraction layer between services and ActiveRecord models. Repositories handle all database queries using predicates-based search, enforcing separation of concerns and enabling easier testing.

Examples:

Basic usage

class ProductRepository < BetterService::Repository::BaseRepository
  def initialize(model_class = Product)
    super
  end
end

repo = ProductRepository.new
products = repo.search({ status_eq: 'active' }, includes: [:category])

With predicates

repo.search({
  user_id_eq: user.id,
  status_in: ['pending', 'confirmed'],
  created_at_gteq: 1.week.ago
}, order: 'created_at DESC', per_page: 20)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class = nil) ⇒ BaseRepository

Initialize repository with a model class

Parameters:

  • model_class (Class, nil) (defaults to: nil)

    ActiveRecord model class If nil, derives class name from repository name



35
36
37
# File 'lib/better_service/repository/base_repository.rb', line 35

def initialize(model_class = nil)
  @model = model_class || derive_model_class
end

Instance Attribute Details

#modelObject (readonly)

Returns the value of attribute model.



29
30
31
# File 'lib/better_service/repository/base_repository.rb', line 29

def model
  @model
end

Instance Method Details

#build(attributes = {}) ⇒ ActiveRecord::Base Also known as: new

Build a new unsaved record

Parameters:

  • attributes (Hash) (defaults to: {})

    Attributes for the new record

Returns:

  • (ActiveRecord::Base)

    Unsaved model instance



87
88
89
# File 'lib/better_service/repository/base_repository.rb', line 87

def build(attributes = {})
  model.new(attributes)
end

#create(attributes = {}) ⇒ ActiveRecord::Base

Create a new record (may return invalid record)

Parameters:

  • attributes (Hash) (defaults to: {})

    Attributes for the new record

Returns:

  • (ActiveRecord::Base)

    Created model instance



96
97
98
# File 'lib/better_service/repository/base_repository.rb', line 96

def create(attributes = {})
  model.create(attributes)
end

#create!(attributes = {}) ⇒ ActiveRecord::Base

Create a new record (raises on validation failure)

Parameters:

  • attributes (Hash) (defaults to: {})

    Attributes for the new record

Returns:

  • (ActiveRecord::Base)

    Created model instance

Raises:

  • (ActiveRecord::RecordInvalid)

    if validation fails



105
106
107
# File 'lib/better_service/repository/base_repository.rb', line 105

def create!(attributes = {})
  model.create!(attributes)
end

#delete(record_or_id) ⇒ Integer

Delete a record without callbacks

Parameters:

  • record_or_id (ActiveRecord::Base, Integer, String)

    Record or ID

Returns:

  • (Integer)

    Number of deleted records



137
138
139
140
# File 'lib/better_service/repository/base_repository.rb', line 137

def delete(record_or_id)
  id = record_or_id.respond_to?(:id) ? record_or_id.id : record_or_id
  model.where(id: id).delete_all
end

#destroy(record_or_id) ⇒ ActiveRecord::Base Also known as: destroy!

Destroy a record

Parameters:

  • record_or_id (ActiveRecord::Base, Integer, String)

    Record or ID

Returns:

  • (ActiveRecord::Base)

    Destroyed model instance



126
127
128
129
130
# File 'lib/better_service/repository/base_repository.rb', line 126

def destroy(record_or_id)
  record = resolve_record(record_or_id)
  record.destroy!
  record
end

#search(predicates = {}, page: 1, per_page: 20, includes: [], joins: [], order: nil, order_scope: nil, limit: :default) ⇒ ActiveRecord::Relation, ...

Search records using predicates

Supports flexible querying through predicates hash that gets translated to ActiveRecord scopes via model’s Searchable concern.

Examples:

Basic search

search({ status_eq: 'active' })

With pagination

search({ user_id_eq: 1 }, page: 2, per_page: 25)

Single record

search({ id_eq: 123 }, limit: 1)

With eager loading

search({}, includes: [:user, :comments], order: 'created_at DESC')

Parameters:

  • predicates (Hash) (defaults to: {})

    Search predicates (e.g., { status_eq: ‘active’ })

  • page (Integer) (defaults to: 1)

    Page number for pagination (default: 1)

  • per_page (Integer) (defaults to: 20)

    Records per page (default: 20)

  • includes (Array) (defaults to: [])

    Associations to eager load

  • joins (Array) (defaults to: [])

    Associations to join

  • order (String, Hash, nil) (defaults to: nil)

    Order clause

  • order_scope (Hash, nil) (defaults to: nil)

    Named scope for ordering { field:, direction: }

  • limit (Integer, Symbol, nil) (defaults to: :default)

    Limit results

    • 1: returns single record (first)

    • Integer > 1: limit to N records

    • nil: no limit (returns all)

    • :default: apply pagination

Returns:

  • (ActiveRecord::Relation, Object, nil)

    Query result



69
70
71
72
73
74
75
76
77
78
# File 'lib/better_service/repository/base_repository.rb', line 69

def search(predicates = {}, page: 1, per_page: 20, includes: [],
           joins: [], order: nil, order_scope: nil, limit: :default)
  cleaned_predicates = (predicates || {}).compact

  scope = build_base_scope(cleaned_predicates)
  scope = apply_joins(scope, joins)
  scope = apply_includes(scope, includes)
  scope = apply_ordering(scope, order, order_scope)
  apply_limit_or_pagination(scope, limit, page, per_page)
end

#update(record_or_id, attributes) ⇒ ActiveRecord::Base Also known as: update!

Update an existing record

Parameters:

  • record_or_id (ActiveRecord::Base, Integer, String)

    Record or ID

  • attributes (Hash)

    Attributes to update

Returns:

  • (ActiveRecord::Base)

    Updated model instance

Raises:

  • (ActiveRecord::RecordInvalid)

    if validation fails



115
116
117
118
119
# File 'lib/better_service/repository/base_repository.rb', line 115

def update(record_or_id, attributes)
  record = resolve_record(record_or_id)
  record.update!(attributes)
  record
end