Class has too many lines. [210/110] Open
class IterationService
DAYS_IN_WEEK = (1.week / 1.day)
VELOCITY_ITERATIONS = 3
STD_DEV_ITERATIONS = 10
DEFAULT_VELOCITY = 10
- Read upRead up
- Exclude checks
This cop checks if the length a class exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.
Complex method IterationService#group_by_day (67.0) Open
def group_by_day(range = nil)
@group_by_day = {}
@group_by_day[range] ||= begin
accepted = @accepted_stories
accepted = accepted.select { |story| story.accepted_at >= range.first && story.accepted_at < range.last } if range
- Read upRead up
- Exclude checks
Flog calculates the ABC score for methods. The ABC score is based on assignments, branches (method calls), and conditions.
You can read more about ABC metrics or the flog tool
Assignment Branch Condition size for group_by_day is too high. [44.88/25] Open
def group_by_day(range = nil)
@group_by_day = {}
@group_by_day[range] ||= begin
accepted = @accepted_stories
accepted = accepted.select { |story| story.accepted_at >= range.first && story.accepted_at < range.last } if range
- Read upRead up
- Exclude checks
This cop checks that the ABC size of methods is not higher than the configured maximum. The ABC size is based on assignments, branches (method calls), and conditions. See http://c2.com/cgi/wiki?AbcMetric
Class IterationService
has 22 methods (exceeds 20 allowed). Consider refactoring. Open
class IterationService
DAYS_IN_WEEK = (1.week / 1.day)
VELOCITY_ITERATIONS = 3
STD_DEV_ITERATIONS = 10
DEFAULT_VELOCITY = 10
Complex method IterationService#backlog_iterations (38.4) Open
def backlog_iterations(velocity_value = velocity)
velocity_value = 1 if velocity_value < 1
@backlog_iterations ||= {}
# mimics the project.js rebuildIteration() function
@backlog_iterations[velocity_value] ||= begin
- Read upRead up
- Exclude checks
Flog calculates the ABC score for methods. The ABC score is based on assignments, branches (method calls), and conditions.
You can read more about ABC metrics or the flog tool
Assignment Branch Condition size for backlog_iterations is too high. [26.74/25] Open
def backlog_iterations(velocity_value = velocity)
velocity_value = 1 if velocity_value < 1
@backlog_iterations ||= {}
# mimics the project.js rebuildIteration() function
@backlog_iterations[velocity_value] ||= begin
- Read upRead up
- Exclude checks
This cop checks that the ABC size of methods is not higher than the configured maximum. The ABC size is based on assignments, branches (method calls), and conditions. See http://c2.com/cgi/wiki?AbcMetric
Complex method IterationService#group_by_developer (36.8) Open
def group_by_developer
@group_by_developer ||= begin
min_iteration = @accepted_stories.map(&:iteration_number).min
max_iteration = @accepted_stories.map(&:iteration_number).max
@accepted_stories.
- Read upRead up
- Exclude checks
Flog calculates the ABC score for methods. The ABC score is based on assignments, branches (method calls), and conditions.
You can read more about ABC metrics or the flog tool
Complex method IterationService#backlog_date (32.8) Open
def backlog_date(calculate_worst = false)
iterations = backlog_iterations(velocity)
last_iteration_number = iterations.last.number
if calculate_worst
std_dev = Statistics.standard_deviation(group_by_velocity.values, STD_DEV_ITERATIONS)
- Read upRead up
- Exclude checks
Flog calculates the ABC score for methods. The ABC score is based on assignments, branches (method calls), and conditions.
You can read more about ABC metrics or the flog tool
Complex method IterationService#velocity (27.5) Open
def velocity(number_of_iterations = VELOCITY_ITERATIONS)
return DEFAULT_VELOCITY if group_by_all_iterations.size.zero?
@velocity ||= {}
@velocity[number_of_iterations] ||= begin
number_of_iterations = group_by_all_iterations.size if number_of_iterations > group_by_all_iterations.size
- Read upRead up
- Exclude checks
Flog calculates the ABC score for methods. The ABC score is based on assignments, branches (method calls), and conditions.
You can read more about ABC metrics or the flog tool
Complex method IterationService#iteration_start_date (20.1) Open
def iteration_start_date(date = nil)
date = start_date if date.nil?
iteration_start_date = date.beginning_of_day
if start_date.wday != iteration_start_day
day_difference = start_date.wday - iteration_start_day
- Read upRead up
- Exclude checks
Flog calculates the ABC score for methods. The ABC score is based on assignments, branches (method calls), and conditions.
You can read more about ABC metrics or the flog tool
Use group[next_date] = accepted.fetch(next_date, group.fetch(next_date - 1.day, 0))
instead of group.merge!(next_date => accepted.fetch(next_date, group.fetch(next_date - 1.day, 0)))
. Open
group.merge!(next_date => accepted.fetch(next_date, group.fetch(next_date - 1.day, 0)))
- Read upRead up
- Exclude checks
This cop identifies places where Hash#merge!
can be replaced by
Hash#[]=
.
Example:
hash.merge!(a: 1)
hash.merge!({'key' => 'value'})
hash.merge!(a: 1, b: 2)
Place the . on the next line, together with the method name. Open
data.merge(state => current_iteration.
- Exclude checks
Space inside parentheses detected. Open
last_date = backlog_iterations.last.start_date + ( project.iteration_length * DAYS_IN_WEEK )
- Exclude checks
Line is too long. [117/100] Open
@dummy_user ||= User.find_or_create_by!(username: "dummy", email: "dummy@foo.com", name: "Dummy", initials: "XX")
- Exclude checks
Prefer single-quoted strings when you don't need string interpolation or special symbols. Open
@dummy_user ||= User.find_or_create_by!(username: "dummy", email: "dummy@foo.com", name: "Dummy", initials: "XX")
- Exclude checks
Align reduce
with @accepted_stories.
on line 106. Open
reduce({}) do |group, iteration|
- Exclude checks
Pass &:accepted_at
as an argument to sort_by
instead of a block. Open
accepted = accepted.sort_by { |story| story.accepted_at }.group_by { |story| story.accepted_at.to_date }
- Read upRead up
- Exclude checks
Use symbols as procs when possible.
Example:
# bad
something.map { |s| s.upcase }
# good
something.map(&:upcase)
Space inside parentheses detected. Open
@backlog = ( @stories - @accepted_stories ).guaranteed_sort_by(&:position)
- Exclude checks
%w
-literals should be delimited by [
and ]
. Open
%w(started finished delivered accepted rejected).reduce({}) do |data, state|
- Read upRead up
- Exclude checks
This cop enforces the consistent usage of %
-literal delimiters.
Specify the 'default' key to set all preferred delimiters at once. You can continue to specify individual preferred delimiters to override the default.
Example:
# Style/PercentLiteralDelimiters:
# PreferredDelimiters:
# default: '[]'
# '%i': '()'
# good
%w[alpha beta] + %i(gamma delta)
# bad
%W(alpha #{beta})
# bad
%I(alpha beta)
Place the . on the next line, together with the method name. Open
@accepted_stories.
- Exclude checks
Line is too long. [122/100] Open
# with calculate_worst = false calculates the final project date based on the average velocity for the past 3 iterations
- Exclude checks
Use iterations.size.positive?
instead of iterations.size > 0
. Open
if iterations.size > 0
- Read upRead up
- Exclude checks
This cop checks for usage of comparison operators (==
,
>
, <
) to test numbers as zero, positive, or negative.
These can be replaced by their respective predicate methods.
The cop can also be configured to do the reverse.
The cop disregards nonzero?
as it its value is truthy or falsey,
but not true
and false
, and thus not always interchangeable with
!= 0
.
Example:
# EnforcedStyle: predicate (default)
# bad
foo == 0
0 > foo
bar.baz > 0
# good
foo.zero?
foo.negative?
bar.baz.positive?
Example:
# EnforcedStyle: comparison
# bad
foo.zero?
foo.negative?
bar.baz.positive?
# good
foo == 0
0 > foo
bar.baz > 0
Place the . on the next line, together with the method name. Open
@accepted_stories = @stories.
- Exclude checks
Align reduce
with @accepted_stories.
on line 146. Open
reduce({}) do |group, iteration|
- Exclude checks
Space missing inside }. Open
data = (min_iteration..max_iteration).reduce({}) { |group, key| group.merge(key => 0)}
- Exclude checks
Space inside parentheses detected. Open
@backlog = ( @stories - @accepted_stories ).guaranteed_sort_by(&:position)
- Exclude checks
Space inside parentheses detected. Open
( days_apart / days_in_iteration ).floor + 1
- Exclude checks
Line is too long. [103/100] Open
extra_iterations = ( std_dev * iterations.size / mean_of_last_ten_iterations ).round
- Exclude checks
Space inside parentheses detected. Open
extra_iterations = ( std_dev * iterations.size / mean_of_last_ten_iterations ).round
- Exclude checks
Line is too long. [110/100] Open
accepted = accepted.sort_by { |story| story.accepted_at }.group_by { |story| story.accepted_at.to_date }
- Exclude checks
Line is too long. [111/100] Open
[ last_iteration_number, date_for_iteration_number(last_iteration_number) + project.iteration_length.days ]
- Exclude checks
Avoid multi-line chains of blocks. Open
end.
reduce({}) do |group, iteration|
- Read upRead up
- Exclude checks
This cop checks for chaining of a block after another block that spans multiple lines.
Example:
Thread.list.find_all do |t|
t.alive?
end.map do |t|
t.object_id
end
Prefer single-quoted strings when you don't need string interpolation or special symbols. Open
@dummy_user ||= User.find_or_create_by!(username: "dummy", email: "dummy@foo.com", name: "Dummy", initials: "XX")
- Exclude checks
Place the . on the next line, together with the method name. Open
select { |record| record.owned_by.nil? }.
- Exclude checks
Line is too long. [113/100] Open
ten_iterations_slice = Statistics.slice_to_sample_size(group_by_velocity.values, STD_DEV_ITERATIONS)
- Exclude checks
Place the . on the next line, together with the method name. Open
end.
- Exclude checks
Place the . on the next line, together with the method name. Open
group_by { |story| story.iteration_number }.
- Exclude checks
Space inside square brackets detected. Open
[ last_iteration_number, date_for_iteration_number(last_iteration_number) + project.iteration_length.days ]
- Exclude checks
Favor unless
over if
for negative conditions. Open
if !backlog_iteration.can_take_story?(story)
# Iterations sometimes 'overflow', i.e. an iteration may contain a
# 5 point story but the project velocity is 1. In this case, the
# next iteration that can have a story added is the current + 4.
next_number = backlog_iteration.number + 1 + (backlog_iteration.overflows_by / velocity_value).ceil
- Read upRead up
- Exclude checks
Checks for uses of if with a negated condition. Only ifs without else are considered. There are three different styles:
- both
- prefix
- postfix
Example:
# EnforcedStyle: both
# enforces `unless` for `prefix` and `postfix` conditionals
# good
unless foo
bar
end
# bad
if !foo
bar
end
# good
bar unless foo
# bad
bar if !foo
Example:
# EnforcedStyle: prefix
# enforces `unless` for just `prefix` conditionals
# good
unless foo
bar
end
# bad
if !foo
bar
end
# good
bar if !foo
Example:
# EnforcedStyle: postfix
# enforces `unless` for just `postfix` conditionals
# good
bar unless foo
# bad
bar if !foo
# good
if !foo
bar
end
Align reduce
with @accepted_stories.
on line 146. Open
reduce({}) do |group, iteration|
- Exclude checks
Align group_by
with @accepted_stories.
on line 146. Open
group_by { |story| story.iteration_number }.
- Exclude checks
Prefer single-quoted strings when you don't need string interpolation or special symbols. Open
relation = relation.where("accepted_at > ? or accepted_at is null", since) if since
- Exclude checks
Pass &:iteration_number
as an argument to group_by
instead of a block. Open
owner.last.group_by { |story| story.iteration_number }.
- Read upRead up
- Exclude checks
Use symbols as procs when possible.
Example:
# bad
something.map { |s| s.upcase }
# good
something.map(&:upcase)
Place the . on the next line, together with the method name. Open
select { |story| story.column == '#done' }.
- Exclude checks
Place the . on the next line, together with the method name. Open
@group_by_iteration ||= @accepted_stories.
- Exclude checks
Place the . on the next line, together with the method name. Open
@group_by_bugs ||= @accepted_stories.
- Exclude checks
Space inside parentheses detected. Open
reduce(0) { |points, story| points + (story.estimate || 0) } )
- Exclude checks
Space inside parentheses detected. Open
extra_iterations = ( std_dev * iterations.size / mean_of_last_ten_iterations ).round
- Exclude checks
Prefer single-quoted strings when you don't need string interpolation or special symbols. Open
@dummy_user ||= User.find_or_create_by!(username: "dummy", email: "dummy@foo.com", name: "Dummy", initials: "XX")
- Exclude checks
Pass &:accepted_at
as an argument to select
instead of a block. Open
accepted += backlog_iterations.first.select { |story| story.accepted_at }
- Read upRead up
- Exclude checks
Use symbols as procs when possible.
Example:
# bad
something.map { |s| s.upcase }
# good
something.map(&:upcase)
Line is too long. [101/100] Open
# with calculate_worst = true add the standard deviation of the velocity for the past 10 iterations
- Exclude checks
Line is too long. [111/100] Open
std_dev = Statistics.standard_deviation(group_by_velocity.values, STD_DEV_ITERATIONS)
- Exclude checks
Place the . on the next line, together with the method name. Open
group_by { |story| story.owned_by.name }.
- Exclude checks
Line is too long. [112/100] Open
number_of_iterations = group_by_all_iterations.size if number_of_iterations > group_by_all_iterations.size
- Exclude checks
Annotation keywords like FIXME
should be all upper case, followed by a colon, and a space, then a note describing the problem. Open
# FIXME must figure out why the Story allows a nil owner in delivered states
- Exclude checks
Place the . on the next line, together with the method name. Open
@backlog.
- Exclude checks
Space inside parentheses detected. Open
( days_apart / days_in_iteration ).floor + 1
- Exclude checks
Line is too long. [121/100] Open
accepted = accepted.select { |story| story.accepted_at >= range.first && story.accepted_at < range.last } if range
- Exclude checks
Pass &:iteration_number
as an argument to group_by
instead of a block. Open
group_by { |story| story.iteration_number }.
- Read upRead up
- Exclude checks
Use symbols as procs when possible.
Example:
# bad
something.map { |s| s.upcase }
# good
something.map(&:upcase)
Line is too long. [117/100] Open
next_number = backlog_iteration.number + 1 + (backlog_iteration.overflows_by / velocity_value).ceil
- Exclude checks
Use day_difference.negative?
instead of day_difference < 0
. Open
day_difference += DAYS_IN_WEEK if day_difference < 0
- Read upRead up
- Exclude checks
This cop checks for usage of comparison operators (==
,
>
, <
) to test numbers as zero, positive, or negative.
These can be replaced by their respective predicate methods.
The cop can also be configured to do the reverse.
The cop disregards nonzero?
as it its value is truthy or falsey,
but not true
and false
, and thus not always interchangeable with
!= 0
.
Example:
# EnforcedStyle: predicate (default)
# bad
foo == 0
0 > foo
bar.baz > 0
# good
foo.zero?
foo.negative?
bar.baz.positive?
Example:
# EnforcedStyle: comparison
# bad
foo.zero?
foo.negative?
bar.baz.positive?
# good
foo == 0
0 > foo
bar.baz > 0
Place the . on the next line, together with the method name. Open
owner.last.group_by { |story| story.iteration_number }.
- Exclude checks
Align select
with @stories.
on line 20. Open
select { |story| story.accepted_at < iteration_start_date(@current_time) }
- Exclude checks
Space inside square brackets detected. Open
[ last_iteration_number, date_for_iteration_number(last_iteration_number) + project.iteration_length.days ]
- Exclude checks
Space inside parentheses detected. Open
days_apart = ( compare_date - iteration_start_date ) / 1.day
- Exclude checks
Space inside parentheses detected. Open
days_apart = ( compare_date - iteration_start_date ) / 1.day
- Exclude checks
Space inside parentheses detected. Open
last_date = backlog_iterations.last.start_date + ( project.iteration_length * DAYS_IN_WEEK )
- Exclude checks
Place the . on the next line, together with the method name. Open
select { |story| story.state == state }.
- Exclude checks
Pass &:iteration_number
as an argument to group_by
instead of a block. Open
group_by { |story| story.iteration_number }.
- Read upRead up
- Exclude checks
Use symbols as procs when possible.
Example:
# bad
something.map { |s| s.upcase }
# good
something.map(&:upcase)
Use !empty?
instead of size > 0
. Open
if iterations.size > 0
- Read upRead up
- Exclude checks
This cop checks for numeric comparisons that can be replaced by a predicate method, such as receiver.length == 0, receiver.length > 0, receiver.length != 0, receiver.length < 1 and receiver.size == 0 that can be replaced by receiver.empty? and !receiver.empty.
Example:
# bad
[1, 2, 3].length == 0
0 == "foobar".length
array.length < 1
{a: 1, b: 2}.length != 0
string.length > 0
hash.size > 0
# good
[1, 2, 3].empty?
"foobar".empty?
array.empty?
!{a: 1, b: 2}.empty?
!string.empty?
!hash.empty?
Place the . on the next line, together with the method name. Open
@accepted_stories.
- Exclude checks
Place the . on the next line, together with the method name. Open
group_by { |story| story.iteration_number }.
- Exclude checks
Place the . on the next line, together with the method name. Open
select { |story| story.column != '#chilly_bin' }.
- Exclude checks
Unnecessary spacing detected. Open
accepted = accepted.select { |story| story.accepted_at >= range.first && story.accepted_at < range.last } if range
- Exclude checks
Align select
with @stories.
on line 20. Open
select { |story| story.column == '#done' }.
- Exclude checks
Align group_by
with @accepted_stories.
on line 106. Open
group_by { |story| story.iteration_number }.
- Exclude checks
Prefer single-quoted strings when you don't need string interpolation or special symbols. Open
@dummy_user ||= User.find_or_create_by!(username: "dummy", email: "dummy@foo.com", name: "Dummy", initials: "XX")
- Exclude checks