diff --git a/.rubocop.yml b/.rubocop.yml index 8dfcc0a2..d7ad8780 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -23,7 +23,7 @@ Lint/UnderscorePrefixedVariableName: # Offense count: 6 Metrics/AbcSize: - Max: 33 + Max: 33.56 # Offense count: 1 # Configuration parameters: CountComments. diff --git a/app/controllers/api/tomatoes_controller.rb b/app/controllers/api/tomatoes_controller.rb index 09128953..1055d21c 100644 --- a/app/controllers/api/tomatoes_controller.rb +++ b/app/controllers/api/tomatoes_controller.rb @@ -5,7 +5,10 @@ class TomatoesController < BaseController # GET /api/tomatoes def index - @tomatoes = current_user.tomatoes.order_by([[:created_at, :desc], [:_id, :desc]]).page params[:page] + @tomatoes = current_user.tomatoes + @tomatoes = @tomatoes.after(from) if from + @tomatoes = @tomatoes.before(to) if to + @tomatoes = @tomatoes.order_by([[:created_at, :desc], [:_id, :desc]]).page params[:page] render json: Presenter::Tomatoes.new(@tomatoes) end @@ -44,6 +47,14 @@ def destroy private + def from + @from ||= Time.zone.parse(params[:from].to_s) + end + + def to + @to ||= Time.zone.parse(params[:to].to_s) + end + def find_tomato @tomato = current_user.tomatoes.find(params[:id]) end diff --git a/app/controllers/tomatoes_controller.rb b/app/controllers/tomatoes_controller.rb index ecd500b5..a30e05f8 100644 --- a/app/controllers/tomatoes_controller.rb +++ b/app/controllers/tomatoes_controller.rb @@ -58,7 +58,7 @@ def create if @tomato.save format.js do @highlight = @tomato - @tomatoes = current_user.tomatoes.after(Time.zone.now.beginning_of_day) + @tomatoes = current_user.tomatoes.after(Time.zone.now.beginning_of_day).order_by([[:created_at, :desc]]) @tomatoes_count = current_user.tomatoes_counters @projects = @tomatoes.collect(&:projects).flatten.uniq diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index bcb59a78..5d9c735c 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -16,7 +16,7 @@ def new_tomato end def daily_tomatoes - @tomatoes ||= current_user.tomatoes.after(Time.zone.now.beginning_of_day) + @tomatoes ||= current_user.tomatoes.after(Time.zone.now.beginning_of_day).order_by([[:created_at, :desc]]) end def tomatoes_counters diff --git a/app/models/tomato.rb b/app/models/tomato.rb index 47501e56..752ccf27 100644 --- a/app/models/tomato.rb +++ b/app/models/tomato.rb @@ -22,11 +22,10 @@ class Tomato include ActionView::Helpers::TextHelper include ApplicationHelper - class << self - def after(time) - where(created_at: { '$gte': time }).order_by([[:created_at, :desc]]) - end + scope :before, -> (time) { where(:created_at.lt => time) } + scope :after, -> (time) { where(:created_at.gte => time) } + class << self def by_day(tomatoes) to_lines(tomatoes) do |tomatoes_by_day| yield(tomatoes_by_day) @@ -65,7 +64,7 @@ def projects private def must_not_overlap - last_tomato = user.tomatoes.after(Time.zone.now - DURATION.seconds).first + last_tomato = user.tomatoes.after(Time.zone.now - DURATION.seconds).order_by([[:created_at, :desc]]).first return unless last_tomato limit = (DURATION.seconds - (Time.zone.now - last_tomato.created_at)).seconds errors.add(:base, "Must not overlap saved tomaotes, please wait #{humanize(limit)}") diff --git a/app/views/pages/api_reference.html.md b/app/views/pages/api_reference.html.md index 92dba76b..7ec7b6e4 100644 --- a/app/views/pages/api_reference.html.md +++ b/app/views/pages/api_reference.html.md @@ -209,6 +209,10 @@ Authorization: d994a295cf68342b99e3036827d3ef8a * `page` a positive integer value to select a page in the range [1, `total_pages`] +* `from` a ISO 8601 date time, selects tomatoes where `created_at` is greater + than or equals to the parameter value +* `to` a ISO 8601 date time, selects tomatoes where `created_at` is less than + the parameter value #### Response diff --git a/test/functional/api/tomatoes_controller_test.rb b/test/functional/api/tomatoes_controller_test.rb index 61efa2af..3d851f6c 100644 --- a/test/functional/api/tomatoes_controller_test.rb +++ b/test/functional/api/tomatoes_controller_test.rb @@ -6,14 +6,17 @@ class TomatoesControllerTest < ActionController::TestCase @user = User.create!(name: 'name', email: 'email@example.com') @user.authorizations.create!(provider: 'tomatoes', token: '123') @tomato1 = @user.tomatoes.build - @tomato1.created_at = 2.hours.ago + @tomato1.created_at = 3.hours.ago @tomato1.save! @tomato2 = @user.tomatoes.build(tag_list: 'one, two') - @tomato2.created_at = 1.hour.ago + @tomato2.created_at = 2.hours.ago @tomato2.save! + @tomato3 = @user.tomatoes.build(tag_list: 'three, four') + @tomato3.created_at = 1.hour.ago + @tomato3.save! @other_user = User.create! - @tomato3 = @other_user.tomatoes.create! + @other_tomato = @other_user.tomatoes.create! end teardown do @@ -36,7 +39,40 @@ class TomatoesControllerTest < ActionController::TestCase tomatoes_ids = parsed_response['tomatoes'].map { |t| t['id'] } assert_includes tomatoes_ids, @tomato1.id.to_s assert_includes tomatoes_ids, @tomato2.id.to_s - assert_not_includes tomatoes_ids, @tomato3.id.to_s + assert_includes tomatoes_ids, @tomato3.id.to_s + assert_not_includes tomatoes_ids, @other_tomato.id.to_s + end + + test 'GET /index, it should return current user\'s list of tomatoes filtered by date (from)' do + get :index, token: '123', from: 150.minutes.ago.iso8601 + assert_response :success + assert_equal 'application/json', @response.content_type + parsed_response = JSON.parse(@response.body) + tomatoes_ids = parsed_response['tomatoes'].map { |t| t['id'] } + assert_equal tomatoes_ids.size, 2 + assert_includes tomatoes_ids, @tomato2.id.to_s + assert_includes tomatoes_ids, @tomato3.id.to_s + end + + test 'GET /index, it should return current user\'s list of tomatoes filtered by date (from, to)' do + get :index, token: '123', from: 150.minutes.ago.iso8601, to: 90.minutes.ago.iso8601 + assert_response :success + assert_equal 'application/json', @response.content_type + parsed_response = JSON.parse(@response.body) + tomatoes_ids = parsed_response['tomatoes'].map { |t| t['id'] } + assert_equal tomatoes_ids.size, 1 + assert_includes tomatoes_ids, @tomato2.id.to_s + end + + test 'GET /index, it should return current user\'s list of tomatoes filtered by date (to)' do + get :index, token: '123', to: 90.minutes.ago.iso8601 + assert_response :success + assert_equal 'application/json', @response.content_type + parsed_response = JSON.parse(@response.body) + tomatoes_ids = parsed_response['tomatoes'].map { |t| t['id'] } + assert_equal tomatoes_ids.size, 2 + assert_includes tomatoes_ids, @tomato1.id.to_s + assert_includes tomatoes_ids, @tomato2.id.to_s end test 'GET /show, given an invalid token, it should return an error' do @@ -55,7 +91,7 @@ class TomatoesControllerTest < ActionController::TestCase test 'GET /show, it should not return other users\' tomatoes' do assert_raises(Mongoid::Errors::DocumentNotFound) do - get :show, token: '123', id: @tomato3.id.to_s + get :show, token: '123', id: @other_tomato.id.to_s end end