diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2016-01-23 23:34:30 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2016-01-23 23:34:30 +0900 |
commit | 841e9796cdeda4288675a3df7b2e984454698a49 (patch) | |
tree | 494e7071b4efcf4d9ca999e718edaaa04475afab | |
parent | c3d4489f007ecd22328c90e4dbcf873776014735 (diff) | |
download | aclog-841e9796cdeda4288675a3df7b2e984454698a49.tar.gz |
web: get rid of page=x in user/public best
-rw-r--r-- | app/controllers/tweets_controller.rb | 74 | ||||
-rw-r--r-- | app/models/tweet.rb | 14 | ||||
-rw-r--r-- | frontend/src/lib/aclog.js | 44 |
3 files changed, 64 insertions, 68 deletions
diff --git a/app/controllers/tweets_controller.rb b/app/controllers/tweets_controller.rb index 29eb603..5cfaf3e 100644 --- a/app/controllers/tweets_controller.rb +++ b/app/controllers/tweets_controller.rb @@ -27,39 +27,39 @@ class TweetsController < ApplicationController end def user_best - @tweets = @user.tweets.reacted.parse_recent(params[:recent]).order_by_reactions.paginate(params) - render_tweets + @tweets = @user.tweets.reacted.parse_recent(params[:recent]).order_by_reactions + render_tweets(:reactions_count) end def user_timeline - @tweets = @user.tweets.reacted(params[:reactions]).order_by_id.paginate(params) - render_tweets + @tweets = @user.tweets.reacted(params[:reactions]).order_by_id + render_tweets(:id) end def user_favorites - @tweets = Tweet.reacted(params[:reactions]).favorited_by(@user).order("favorites.id DESC").includes(user: :account).paginate(params) - render_tweets + @tweets = Tweet.reacted(params[:reactions]).favorited_by(@user).order("favorites.id DESC").includes(user: :account) + render_tweets(:page) end def user_favorited_by @source_user = authorize! User.find(screen_name: params[:source_screen_name]) - @tweets = @user.tweets.reacted(params[:reactions]).favorited_by(@source_user).order("favorites.tweet_id DESC").paginate(params) - render_tweets + @tweets = @user.tweets.reacted(params[:reactions]).favorited_by(@source_user).order("favorites.tweet_id DESC") + render_tweets(:id) end def all_best - @tweets = Tweet.reacted.parse_recent(params[:recent]).order_by_reactions.includes(user: :account).paginate(params) - render_tweets + @tweets = Tweet.reacted.parse_recent(params[:recent]).order_by_reactions.includes(user: :account) + render_tweets(:reactions_count) end def all_timeline - @tweets = Tweet.reacted(params[:reactions]).order_by_id.includes(user: :account).paginate(params) - render_tweets + @tweets = Tweet.reacted(params[:reactions]).order_by_id.includes(user: :account) + render_tweets(:id) end def filter - @tweets = Tweet.recent((params[:period] || 7).days).filter_by_query(params[:q].to_s).order_by_id.includes(user: :account).paginate(params) - render_tweets + @tweets = Tweet.recent((params[:period] || 7).days).filter_by_query(params[:q].to_s).order_by_id.includes(user: :account) + render_tweets(:id) end private @@ -77,27 +77,37 @@ class TweetsController < ApplicationController statuses: sts } end - def render_tweets - if request.format.atom? - return render("tweets") + def paginate_tweets(type) + qhash = Rack::Utils.parse_query(request.query_string) + page_per = params[:count] ? [params[:count].to_i, Settings.tweets.count.max].min : Settings.tweets.count.default + + case type + when :id + @tweets = @tweets.limit(page_per).max_id(params[:max_id]).since_id(params[:since_id]) + { prev: qhash.merge(since_id: @tweets.first.id.to_s, max_id: ""), + next: qhash.merge(since_id: "", max_id: (@tweets.last.id - 1).to_s) } + when :reactions_count + @tweets = @tweets.limit(page_per).not_reacted_than(params[:last_reactions], params[:last_id]) + { next: qhash.merge(last_reactions: @tweets.last.reactions_count, last_id: @tweets.last.id.to_s) } + when :page + page = [params[:page].to_i, 1].max + @tweets = @tweets.page(page, page_per) + { prev: page == 1 ? nil : params.merge(page: page - 1), + next: params.merge(page: page + 1) } end + end - hash = { - user: @user.as_json(methods: :registered), - statuses: @tweets.map(&method(:transform_tweet)) } - - if @tweets.length > 0 - if !params[:page] && @tweets.order_values.all? {|o| !o.is_a?(String) && o.expr.name == :id } - hash[:prev] = params.dup.tap {|h| h.delete(:max_id) }.merge!(since_id: @tweets.first.id.to_s) - hash[:next] = params.dup.tap {|h| h.delete(:since_id) }.merge!(max_id: (@tweets.last.id - 1).to_s) - else - page = [params[:page].to_i, 1].max - hash[:prev] = page == 1 ? nil : params.merge(page: page - 1) - hash[:next] = params.merge(page: page + 1) - end - end + def render_tweets(pagination) + qhash = paginate_tweets(pagination) - render_json data: hash + if request.format.atom? + render "tweets" + else + qhash.merge!(user: @user.as_json(methods: :registered), + statuses: @tweets.map(&method(:transform_tweet))) + + render_json data: qhash + end end def transform_tweet(tweet) diff --git a/app/models/tweet.rb b/app/models/tweet.rb index 9dbb289..ba39f78 100644 --- a/app/models/tweet.rb +++ b/app/models/tweet.rb @@ -17,24 +17,14 @@ class Tweet < ActiveRecord::Base scope :max_id, ->(id) { where("tweets.id <= ?", id.to_i) if id } scope :since_id, ->(id) { where("tweets.id > ?", id.to_i) if id } + scope :not_reacted_than, ->(last_count, last_id) { where("reactions_count < ? OR (reactions_count = ? AND id < ?)", last_count, last_count, last_id) if last_count } scope :page, ->(page, page_per) { limit(page_per).offset((page - 1) * page_per) } scope :order_by_id, -> { order(id: :desc) } - scope :order_by_reactions, -> { order(reactions_count: :desc) } + scope :order_by_reactions, -> { order(reactions_count: :desc, id: :desc) } scope :favorited_by, ->(user) { joins(:favorites).where(favorites: { user: user }) } - # should be called in last - scope :paginate, ->(params) { - page_per = params[:count] ? [params[:count].to_i, Settings.tweets.count.max].min : Settings.tweets.count.default - - if !params[:page] && self.all.order_values.all? {|o| !o.is_a?(String) && o.expr.name == :id } - limit(page_per).max_id(params[:max_id]).since_id(params[:since_id]) - else - page([params[:page].to_i, 1].max, page_per) - end - } - class << self # Builds a new instance of Tweet and initialize with JSON data from Twitter API. # @note This method just builds an instance, doesn't save it. diff --git a/frontend/src/lib/aclog.js b/frontend/src/lib/aclog.js index 1e7ec6d..b41f459 100644 --- a/frontend/src/lib/aclog.js +++ b/frontend/src/lib/aclog.js @@ -2,7 +2,7 @@ import Settings from "../../settings"; import Storage from "storage"; import utils from "utils"; -var encodeQuery = (params) => { +var encodeQuery = params => { if (!params) return ""; var keys = Object.keys(params); if (keys.length === 0) return ""; @@ -10,8 +10,23 @@ var encodeQuery = (params) => { return keys.map(key => [key, params[key]].map(encodeURIComponent).join("=")).join("&"); } -var continueRequest = promise => { - return promise.then(res => res.json().then(json => [res, json])).then(xx => { +var request = (method, endpoint, params, body) => { + if (Settings.debug) console.log("[API Request] " + method + " " + endpoint + " query: " + encodeQuery(params) + " body: " + encodeQuery(body)); + var url = utils.getCurrentBaseUrl() + "/i/api/" + endpoint + ".json"; + var opts = { + method: method, + credentials: "include", + headers: { }, + }; + + if (method === "post") { + opts.headers["content-type"] = "application/x-www-form-urlencoded; charset=UTF-8"; + opts.body = encodeQuery(Object.assign({ authenticity_token: Storage.store.authenticity_token }, body)); + } else { + url += "?" + encodeQuery(params); + } + + return fetch(url, opts).then(res => res.json().then(json => [res, json])).then(xx => { var [res, json] = xx; if (res.status >= 400) { var error = new Error(res.statusText); @@ -24,27 +39,8 @@ var continueRequest = promise => { }); }; -var get = (endpoint, params) => { - if (Settings.debug) console.log("[API Request] " + endpoint + " query: " + encodeQuery(params)); - var url = utils.getCurrentBaseUrl() + "/i/api/" + endpoint + ".json?" + encodeQuery(params); - return continueRequest(fetch(url, { - method: "get", - credentials: "include", - })); -} - -var post = (endpoint, body) => { - if (Settings.debug) console.log("[API Request] " + endpoint + " body: " + encodeQuery(body)); - var url = utils.getCurrentBaseUrl() + "/i/api/" + endpoint + ".json"; - return continueRequest(fetch(url, { - method: "post", - credentials: "include", - headers: { - "content-type": "application/x-www-form-urlencoded; charset=UTF-8" - }, - body: encodeQuery(Object.assign({ authenticity_token: Storage.store.authenticity_token }, body)) - })); -} +var get = (endpoint, params) => request("get", endpoint, params, null); +var post = (endpoint, body) => request("post", endpoint, null, body); export default { users: { |