Поиск пользователей по возрасту по дате рождения

У меня возникают проблемы с пониманием того, как выполнять поиск по диапазону возраста пользователя по дате его рождения. Моя БД хранит только пользовательскую доб. Я хочу, чтобы посетители использовали форму расширенного поиска и выполняли поиск по возрасту, например, "18-23", "28-36" и т. Д.

Я пробовал несколько вещей, но ни одна из них не работает. Я добавил область действия для модели User, def min & max age и еще одно решение, которое не сработало. Возможно, я правильно понимаю часть кода, но не выполняю другую часть. Я не уверен. Если кто-то может направить меня в правильном направлении, это было бы здорово, чтобы я мог научиться этому.

Когда я выполняю поиск по выбранному возрасту, он возвращает всех пользователей.

Поиск модели:

attr_accessible :age, :children, :ethnicity, :career, :gender, :religion, :zip_code, :birthday, :max_age, :min_age, :youngest_age, :oldest_age

  def users
    @users ||= find_users
  end

    private

  def find_users
    users = User.order(:id)
    users = users.where(gender: gender) if gender.present?
       users = users.where(zip_code: zip_code) if zip_code.present?
       users = users.where(children: children) if children.present?
       users = users.where(religion: religion) if religion.present?
       users = users.where(ethnicity: ethnicity) if ethnicity.present?
       users = users.where("birthday >= ? AND birthday <= ?", 80.years.ago + 1.day, 18.years.ago)


       users
  end
end

Search_Form:

<%= select(@object, :youngest_age, (18..75).to_a) %> to <%= select(@object, :oldest_age, (18..75).to_a) %>

4 ответа

Решение

Это должно сделать это:

# view
<%= select @object, :min_age, (18..75).to_a %>
to
<%= select @object, :max_age, (18..75).to_a %>

# controller
def show
  @search = Search.find(params[:id])
  @users = @search.users
end

# Search model
def find_users
  users = User.order(:id)
  users = users.where(gender: gender) if gender.present?
  users = users.where(zip_code: zip_code) if zip_code.present?
  users = users.where(children: children) if children.present?
  users = users.where(religion: religion) if religion.present?
  users = users.where(ethnicity: ethnicity) if ethnicity.present?

  if min_age.present? && max_age.present?
    min = [ min_age, max_age ].min
    max = [ min_age, max_age ].max
    min_date = Date.today - min.years
    max_date = Date.today - max.years
    users = users.where("birthday BETWEEN ? AND ?", max_date, min_date)
  end
  users
end

Вам нужно будет передать два параметра из формы поиска в контроллер. Я предполагаю, что они будут params[:youngest_age] а также params[:oldest_age] за это. Я также предполагаю, что это будут целые числа (например: params[:youngest_age] = 18)

youngest_age = params[:youngest_age].years
oldest_age = params[:oldest_age].years

User.where("birthday >= ? AND birthday <= ?", Date.today - youngest_age, Date.today - oldest_age)

Похоже, в вашем коде есть ошибка в этом методе:

def find_users
  users = User.order(:id)
  users = users.where(gender: gender) if gender.present?
  users = users.where(zip_code: zip_code) if zip_code.present?
  users = users.where(children: children) if children.present?
  users = users.where(religion: religion) if religion.present?
  users = users.where(ethnicity: ethnicity) if ethnicity.present?
  users = User.where("birthday >= ? AND birthday <= ?", 80.years.ago + 1.day, 18.years.ago)
  users
end

От второй до последней строки, перед тем как возвращать пользователей, вы называете "User.where", а не "users.where". По сути, вы начинаете новый запрос в этой точке, а не складываете все условия вместе.

Исправить последнее where пункт вашего find_users метод использовать users отношение, поэтому вы продолжаете цепочку запросов вместо User класс модели, который эффективно сбрасывает область запроса.

Для поиска по диапазону дат в вашем запросе можно было бы полностью избежать использования строковых фрагментов SQL, используя обычный диапазон ruby:

Модель пользователя:

def self.with_age_range(year_range)
  today = Date.today
  where birthday: (today - year_range.max.years)..(today - year_range.min.years)
end

И назовите это следующим образом:

User.with_age_range 18..23

Или в вашем контроллере:

@users = User.with_age_range params[:min_age]..params[:max_age]
Другие вопросы по тегам