Как использовать обратные вызовы для методов с определенными шаблонами именования?

#ruby-on-rails #ruby #rails-activerecord

#ruby-on-rails #ruby #rails-activerecord

Вопрос:

Я пытаюсь найти красивый способ объявления обратных вызовов для методов с определенными шаблонами имен. Например:

 class UsersController < ApplicationController
  before_action :set_venue, only: [:get_location, :get_date, :get_time, :sort_teams, :get_teams]
end
  

except или only есть много методов для объявления в любом случае.

Как я могу выполнить что-то вроде before_action: only:[:get_*, :sort_teams_by_*]

Ответ №1:

Вы можете передать вызываемый (proc или лямбда) в качестве if: опции:

 before_action :set_venue, 
  if: proc { |c| c.action_name =~ /^(get|sort_teams_by)_*/ }
  

Но это кажется разумным решением для узаконивания действительно вонючего кода. Имена всех этих действий в вашем контроллере — это явный признак того, что у вас есть некоторые очень неудобные маршруты, например users/1/get_location , вместо users/1/location и users/1/teams .

Это также говорит нам о том, что у этого контроллера может быть много обязанностей и он обрабатывает несколько разных ресурсов. Например users/1/get_teams , действительно должно быть users/1/teams и обрабатываться Users::TeamsController .

См .:

Комментарии:

1. Клянусь Богом, я вернулся, чтобы написать тот же ответ, используя proc и условия. Но у меня есть один вопрос: это снижает производительность?

2. Нет, я не могу себе представить, что это окажет какое-либо влияние на производительность. Тем не менее, это чертовски вонючий. Всякий раз, когда вы предваряете что-либо с get_ помощью Ruby или set_ в Ruby, ваш spidey sense должен быть выше крыши.

3. Он не обрабатывает разные ресурсы, это контроллер для telegram-бота, который обрабатывает одно сообщение. Владелец gem предложил написать это таким образом. Исходный код здесь: github.com/Nmerey/team_sorter_bot/blob/master/app/controllers/… Пожалуйста, не стесняйтесь посоветовать мне, как я могу сделать его более спокойным. Любая помощь приветствуется.

4. Если вам нужно сопоставить существующий API, это одно, но ваш внутренний макет кода определенно не должен страдать от этого, и этот код имеет много логики для контроллера. И это будет сложно протестировать. Брэндон Киперс сформулировал довольно хорошую лакмусовую бумажку для классов — если вы не можете написать описание класса верхнего уровня, не используя слова «и» или «или», вам нужно многое сделать.

5. Вообще ничего не понял. Не могли бы вы уточнить свои слова, используя какой-нибудь пример из исходного кода?