5266


UserはItemを複数所持していて  
ItemはScoreを複数所持していて  
Scoreにはvalueというintegerの値を持っているという構成のとき  
１ユーザが所持しているItemsの中身をスコアの合計値が大きい順に並べ替えしたいです。

[code]

    class User < ActiveRecord::Base
      has_many :items
    
      def mostScoreItems(start=0, length=65535)
        items
        .includes(:scores)
        .select('sum(value) as sum_value')
        .group('items.id')
        .order('sum_value desc')
        .references(:scores)
      end
    end
    
[/code]

前回の質問でなんとかここまででき、なんとか求めているデータを取得する事ができたのですが  
いくつか実現したいことがあります。

① mostScoreItemsの第一引数startの値で、ソートを掛けた順のstartの値からデータを取得したい。

② mostScoreItemsの第二引数のlengthの値で、指定した件数だけデータを取得したい。

③ メソッドチェーンができなくなってるっぽいので、できるようにしたい。

恐らく、③を解決すれば、第一引数のstartは.offsetで繋ぎ、lengthは.limitで繋ぐことで、引数を渡す必要がなくなり、①と②も解決する上、コードの汎用性も高くなって幸せな気分になれると思ったのですが、Rails初心者のため、どうしてチェーンが切れてしまうのか、切れないようにするにはどのオブジェクトを返せばいいのか等、色々迷ってしまったため実現できませんでした。

そのため、引数をとるという方法で解決しようと思い.orderの後や.selectの後などに.limitや.offsetを付けてみたのですが駄目でした。

どうすれば解決できるか皆様の意見よろしくお願いいたします。


CC BY-SA 3.0
2015-01-25T14:45:02.473
5265
2015-01-26T10:58:31.833
2015-01-25T14:52:46.420
5840
5840
question
rails-activerecord
rails4でアイテムに付けられたスコアの合計値が大きい順のデータを取得するには？


おそらくこんな感じでできると思います。

[code]

    def most_score_items(offset = 0, limit = 65535)
      self
        .items
        .joins(:scores)
        .group("scores.item_id")
        .order("sum(scores.value) desc, items.id")
        .select("items.*, sum(scores.value) as sum_value")
        .offset(offset)
        .limit(limit)
    end
    
[/code]

合計値は、特異メソッド `sum_value` でアクセス出来ます。

[code]

    res = User.most_score_items
    # => #<ActiveRecord::AssociationRelation [#<Item>, ...]
    res.first.sum_value
    # => 1234
    
[/code]

SQL としては、

[code]

    SELECT  items.*, sum(scores.value) as sum_value
    FROM "items"
    INNER JOIN "scores" ON "scores"."item_id" = "items"."id"
    WHERE "items"."user_id" = ?
    GROUP BY scores.item_id
    ORDER BY sum(scores.value) desc, items.id
    LIMIT ?
    OFFSET ?
    
[/code]

となります。

なお、標準SQLでは、`SELECT`句で作成した`sum_value`は`ORDER BY`句で利用できないため、`sum(scores.value)`
と指定しています。(RDBMSによっては問題無く使えます。)


CC BY-SA 3.0
2015-01-25T15:31:26.413
5266
2015-01-26T10:58:31.833
2015-01-26T10:58:31.833
76
76
5265
answer