Skip to content
Open
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
1 change: 1 addition & 0 deletions app/models/catalog_plan.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class CatalogPlan < ApplicationRecord
include PaperTrailTraceable
include Currencies
include Discard::Model
include CatalogCodeFormat

self.discard_column = :deleted_at

Expand Down
19 changes: 19 additions & 0 deletions app/models/concerns/catalog_code_format.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

# Enforces a slug-safe `code` on v2 catalog objects (Product, ProductCategory,
# ProductFilter, RateCard, RateCardRate, CatalogPlan, RatePhase). Codes are
# member-route params, so restricting them to a URL-safe charset keeps every
# code addressable and avoids collisions with nested route segments. The
# leading negative lookahead rejects an all-dot code (`.`, `..`, …): those are
# path-segment specials that clients and proxies normalize away, so they are
# not reliably addressable. allow_blank leaves the empty case to the presence
# validation.
module CatalogCodeFormat
extend ActiveSupport::Concern

CODE_FORMAT = /\A(?!\.+\z)[a-zA-Z0-9_\-.]+\z/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

these options with many dots and text are allowed as well?


included do
validates :code, format: {with: CODE_FORMAT}, allow_blank: true
end
end
1 change: 1 addition & 0 deletions app/models/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class Product < ApplicationRecord
include PaperTrailTraceable
include Discard::Model
include CatalogAttachable
include CatalogCodeFormat

self.discard_column = :deleted_at

Expand Down
1 change: 1 addition & 0 deletions app/models/product_category.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class ProductCategory < ApplicationRecord
include PaperTrailTraceable
include Discard::Model
include CatalogAttachable
include CatalogCodeFormat

self.discard_column = :deleted_at

Expand Down
1 change: 1 addition & 0 deletions app/models/product_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class ProductFilter < ApplicationRecord
include PaperTrailTraceable
include Discard::Model
include CatalogCodeFormat

self.discard_column = :deleted_at

Expand Down
1 change: 1 addition & 0 deletions app/models/rate_card.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class RateCard < ApplicationRecord
include Currencies
include Discard::Model
include CatalogAttachable
include CatalogCodeFormat

self.discard_column = :deleted_at

Expand Down
1 change: 1 addition & 0 deletions app/models/rate_card_rate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class RateCardRate < ApplicationRecord
include PaperTrailTraceable
include ChargePropertiesValidation
include Discard::Model
include CatalogCodeFormat

self.discard_column = :deleted_at

Expand Down
1 change: 1 addition & 0 deletions app/models/rate_phase.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class RatePhase < ApplicationRecord
include PaperTrailTraceable
include Discard::Model
include CatalogCodeFormat

self.discard_column = :deleted_at

Expand Down
2 changes: 2 additions & 0 deletions spec/models/catalog_plan_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

it_behaves_like "paper_trail traceable"

it_behaves_like "a catalog code", :catalog_plan

describe "associations" do
it do
expect(catalog_plan).to belong_to(:organization)
Expand Down
2 changes: 2 additions & 0 deletions spec/models/product_category_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

it_behaves_like "paper_trail traceable"

it_behaves_like "a catalog code", :product_category

describe "associations" do
it do
expect(product_category).to belong_to(:organization)
Expand Down
2 changes: 2 additions & 0 deletions spec/models/product_filter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

it_behaves_like "paper_trail traceable"

it_behaves_like "a catalog code", :product_filter

describe "associations" do
it do
expect(product_filter).to belong_to(:organization)
Expand Down
2 changes: 2 additions & 0 deletions spec/models/product_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

it_behaves_like "paper_trail traceable"

it_behaves_like "a catalog code", :product

describe "enums" do
it do
expect(product).to define_enum_for(:product_type)
Expand Down
2 changes: 2 additions & 0 deletions spec/models/rate_card_rate_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

it_behaves_like "paper_trail traceable"

it_behaves_like "a catalog code", :rate_card_rate

describe "enums" do
it do
expect(rate_card_rate).to define_enum_for(:rate_model)
Expand Down
2 changes: 2 additions & 0 deletions spec/models/rate_card_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

it_behaves_like "paper_trail traceable"

it_behaves_like "a catalog code", :rate_card

describe "enums" do
it do
expect(rate_card).to define_enum_for(:billing_timing)
Expand Down
2 changes: 2 additions & 0 deletions spec/models/rate_phase_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

it_behaves_like "paper_trail traceable"

it_behaves_like "a catalog code", :rate_phase

describe "associations" do
it do
expect(rate_phase).to belong_to(:organization)
Expand Down
33 changes: 33 additions & 0 deletions spec/support/shared_examples/catalog_code_format.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

# Shared validation for the slug-safe `code` on v2 catalog objects.
# Usage: it_behaves_like "a catalog code", :product
RSpec.shared_examples "a catalog code" do |factory|
describe "code format" do
it "allows a slug-safe code" do
record = build(factory, code: "valid_code-1.2")
record.valid?
expect(record.errors.where(:code, :invalid)).to be_empty
end

it "rejects a code containing a slash" do
record = build(factory, code: "a/b")
record.valid?
expect(record.errors.where(:code, :invalid)).to be_present

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be more sensitive and validate any error in code. record.errors[:code] it does validate any error and not only the invalid one.

end

it "rejects a code containing a space" do
record = build(factory, code: "a b")
record.valid?
expect(record.errors.where(:code, :invalid)).to be_present
end

it "rejects the path-segment specials . and .." do
%w[. ..].each do |code|
record = build(factory, code:)
record.valid?
expect(record.errors.where(:code, :invalid)).to be_present
end
end
end
end
Loading