Class: Schemas::BaseBoatSchema

Inherits:
Base
  • Object
show all
Defined in:
app/getboat/schemas/base_boat_schema.rb

Instance Attribute Summary

Attributes included from Dry::Schema

#attributes, #errors

Instance Method Summary collapse

Methods inherited from Base

#clear_html, #forced_array, #forced_hash, #normalize_integer, #normalize_url, #nullify_empty, #strip_string, #to_big_decimal, #to_bool, #to_date, #to_float

Methods included from Dry::Schema

#[], #initialize, #valid?

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Dry::Schema

Instance Method Details

#rule_boat_photos_attributes(parents) ⇒ Object



154
155
156
157
# File 'app/getboat/schemas/base_boat_schema.rb', line 154

def rule_boat_photos_attributes(parents)
  messages = { present: I18n.t('errors.boat.boat_photos_attributes.blank') }
  rule(:boat_photos_attributes, parents, messages) { present? }
end

#rule_boat_type_id(parents) ⇒ Object



136
137
138
139
140
141
142
# File 'app/getboat/schemas/base_boat_schema.rb', line 136

def rule_boat_type_id(parents)
  messages = {
      present: I18n.t('errors.boat.boat_type_id.blank'),
      gt:      I18n.t('errors.boat.boat_type_id.blank')
  }
  rule(:boat_type_id, parents, messages) { present? & gt?(0) }
end

#rule_maximum_guests_during_cruise(parents) ⇒ Object



145
146
147
148
149
150
151
# File 'app/getboat/schemas/base_boat_schema.rb', line 145

def rule_maximum_guests_during_cruise(parents)
  messages = {
      present: I18n.t('errors.boat.maximum_guests_during_cruise.blank'),
      gt:      I18n.t('errors.boat.maximum_guests_during_cruise.blank')
  }
  rule(:maximum_guests_during_cruise, parents, messages) { present? & gt?(0) }
end

#rule_name(parents) ⇒ Object



127
128
129
130
131
132
133
# File 'app/getboat/schemas/base_boat_schema.rb', line 127

def rule_name(parents)
  messages = {
      present:        I18n.t('errors.boat.name.blank'),
      length_between: I18n.t('errors.boat.name.length_invalid', min: 2, max: 255)
  }
  rule(:name, parents, messages) { present? & length_between?(2..255) }
end

#schemaObject



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'app/getboat/schemas/base_boat_schema.rb', line 3

def schema
  result = {
      properties: {
          id: {
              type: %i[null number],
              cast: ->(value) { normalize_integer(value) }
          },
          name: {
              type: [:null, :string],
              cast: ->(value) { clear_html(strip_string(value)) },
              rule: ->(parents) { rule_name(parents) }
          },
          boat_type_id: {
              enum: [nil, -1] + Dicts::BoatType::ALL.collect(&:id),
              cast: ->(value) { normalize_integer(value) },
              rule: ->(parents) { rule_boat_type_id(parents) }
          },
          boat_model: {
              type: %i[null string],
              cast: ->(value) { clear_html(strip_string(value)) }
          },
          builder: {
              type: %i[null string],
              cast: ->(value) { clear_html(strip_string(value)) }
          },
          length: {
              type: :hash,
              required: %i[value length_id],
              properties: {
                  value: {
                      type: %i[null number string],
                      cast: ->(value) { to_float(value) }
                  },
                  length_id: {
                      enum: Dicts::Length.all.collect(&:id),
                      cast: ->(value) { normalize_integer(value) }
                  }
              }
          },
          crew_total: {
              type: %i[null number],
              cast: ->(value) { normalize_integer(value) }
          },
          guest_cabins: {
              type: %i[null number],
              cast: ->(value) { normalize_integer(value) }
          },
          guests_total: {
              type: %i[null number],
              cast: ->(value) { normalize_integer(value) }
          },
          maximum_guests_during_cruise: {
              type: %i[null number],
              cast: ->(value) { normalize_integer(value) },
              rule: ->(parents) { rule_maximum_guests_during_cruise(parents) }
          },
          boat_locations_attributes: {
              type: %i[null array],
              items: {
                  type: :hash,
                  required: %i[latitude longitude address is_main _destroy],
                  cast: ->(value) do
                    value[:latitude]  = to_big_decimal value[:latitude]
                    value[:longitude] = to_big_decimal value[:longitude]
                    value[:address]   = strip_string   value[:address]
                    value[:is_main]   = to_bool        value[:is_main]
                    value[:_destroy]  = to_bool        value[:_destroy]

                    value[:latitude].nil? || value[:longitude].nil? || !value[:address].present? ? nil : value
                  end
              },
              cast: ->(value) { forced_array(value) }
          }
      }
  }

  result[:properties][:rent_prices] = {
      type: [:null, :array],                                                                                      # это первая версия, где я пробую разобраться с массивом объектов (версия покруче тут - app/getboat/schemas/base_boat_schema.rb - с помощью :items)
      cast: ->(value) do
        value&.inject([]) do |res, el|
          el[:_delete]  = to_bool el[:_delete]
          el[:currency] = normalize_integer el[:currency]
          el[:discount] = to_float el[:discount]
          el[:duration] = to_float el[:duration]
          el[:season]   = normalize_integer el[:season]
          el[:uom]      = normalize_integer el[:uom]
          el[:value]    = normalize_integer(el[:value].is_a?(String) ? el[:value].split(/[, ]/).join : el[:value])
          res << el
          res
        end
      end
  }

  result[:properties][:sale_price] = {
      type: [:null, :hash],
      properties: {
          currency_id: {
              enum: Dicts::Currency.all.collect(&:id),
              cast: ->(value) { normalize_integer(value) }
          },
          value: {
              type: %i[number null string],
              cast: ->(value) do
                val = value.is_a?(String) ? value.split(/[, ]/).join : value
                normalize_integer val
              end
          },
          discount: {
              type: %i[number null string],
              cast: ->(value) { to_float(value) }
          },
      }
  }

  result[:properties][:boat_photos_attributes] = {
      type: [:null, :hash],
      cast: ->(value) { nullify_empty(value) },
      rule: ->(parents) { rule_boat_photos_attributes(parents)}
  }

  result
