Rails-запрос с has_many и own_to неожиданными результатами - PullRequest
0 голосов
/ 25 января 2019

Я создаю приложение Rails, и у меня есть модель с именем Item.Он принадлежит к типу, а has_many типы через ItemTypes.

Когда я запрашиваю Предметы по их ассоциации типов has_many, я не ожидаю результатов, но получаю обратно предметы, когда они принадлежат этому Типу.

# models/item.rb
class Item < ApplicationRecord
  has_many :item_types
  has_many :types, through: :item_types
  belongs_to :type, inverse_of: :items
end

# models/type.rb
class Type < ApplicationRecord
  has_many :items, inverse_of: :item_type, dependent: :nullify
end

# models/itemtype.rb
class ItemType < ApplicationRecord
  belongs_to :item
  belongs_to :type
end

Пример (ожидаемое поведение):

food = Type.create
pizza = Item.create(type: food)

irb> pizza.type
food

irb> pizza.types
[]

Однако, когда я запрашиваю элементы со связанным типом элемента и не ожидаю результатов, я получаю обратно свой элемент, даже если нет объектов ItemType.

irb> Item.where(type: food)
pizza
irb> Item.where(types: food)
pizza

(пицца все еще возвращается, несмотря на то, что pizza.types возвращает [])

Я не уверен, что происходит за кулисами, но я считаю, что это неожиданное поведение,Почему это происходит и как я могу получить свой запрос Item.where(types: food), который не дал результатов?

Ответы [ 2 ]

0 голосов
/ 29 января 2019

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

Проблема в том, что мы запрашиваем элементы по типу или типам, в Item.where(type: food) или * 1004.* types неоднозначны и, по-видимому, ссылаются на отношение отношение__, определенное в модели элементов с помощью belongs_to :type.

Чтобы обойти это, для запроса элементов по их типам элементов вы можете сначала объединить таблицы, используя includes(:item_types) изатем могут запрашивать те ItemTypes, где их тип имеет желаемый экземпляр.

Результирующий запрос, который дает мне желаемый результат: Item.includes(:item_types).where(item_type: {type: food}).

0 голосов
/ 25 января 2019

Ваши модели не совсем корректны;вам нужно наследовать от ApplicationRecord, если вы ожидаете, что они будут работать с базой данных.Вы должны использовать генератор для генерации ваших моделей.

rails g model Item name:string
rails g model Type name:string
rails g model ItemType item:references type:references

Затем измените ваши модели так, чтобы они выглядели так:

class Item < ApplicationRecord
  has_many :item_types
  has_many :types, through: :item_types
end

class Type < ApplicationRecord
  has_many :item_types
  has_many :items, through: :item_types
end

class ItemType < ApplicationRecord
  belongs_to :item
  belongs_to :type
end

Ваш синтаксис подходит для псевдокода, но кодниже должно работать

carbs = Type.create(name: 'Carbs')
pizza = Item.create(name: 'Pizza')
carbs.items << pizza

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

carbs.items.create(name: 'Milkshake')

Затем вы получаете доступ к таким вещам, как:

carbs.items.first.name #=> 'Pizza'
pizza.types.map(&:name) #=> ['Carbs']

Вы можете обратиться к документации по основам ассоциации , чтобы узнать о дополнительных функциях.

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