Class: Vehicles::Make

Inherits:
Object
  • Object
show all
Defined in:
lib/vehicles/make.rb,
sig/vehicles.rbs

Overview

A vehicle make, e.g. "Volkswagen", and the models it builds. Immutable value object. Its models are built lazily once and cached.

make = Vehicles.make("Audi")
make.slug       # => "audi"
make.models     # => ["A3", "A4", "Q3", ...]
make.model("a3")# => #<Vehicles::Model "Audi A3">

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs) ⇒ Make

Returns a new instance of Make.



14
15
16
17
18
19
20
# File 'lib/vehicles/make.rb', line 14

def initialize(attrs)
  @name    = attrs["name"]
  @slug    = attrs["slug"]
  @aliases = Array(attrs["aliases"]).freeze
  @kinds   = Array(attrs["kinds"]).map(&:to_sym).freeze
  @raw_models = attrs["models"] || []
end

Instance Attribute Details

#aliasesArray[String] (readonly)

Returns the value of attribute aliases.

Returns:

  • (Array[String])


12
13
14
# File 'lib/vehicles/make.rb', line 12

def aliases
  @aliases
end

#kindsArray[Symbol] (readonly)

Returns the value of attribute kinds.

Returns:

  • (Array[Symbol])


12
13
14
# File 'lib/vehicles/make.rb', line 12

def kinds
  @kinds
end

#nameString (readonly)

Returns the value of attribute name.

Returns:

  • (String)


12
13
14
# File 'lib/vehicles/make.rb', line 12

def name
  @name
end

#slugString (readonly)

Returns the value of attribute slug.

Returns:

  • (String)


12
13
14
# File 'lib/vehicles/make.rb', line 12

def slug
  @slug
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



80
81
82
# File 'lib/vehicles/make.rb', line 80

def ==(other)
  other.is_a?(Make) && other.slug == slug
end

#continentsObject

Continents this make is evidenced in (union of its models' regions). => [:eu, :as, :na] — powers make-level continent filtering.



42
43
44
# File 'lib/vehicles/make.rb', line 42

def continents
  @continents ||= models.flat_map(&:regions).uniq.freeze
end

#hashObject



85
86
87
# File 'lib/vehicles/make.rb', line 85

def hash
  slug.hash
end

#in_region?(region) ⇒ Boolean

Is this make evidenced on the given continent? (:eu/:na/:as/:sa/:oc/:af)

Returns:

  • (Boolean)


47
48
49
# File 'lib/vehicles/make.rb', line 47

def in_region?(region)
  continents.include?(region.to_sym)
end

#inspectObject



89
90
91
# File 'lib/vehicles/make.rb', line 89

def inspect
  %(#<Vehicles::Make "#{name}">)
end

#model(query) ⇒ Model?

Find one model within this make by exact (normalized) name or slug. "a3" / "A3" / "Q 3" resolve; partial input does NOT (so model("a") returns nil, not "A3" — important, since the vehicle_model validator relies on this). Fuzzy/partial matching lives in Vehicles.search.

Parameters:

  • query (Object)

Returns:



65
66
67
68
69
70
# File 'lib/vehicles/make.rb', line 65

def model(query)
  q = Vehicles.normalize(query)
  return nil if q.empty?

  models.find { |m| Vehicles.normalize(m.name) == q || m.model_slug == q }
end

#model_names(**filters) ⇒ Array[String]

Model display names — what you drop into a dropdown. => ["A3", "A4", ...]

Parameters:

  • kind: (Symbol, nil)
  • body_type: (Symbol, nil)

Returns:

  • (Array[String])


52
53
54
# File 'lib/vehicles/make.rb', line 52

def model_names(**filters)
  models(**filters).map(&:name)
end

#model_options(**filters) ⇒ Array[[String, String]]

[[label, value], ...] for Rails select. => [["A3", "a3"], ["A4", "a4"]]

Parameters:

  • kind: (Symbol, nil)
  • body_type: (Symbol, nil)

Returns:

  • (Array[[String, String]])


57
58
59
# File 'lib/vehicles/make.rb', line 57

def model_options(**filters)
  models(**filters).map { |m| [m.name, m.model_slug] }
end

#models(kind: nil, body_type: nil, region: nil, rarity: nil, max_decile: nil) ⇒ Array[Model]

All models for this make, optionally filtered by kind/body_type/region/ rarity. Returns Vehicles::Model objects, ordered by popularity (as built). The unfiltered list is memoized AND frozen — it's shared process-wide, so a frozen array turns accidental caller mutation into a loud error instead of silently corrupting the dataset. Filtered calls return a fresh array. models(kind: :car, region: :eu) # European cars only models(rarity: :common) # just the well-known ones models(max_decile: 3) # top-30% by popularity

Parameters:

  • kind: (Symbol, nil) (defaults to: nil)
  • body_type: (Symbol, nil) (defaults to: nil)

Returns:



30
31
32
33
34
35
36
37
38
# File 'lib/vehicles/make.rb', line 30

def models(kind: nil, body_type: nil, region: nil, rarity: nil, max_decile: nil)
  list = (@models ||= @raw_models.map { |m| Model.new(m, make: name, make_slug: slug) }.freeze)
  list = list.select { |m| m.kind == kind.to_sym }             if kind
  list = list.select { |m| m.body_type == body_type.to_sym }   if body_type
  list = list.select { |m| m.available_in_region?(region) }    if region
  list = list.select { |m| m.rarity == rarity.to_sym }         if rarity
  list = list.select { |m| m.global_decile && m.global_decile <= max_decile } if max_decile
  list
end

#to_hHash[Symbol, untyped]

Returns:

  • (Hash[Symbol, untyped])


72
73
74
# File 'lib/vehicles/make.rb', line 72

def to_h
  { name: name, slug: slug, kinds: kinds, models: model_names }
end

#to_sObject



76
77
78
# File 'lib/vehicles/make.rb', line 76

def to_s
  name
end