Всем привет.
Последний час я потратил на дебаг очень странного поведения рельсов.
Есть следующие модели
app/models/user.rb
class User < ApplicationRecord
...
has_many :images
has_many :videos
...
has_many :tags
...
end
app/models/image.rb
class Image < ApplicationRecord
...
belongs_to :user
...
has_and_belongs_to_many :tags
...
include TagsFunctions
...
end
app/models/video.rb
class Video < ApplicationRecord
...
include TagsFunctions
...
belongs_to :user
...
has_and_belongs_to_many :tags
...
end
app/models/concerns/tags_functions.rb
module TagsFunctions
extend ActiveSupport::Concern
# хак для заполнения тэгов у вновь создаваемых моделей
included do
attr_accessor :tags_after_creation
after_create -> { self.tags_string = tags_after_creation if tags_after_creation.present? }
end
def tags_string
tags.pluck(:text).join(',')
end
def tags_string=(value)
unless user # Если пользователь еще не заполнен, запоминаем тэги и выходим
@tags_after_creation = value
return
end
@tags_after_creation = ''
self.tags = []
value.to_s.split(',').map(&:strip).each do |tag_text| # разбиваем строку, используя запятую, как разделитель
tag = user.tags.find_or_create_by(text: tag_text) # получаем/создаем нужные тэги
self.tags << tag # записываем тэги в ассоциацию
end
end
end
Выполняем вот такой код:
user = User.first
tags_string = 'test'
image = user.images.create(tags_string: tags_string)
video = user.videos.create(tags_string: tags_string)
В результате, в
video.tags
мы имеем два одинаковых (дублирующихся) тега.
В
image.tags
- один тег.
Если выполнить код вот так:
user = User.first
tags_string = 'test'
image = Image.create(user: user, tags_string: tags_string)
video = Video.create(user: user, tags_string: tags_string)
то все в порядке, один тег и там и там.
И теперь еще большая мистика (для меня). Если в
video.rb
переместить
include TagsFunctions
после has_and_belongs_to_many :tags
, то все начинает работать правильно и с первым вариантом кода.
Мне казалось, что я хорошо знаю рельсы, но это поведение ставит меня в тупик.
Версия рельсов: 5.1.1
Кто может объяснить такое поведение?