简体   繁体   中英

Rails: Inner join with acts-as-taggable-on's find_related_tags gives mysql error

I've got the following structure set up in ActiveRecord in Rails 3

class Domain < AR
  has_and_belongs_to_many :videos
end

class Video < AR
  has_and_belongs_to_many :domains
  acts_as_taggable_on :tags
  scope :with_state, lambda { |s| where('state = ?', s)  }
end

Somewhere in my controller I want to find other videos from a video based on a certain tag, wich is quite easy using the find_related_tags method. But I need to restrict the related videos to the current domain which is present through a helper method called current_domain , so I came up with the following AR query:

@video = Video.find(params[:id])
@video.find_related_tags.joins(:domains).with_state(:converted).where('domains.id = ?', current_domain.id)

This AR query produces the following MySQL query:

SELECT videos.*, COUNT(tags.id) AS count FROM videos, tags, taggings
INNER JOIN `domains_videos` ON `domains_videos`.`video_id` = `videos`.`id`
INNER JOIN `domains` ON `domains`.`id` = `domains_videos`.`domain_id`
WHERE (videos.id != 5 AND videos.id = taggings.taggable_id 
  AND taggings.taggable_type = 'Video'
  AND taggings.tag_id = tags.id
  AND tags.name IN ('not'))
  AND (state = 'converted')
  AND (domains.id = 4)
GROUP BY videos.id
ORDER BY count DESC

It seems fine to me, but it produces a MySQL error:

Mysql2::Error: Unknown column 'videos.id' in 'on clause'

And that I don't get! Why is videos.id an unkown column in

INNER JOIN `domains_videos` ON `domains_videos`.`video_id` = `videos`.`id`

All join tables are properly set up. Everything works. If I remove the .joins(:domains) part it works... I'm sure it's something simple I'm just not seeing :)

It seems that the MySQL query is valid, but the videos.id column is unknown cause videos is not in the join set but only used in the FROM clause. So I ended up with the solution to do the following:

Video.find_by_sql("
  SELECT videos.*, COUNT(tags.id) AS count
  FROM videos
  INNER JOIN domains_videos ON domains_videos.video_id = videos.id
  INNER JOIN domains ON domains.id = domains_videos.domain_id
  INNER JOIN taggings ON videos.id = taggings.taggable_id AND taggings.taggable_type = '#{self.class.to_s}'
  INNER JOIN tags ON taggings.tag_id = tags.id
  WHERE tags.name IN (#{joined_tags})
  AND videos.state = 'converted'
  AND domains.id = #{domain.id}
  AND videos.id != #{id}
  GROUP BY videos.id
  ORDER BY count DESC
  LIMIT #{limit}
")

Since everything is really joined now, the statement now is valid for MySQL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM