使用Ruby on Rails 5连接表

时间:2018-03-26 16:49:46

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 ruby-on-rails-3.2

我有模型ArticleLanguage(表articleslanguages)。 文章has_many languages和语言belongs_to article。 我想用他们的语言选择文章。 我在Article模型中使用它:

def self.articles_per_page(limit, offset)
  joins("LEFT JOIN languages ON languages.article_id = articles.id")
  .select('articles.id, languages.language, COUNT(languages.id) as all_languages')
  .limit(limit).offset(offset)
  .group('articles.id, languages.language')
end

articles_controller

def get_per_page
  limit = 40
  render json: Article.articles_per_page(limit, params[:offset])
end

然后我提出Ajax请求获取文章及其语言的JSON回复:

$.get(articlesUrl + '?offset=' + offset, function(article){
    $.each(article, function(index, performance){
        $('#articleTable').append(// DATA //);
    });
            offset = $('#articleTable').children('.articleRow').length;
        })

问题在于,如果我在articles表中有1篇文章,并且在语言表中有与本文相关的示例3种语言,则返回3行,文章相同。

2 个答案:

答案 0 :(得分:1)

考虑到你写道“我想用他们的语言选择文章。”你可以简单地写出类方法,如:

def self.articles_per_page(limit, offset)
  includes(:languages).limit(limit).offset(offset)
end

@articles = Article.articles_per_page(10, 0)

= @articles.each do |article|
  = article.whatever
  = article.languages.each do |language|
    = language.whatever
  = article.languages.count # I'd add counter_cache

如果你需要的只是count()我会在文章模型中添加一个counter_cache列:

在language.rb

belongs_to :article, counter_cache: true

然后将languages_count添加到文章模型中,您可以执行以下操作:

= @articles.each do |article|
  = article.languages_count

然而,对于您的选择和组,我假设您可能尝试为查询添加某种性能?如果知道你的观点是什么样的话,那么select / group组合的目的会有所帮助。

答案 1 :(得分:0)

我知道问题是因为我使用.group(articles.id, languages.language, ..),但没有它我会收到错误:

  

Mysql2 ::错误:在没有GROUP BY的聚合查询中,SELECT列表的表达式#1包含非聚合列' .articles.id&#39 ;;这与sql_mode = only_full_group_by:

不兼容

我所做的是删除group(...)config/database.yml

default: &default
    adapter: mysql2
    pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
    timeout: 5000
    username: database_user
    password: database_password
    variables:
        sql_mode: TRADITIONAL # THIS FIX THE PROBLEM

然后重启服务器。