Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
### Changed
- Exposed `.find_by` as a public method for more complex querying of models, and to allow people to write
their own custom filters on top of this method
- Hyphenated keys when passed into `.create` or `#update` will now be converted to underscores to ensure consistency with
ruby conventions and to prevent issues with helper generation
- `.with_email` filter now supports `email_address`, `email` and `email-address` key names for better flexibility when
filtering on email addresses

### Fixed
- Hyphenated keys are not permitted for the `primary_key` setting as this will cause issues with ruby

### Security

Expand Down
1 change: 1 addition & 0 deletions lib/testing_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def configure
# Configure a default primary key for all TestingRecord models
def default_primary_key=(value)
raise InvalidConfigurationError, 'Invalid primary key value, must be a Symbol' unless value.is_a?(Symbol)
raise InvalidConfigurationError, 'Primary key value cannot contain `-` please use `_` instead' if value.to_s.include?('-')

@default_primary_key = value
TestingRecord::Model.primary_key value
Expand Down
7 changes: 6 additions & 1 deletion lib/testing_record/dsl/builder/filters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ def find_by(attributes)
#
# @return [TestingRecord::Model, nil]
def with_email(email_address)
find_by({ email_address: })&.first&.tap { |entity| entity.class.current = entity }
email_address_results =
find_by({ email_address: }).first ||
find_by({ email: email_address }).first ||
find_by({ 'email-address': email_address }).first

email_address_results&.tap { |entity| entity.class.current = entity }
end

# Checks to see whether an entity exists with the provided id
Expand Down
4 changes: 2 additions & 2 deletions lib/testing_record/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class << self
#
# @return [TestingRecord::Model]
def create(attributes)
attributes.transform_keys!(&:to_sym)
attributes.transform_keys! { |key| key.to_s.tr('-', '_').to_sym }
if respond_to?(:all)
create_with_caching(attributes)
else
Expand Down Expand Up @@ -135,7 +135,7 @@ def to_s
#
# @return [TestingRecord::Model]
def update(attrs)
attrs.transform_keys(&:to_sym).each do |key, value|
attrs.transform_keys! { |key| key.to_s.tr('-', '_').to_sym }.each do |key, value|
attributes[key] = value
instance_variable_set("@#{key}", value)
TestingRecord.logger.info("Updated '#{key}' on the #{self.class} entity to be '#{value}'")
Expand Down
29 changes: 28 additions & 1 deletion spec/testing_record/dsl/builder/filters_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
Class.new(TestingRecord::Model) do
caching :enabled
primary_key :email_address

def self.name
'FakeModel'
end
end
end

Expand Down Expand Up @@ -36,7 +40,7 @@
end
end

context 'when entity exists' do
context 'when entity exists with an `email_address` key' do
before do
model_klazz.create({ email_address: 'foo@bar.com' })
model_klazz.create({ email_address: 'baz@bar.com' })
Expand All @@ -46,6 +50,29 @@
expect(model_klazz.with_email('foo@bar.com')).to be_a TestingRecord::Model
end
end

context 'when entity exists with an `email-address` key' do
before do
model_klazz.create({ 'email-address': 'foo@bar.com' })
model_klazz.create({ 'email-address': 'baz@bar.com' })
end

it 'finds the first matching model (which is stored as a snake_cased key)' do
expect(model_klazz.with_email('foo@bar.com')).to be_a TestingRecord::Model
end
end

context 'when entity exists with an `email` key' do
before do
model_klazz.primary_key :email
model_klazz.create({ email: 'foo@bar.com' })
model_klazz.create({ email: 'baz@bar.com' })
end

it 'finds the first matching model' do
expect(model_klazz.with_email('foo@bar.com')).to be_a TestingRecord::Model
end
end
end

describe '.find_by' do
Expand Down
15 changes: 15 additions & 0 deletions spec/testing_record/model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@
expect(primary_model_entity).to respond_to(:attributes, :id, :foo, :bar)
end
end

context 'with any hyphenated keys' do
before do
FakeModel.caching :enabled
FakeModel.create({ id: 1, snake_case: :whatever, 'hyphenated-case': :no_op, 'hyphenated-case-two': :no_op })
end

it 'stores the hyphenated keys as snake_cased keys in the attributes hash' do
expect(FakeModel.current.attributes).to eq({ hyphenated_case: :no_op, hyphenated_case_two: :no_op, id: 1, snake_case: :whatever })
end

it 'stores the hyphenated keys as snake_cased reader methods' do
expect(FakeModel.current).to respond_to(:hyphenated_case, :hyphenated_case_two)
end
end
end

describe '.current=' do
Expand Down