Skip to content

Commit

Permalink
Adds support for #except and #only on relations
Browse files Browse the repository at this point in the history
  • Loading branch information
benedikt committed Sep 9, 2024
1 parent de33c74 commit a4827f2
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
24 changes: 24 additions & 0 deletions lib/active_model/relation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ def inspect
"#<#{self.class.name} [#{entries.join(', ')}]>"
end

def except(*skips)
relation_with(values.except(*skips))
end

def only(*keeps)
relation_with(values.slice(*keeps))
end

private

def method_missing(...)
Expand All @@ -142,5 +150,21 @@ def respond_to_missing?(...)
def spawn
clone
end

def values
{
where: where_clause,
offset: offset_value,
limit: limit_value
}
end

def relation_with(values)
spawn.tap do |relation|
relation.where_clause = values[:where] || WhereClause.new
relation.offset_value = values[:offset]
relation.limit_value = values[:limit]
end
end
end
end
46 changes: 46 additions & 0 deletions spec/active_model/relation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,52 @@ def doubled_size
end
end

describe '#except' do
it 'should return a new relation' do
expect(subject.except(:where)).to be_a(described_class)
end

it 'should return a new instance' do
expect(subject.except(:where)).not_to eq(subject)
end

it 'should remove the where values' do
expect(subject.where(state: 'completed').except(:where)).to match_array(records)
end

it 'should remove the offset value' do
expect(subject.offset(1).except(:offset)).to match_array(records)
end

it 'should remove the limit value' do
expect(subject.limit(1).except(:limit)).to match_array(records)
end
end

describe '#only' do
subject { super().where(state: 'completed').offset(1).limit(1) }

it 'should return a new relation' do
expect(subject.only(:where)).to be_a(described_class)
end

it 'should return a new instance' do
expect(subject.only(:where)).not_to eq(subject)
end

it 'should keep only the where values' do
expect(subject.where(state: 'completed').only(:where)).to match_array(records[2..3])
end

it 'should keep only the offset value' do
expect(subject.offset(1).only(:offset)).to match_array(records[1..3])
end

it 'should keep only the limit value' do
expect(subject.limit(1).only(:limit)).to match_array(records[0..0])
end
end

describe 'model class methods' do
it 'should delegate methods to the model class' do
expect(subject.model_name).to eq(model_class.model_name)
Expand Down

0 comments on commit a4827f2

Please sign in to comment.