我花了一个小时调试一个非常奇怪的 rails 行为。鉴于:
应用程序/模型/user.rb
class User < ApplicationRecord
...
has_many :images
has_many :videos
...
has_many :tags
...
end
应用程序/模型/image.rb
class Image < ApplicationRecord
...
belongs_to :user
...
has_and_belongs_to_many :tags
...
include TagsFunctions
...
end
应用程序/模型/video.rb
class Video < ApplicationRecord
...
include TagsFunctions
...
belongs_to :user
...
has_and_belongs_to_many :tags
...
end
应用程序/模型/tag.rb
class Tag < ApplicationRecord
belongs_to :user
validates :text, uniqueness: {scope: :user}, presence: true
before_create :set_code
def set_code
return if self[:code].present?
loop do
self[:code] = [*'A'..'Z'].sample(8).join
break if Tag.find_by(code: self[:code]).nil?
end
end
end
应用程序/模型/关注/tags_functions.rb
module TagsFunctions
extend ActiveSupport::Concern
# hack for new models
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)
它将提供 1 个项目image.tags
,但 2 个重复项目video.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)
一切正常,图像 1 个标签,视频 1 个标签
甚至更多...如果我们移到include TagsFunctions
下面 has_and_belongs_to_many :tags
的video.rb
文件中,两个代码示例都可以正常工作。
我以为我很了解 Rails,但这种行为对我来说真的不清楚。
导轨版本:5.1.1