Как получить доступ к вложенным переменным без ошибок в Rails - PullRequest
1 голос
/ 06 ноября 2019

Если у меня есть параметры, имеющие структуру:

data = {
  "messageId" => "B2YAx4rSMTZ4D8FJs1hsoV",
  "eventId" => "appointmentBooking.cancelled",
  "eventSchemaVersion" => 1.0,
  "eventInstanceOriginationDateTime" => "2019-11-06T19:24:10Z",
  "eventData" => {
    "siteId" => 232,
    "appointmentId" => 48761
  },
  "subdomain" => "api",
  "consultation" => {}
}

и я хочу получить доступ к siteId и appointmentId для другой функции, я обнаруживаю, что выполняю следующее:

data = params['eventData']

if data.present?
  siteID = data['siteId']
  appointmentID = data['appointmentId']
end

if siteID and appointmentID
  # process this
end

Иногда это работает, но если !data.present?, то siteID и appointmentID не определены и последний вызов if выдаст ошибку:

NameError (undefined local variable or method `siteID'

Есть ли лучший способсделать это без предварительного определения переменных сразу после data = params['eventData']?

Ответы [ 3 ]

3 голосов
/ 06 ноября 2019

Вы можете явно проверить наличие атрибутов, которые, как вы надеетесь, существуют, а затем установить переменные и обработать за один раз:

data = params['eventData']

if data && data['siteId'] && data['appointmentId']
  siteID = data['siteId']
  appointmentID = data['appointmentId']
  # process this
end

Другой вариант - сохранить результаты оператора if в его собственномvar, а затем использовать его в качестве условия для обработки:

data = params['eventData']

process = if data.present?
  siteID = data['siteId']
  appointmentID = data['appointmentId']
end

if process
  # process this
end

Или другой вариант - установить переменные inline:

data = params['eventData']

if data && siteID = data['siteId'] && appointmentID = data['appointmentId']
  # process here
end
3 голосов
/ 06 ноября 2019

Вы можете использовать метод dig . Возвращается nil, если какой-либо промежуточный шаг равен nil.

appointment_id = data.dig('eventData', 'appointmentId')
#=> 48761

site_id = data.dig('eventData', 'siteId')
#=> 232

Тогда

if site_id && appointment_id
  # do_something
end
0 голосов
/ 07 ноября 2019

Мы можем написать следующий метод:

def extract(schedule)
  siteId, appointmentId = 
    schedule["eventData"]&.values_at("siteId", "appointmentId")
end

Если schedule не имеет ключа, "eventData", sideId и appointentId обоим присваиваются значения nil. Если у schedule есть ключ "eventData", я предположил, что schedule["eventData"] - это хеш, а:

siteId = schedule["eventData"]["siteId"]
appointmentId = schedule["eventData"]["appointmentId"]

& - это безопасный оператор навигации , который сделал егодебют в Ruby v2.3. См. Также Hash # values_at .

Этот метод используется следующим образом.

def doit(schedule)
  siteId, appointmentId = extract(schedule)
  if siteId && appointmentId
    # do something
  else
    # do something else
  end
end

Вот несколько примеров значений, возвращаемых extract:

schedule = { "eventData"=>{ "siteId"=>232, "appointmentId"=>48761 } }
siteId, appointmentId = extract(schedule)
  #=> [232, 48761] 
siteId
  #=> 232 
appointmentId
  #=> 48761 

schedule = { "eventData" => { "siteId" => 232 } }
siteId, appointmentId = extract(schedule)
  #=> [232, nil] 

schedule = { "eventData" => {} }    
siteId, appointmentId = extract(schedule)
  #=> [nil, nil] 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...