end

#validate_crew_totalObject



191
192
193
# File 'app/getboat/schemas/base_boat_schema.rb', line 191

def validate_crew_total
  errors.add(:crew_total, I18n.t('errors.boat.crew_total.blank')) unless crew_total.present?
end

#validate_guest_cabinsObject



201
202
203
# File 'app/getboat/schemas/base_boat_schema.rb', line 201

def validate_guest_cabins
  errors.add(:guest_cabins, I18n.t('errors.boat.guest_cabins.blank')) unless guest_cabins.present?
end

#validate_guests_totalObject



196
197
198
# File 'app/getboat/schemas/base_boat_schema.rb', line 196

def validate_guests_total
  errors.add(:guests_total, I18n.t('errors.boat.guests_total.blank')) unless guests_total.present?
end

#validate_lengthObject



186
187
188
# File 'app/getboat/schemas/base_boat_schema.rb', line 186

def validate_length
  errors.add(:length_value, I18n.t('errors.boat.length.blank')) unless length[:value]&.nonzero?
end

#validate_locationObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'app/getboat/schemas/base_boat_schema.rb', line 160

def validate_location
  unless boat_locations_attributes
    errors.add :boat_locations, I18n.t('errors.boat.boat_locations.blank')
    return
  end

  bls  = boat_locations_attributes.compact.select { |loc| !loc[:_destroy] }
  mbls = bls.select { |loc| loc[:is_main] }

  if bls.size.zero?
    errors.add :boat_locations, I18n.t('errors.boat.boat_locations.blank')
    return
  end

  if bls.size > 5
    errors.add :boat_locations, I18n.t('errors.boat.boat_locations.limit', max: 5)
    return
  end

  if mbls.size == 0
    errors.add :boat_locations, I18n.t('errors.boat.boat_locations.is_main')
    return
  end
end

#validate_prices_and_rent_pricesObject



206
207
208
209
210
211
212
213
214
215
# File 'app/getboat/schemas/base_boat_schema.rb', line 206

def validate_prices_and_rent_prices
  rent_prices_present = rent_prices.present? && rent_prices.count { |price| price[:_delete] } < rent_prices.count
  sale_price_present  = sale_price.present? && sale_price[:value]&.>(0)
  return if rent_prices_present && sale_price_present

  if !(rent_prices_present || sale_price_present)
    errors.add :rent_prices, I18n.t('errors.boat.prices.any')
    errors.add :sale_price, I18n.t('errors.boat.prices.any')
  end
end

#validate_rent_pricesObject



218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'app/getboat/schemas/base_boat_schema.rb', line 218

def validate_rent_prices
  return unless rent_prices.present?

  rent_prices.each do |price|
    if price[:value].nil? || price[:value].zero?
      errors.add :rent_prices, I18n.t('errors.boat.rent_prices.invalid')
      break
    end
    if price[:duration].nil? || price[:duration].zero?
      errors.add :rent_prices, I18n.t('errors.boat.rent_prices.invalid_duration')
      break
    end
  end
end