Rails: шаблон проектирования для изменения параметров в зависимости от типа пользователя перед передачей в модель - PullRequest
0 голосов
/ 13 июня 2018

Существует несколько действий контроллера, которые получают startDate в качестве параметра и передают его соответствующим моделям для извлечения данных.На основе свойства пользователя существуют правила проверки, которые должны применяться к этому параметру.Проверка не будет просто неудачной, но вместо этого назначит значение по умолчанию, специфичное для этого пользовательского свойства.

Модификация, требуемая для startDate, является общей для всех действий и должна применяться во всех случаях.Итак, я предполагаю, что эта логика не должна повторяться на каждой модели.Вместо этого, фильтр before_action контроллера, что-то вроде Filter_params, звучит как раз для этого.

before_action :filtered_params

def filtered_params
   params.require(:query).permit(:start_date)
   user = User.instance
   if(user.type == 'student') {} # startDate should be Greater than or equal to 12-03-2018. modify params.startDate with the logic
   elsif(user.type == 'professor') {} // startDate should be Greater than equal to 01-01-2018
   else {} // do nothing
   end
end

Приведенный выше подход работает, но я не хочу зацикливаться на цикле if else.Есть ли лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

Возможно, вы могли бы сделать что-то вроде:

before_action :filtered_params

def filtered_params
  @filtered_params ||= get_filtered_params
end

def get_filtered_params
  # not sure about this user assignment, but let's go with it...
  user = User.instance
  begin
    "ParamsFilter::#{user.type.camelize}Service".constantize.call params
  rescue NameError => e
    # I'm guessing at the default behavior here. You would need to 
    # modify to meet your requirements.
    return params.require(:query).permit(:start_date)
  end
end

Тогда вам понадобится что-то вроде:

app
 |- services
 |   |- params_filter
 |   |   |- service_base.rb
 |   |   |- student_service.rb
 |   |   |- professor_service.rb
 |   |- service_base.rb

И служба может выглядеть примерно так:

class ParamsFilter::StudentService < ParamsFilter::ServiceBase

  MIN_START_DATE = '12-03-2018'

  #======================================================================
  # Instance Methods
  #======================================================================

    def call
      # In this case, given how ServiceBase is defined, the params will 
      # be received as `args`, so you'll need to work with the `args` 
      # variable, which will contain `params`.

      # You could do stuff unique to `student`:
      student_stuff

      # and then do some common stuff by calling `super`.
      super

    end

  private

    def student_stuff
    end

end

Где ParamsFilter::ServiceBase может выглядеть примерно так:

class ParamsFilter::ServiceBase < ServiceBase

  #======================================================================
  # Instance Methods
  #======================================================================

    def call
      args[:start_date] = self.class::MIN_START_DATE unless start_date_okay?
    end

  private 

    def start_date_okay?
      args[:start_date] >= self.class::MIN_START_DATE
    end

end

Где service_base.rb может выглядеть примерно так:

class ServiceBase

  attr_accessor *%w(
    args
  ).freeze

  class << self

    def call(args=nil)
      new(args).call
    end

  end # Class Methods

  #======================================================================
  # Instance Methods
  #======================================================================

  def initialize(args)
    @args = args
  end

end
0 голосов
/ 13 июня 2018

Как отмечает Дейв, это странное поведение.Однако, если вам необходимо изменить start_date, рассмотрите возможность использования обратного вызова before_validation.Гораздо безопаснее / чище НЕ изменять входящие параметры, но делать это на уровне модели.

class User

MINIMUM_STUDENT_START_DATE = '12-03-2018'
MINIMUM_PROFESSOR_START_DATE = '01-01-2018'

before_validation :set_start_date

def set_start_date
  if type == 'student' && start_date < MINIMUM_STUDENT_START_DATE
    self.start_date = MINIMUM_STUDENT_START_DATE
  elsif type == 'professor' && start_date < MINIMUM_PROFESSOR_START_DATE
    self.start_date = MINIMUM_PROFESSOR_START_DATE
  end
end
...