Rails: Фильтр, сравнивая две модели - PullRequest
0 голосов
/ 14 ноября 2018

Я запутался в сопоставлении между двумя моделями. Я исследовал StackOverflow и Google до 2 дней, но ни в коем случае ... Есть больше вопросов и ответов о сопоставлении и фильтрации, но речь идет об одностороннем поиске, листинге. Может быть, я не мог понять, я не уверен. Например: У меня есть содержимое и пользователи в моем приложении. Я поделился контентом, и я не хочу делать его видимым, приятным для всех пользователей. Пользователи должны видеть, кто;

  • Больше 18 лет и меньше 70.
  • должен жить в Англии и Город лондон (Может быть изменяемым)
  • они должны иметь водительские права
  • пол: человек бла бла и т. Д.

Моей первой идеей было создание профиля для пользователей и получение информации от них. Также создайте фильтр профиля для модели Content и заполните форму как Белов.

Но проблема на последнем этапе; «Как я сравниваю их только для пользователей, которые могут видеть, и кому нравится, у кого истинные атрибуты такие же, как у Content атрибутов фильтра.

Модель;

User и Content

Profile принадлежит_ user

Contentfilter принадлежит_ Content

Чем; Показать содержимое, если атрибуты профиля current_user совпадают с фильтрами содержимого.

У вас есть предложения? Спасибо.

1 Ответ

0 голосов
/ 14 ноября 2018

Я предполагаю, что вы имеете в виду любой соответствующий контент, но я предоставляю решение для ВСЕХ или ЛЮБЫХ фильтров соответствия профиля.

Вот одно быстрое решение о том, как вы можете достичь того, чего хотите.

Учитывая следующие модели:

# app/models/user.rb
class User < ApplicationRecord
  has_one :profile, as: :profilable

  def all_matching_content
    profile: Profile.where(
      "? >= age", profile.age).
      where(
        gender: profile.gender,
        city: profile.city,
        license: profile.license).
      where(profilable_type: "Content"))
  end

  def any_matching_content
    Content.where(
      profile: Profile.where("? >= age", profile.age).
        or(Profile.where(gender: profile.gender)).
        or(Profile.where(city: profile.city)).
        or(Profile.where(license: profile.license)).
      where(profilable_type: "Content"))
    end
  end
end

# app/models/profile.rb
class Profile < ApplicationRecord
  belongs_to :profilable, polymorphic: true, optional: true
end

# app/models/content.rb
class Content < ApplicationRecord
  has_one :profile, as: :profilable
end

И следующие миграции:

# db/migrate/20181114004031_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :name, index: true
      t.timestamps
    end
  end
end

# db/migrate/20181114004134_create_profiles.rb
class CreateProfiles < ActiveRecord::Migration[5.2]
  def change
    create_table :profiles do |t|
      t.references :profilable, polymorphic: true, null: true
      t.boolean :license, index: true
      t.string :city, index: true
      t.string :gender, index: true
      t.integer :age, index: true
      t.timestamps
      t.index [:license, :city, :gender, :age], name: "profile_composite_index"
    end
  end
end

# db/migrate/20181114004307_create_contents.rb
class CreateContents < ActiveRecord::Migration[5.2]
  def change
    create_table :contents do |t|
      t.string :title, index: true
      t.timestamps
    end
  end
end

И следующие семена:

# db/seeds.rb
User.create!(
  name: "John",
  profile: Profile.create!(
    license: true,
    city: "London",
    gender: "Male",
    age: 19
  )
)

User.create!(
  name: "Jane",
  profile: Profile.create!(
    license: false,
    city: "London",
    gender: "Female",
    age: 17
  )
)

User.create!(
  name: "Rose",
  profile: Profile.create!(
    license: true,
    city: "Edinburgh",
    gender: "Female",
    age: 21
  )
)

User.create!(
  name: "Hans",
  profile: Profile.create!(
    license: true,
    city: "Berlin",
    gender: "Male",
    age: 24
  )
)

Content.create!(
  title: "London introduces new tax",
  profile: Profile.create!(
    city: "London"
  )
)

Content.create!(
  title: "New license requirements in Berlin",
  profile: Profile.create!(
    city: "Berlin",
    license: true
  )
)

Content.create!(
  title: "Women should get new immunization",
  profile: Profile.create!(
    gender: "Female"
  )
)

Content.create!(
  title: "Adults only expo opens Wednesday",
  profile: Profile.create!(
    age: 18
  )
)

Вы будетеуметь выполнять следующие действия:

> john = User.find_by(name: "John")
> john.all_matching_content
=> #<ActiveRecord::Relation []>

> john.any_matching_content.map(&:title)
=> ["London introduces new tax", "New license requirements in Berlin", "Adults only expo opens Wednesday"]

> jane = User.find_by(name: "Jane")
> jane.any_matching_content.map(&:title)
=> ["London introduces new tax", "Women should get new immunization"]

> rose = User.find_by(name: "Rose")
> rose.any_matching_content.map(&:title)
=> ["New license requirements in Berlin", "Women should get new immunization", "Adults only expo opens Wednesday"]

> hans = User.find_by(name: "Hans")
> hans.any_matching_content.map(&:title)
=> ["New license requirements in Berlin", "Adults only expo opens Wednesday"]

Решение работает путем совместного использования полиморфной модели Profile с User и Content.Затем он сопоставляет Content с экземпляром User, передавая атрибуты пользователя Profile в запрос на сопоставление профилей, принадлежащих к типам Content.

Обратите внимание, что метод #all_matching_content требует, чтобы всеАтрибуты профиля совпадают, в основном это означает, что все условия в запросе - "И".Вместо этого метод #any_matching_content использует условия «ИЛИ».

Я загрузил быстрый проект в GitHub с уже закодированным примером:

https://github.com/JurgenJocubeit/so-53289847

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...