ignat-z / ducalis Goto Github PK
View Code? Open in Web Editor NEWRuboCop based static code analyzer for enterprise Rails applications.
Home Page: https://ducalis-rb.github.io/
License: MIT License
RuboCop based static code analyzer for enterprise Rails applications.
Home Page: https://ducalis-rb.github.io/
License: MIT License
It's much descriptive to use \x
mode for multi-lines regexes
Use x
modifier for complex regexps. This makes them more readable and you can add some useful comments. Just be careful as spaces are ignored.
regexp = %r{
start # some text
\s # white space char
(group) # first group
(?:alt1|alt2) # some alternation
end
}x
Related links:
Argumentation from: https://brandur.org/mediator#lean-jobs, seems like worker class knows too much if it is more than ~20 lines.
It seems like https://ducalis-rb.github.io/ has no backlink to the GitHub project
False positive triggering
def create_message_struct(message)
objects = message["objects"].map { |object| convert_message_object(object) }
Auditor::Message.new(message, objects)
end
def complete=(value, complete_at)
value = value.to_b
self.complete_at = complete_at if complete && value
self.complete_at = nil unless value
end
Records like
gem 'wirble', :group => :development
gem 'wirble', group: :development
gem 'rest-client', require: 'rest_client'
#1
class A
module B
include C
end
end
#2
module A
class B
class << self
include C
end
end
end
Add link to Confreaks video
https://www.youtube.com/watch?v=HctYHe-YjnE
https://github.com/ignat-z/ducalis/blob/master/lib/ducalis/cops/preferable_methods.rb
delete
method, some kind of: "if there is no name
suffix in calling variable name && arguments count <=1 && if argument exists it is a variable"save(validate: false)
update_attribute
update_column
update_columns
toggle
seems like they are pretty unique in Ruby scope.
2.2+
Create documentation GitHub page to not pollute source code with documentation changes.
All collection of methods from object:
Object.new.methods
# => [:tap, :public_send, :instance_variables, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :is_a?, :instance_variable_get, :instance_of?, :public_method, :extend, :define_singleton_method, :singleton_method, :to_enum, :enum_for, :<=>, :===, :=~, :!~, :eql?, :respond_to?, :freeze, :inspect, :display, :object_id, :send, :to_s, :method, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :==, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]
Ok for gems, okish for business objects, not ok for business logic.
Something about not only actual tap
using but about moving variable to method or inline it as is
You describe nicely the bad cases and why to improve it. It would be great of you would show in code how you would make each case better. This increases the understanding tremendously.
make it clear what is filters
validates :year, numericality: { only_integer: true },
inclusion: { in: Date.current.year - 1..Date.current.year + 2 }
[
Date.today - RATE_CHANGES_DAYS,
Date.today + RATE_CHANGES_DAYS
]
def initialize
@used_year = settings[:year] || Date.current.year
@used_quarter = settings[:quarter] || quarter(Date.current)
end
Import.where(begin_date: Date.today, end_date: Date.today).first_or_create!
From Thor to OptionParser
Add args
argument to black list
Add example with passing hash as variable with **
[bugfix]
specs.DETAILS
const.Comment PR if someone changed business logic (ruby file in app/
) but there is no any changes in specs
Ducalis force to use update in migrations even in rails <4 (c)
scope :active, -> { where(completed_at: nil) } # good
scope :active, -> { where(tasks: { completed_at: nil }) } # better
Nice to have some kind of comment to make ducalis
happy and increase bus factor by passing explanation why it violates rules
# ducalis:disable: use `delete_all` because of performance reasons
def remove_garbage
AuditLog.where(user_id: user_id).delete_all
end
Rule of thumb: count one for each group, join, having, where, order in your query. More than three? Things will 💥 blow up.
https://deliveroo.engineering/guidelines/active-record/#query-objects
Probably enforce fetch
calling on params
hash. Use fetch
for hash access with default,
hash[:name] || DEFAULT_NAME
# to
hash.fetch(:name. DEFAULT_NAME)
# or
hash.fetch(:name) { DEFAULT_NAME }
Explanation:
ActionController::ParameterMissing
and KeyError
gets raised right where error happens -- on fetching params. ActionController::ParameterMissing
is more descriptive than ActiveRecord::RecordNotFound
with strange Couldn't find Model with 'id'=
, additionally it saves request to DB.
Deny public_send
, send
, and __send__
methods to prevent security issues and make it easier to grep code.
TBD
I'm not sure, but regexes like this should be banned:
/json|yaml/
/(>=)|(<=)|(~>)|(>)|(<)|(=)/
/Access Denied/
%r{^/(book|chapter)}
There are some alternatives:
ALLOWED_FORMATS = %w[json yaml] && Regexp.union(ALLOWED_FORMATS)
OPERATORS = %w(>= <= > < =) && Regexp.new(OPERATORS.map { |key| "(#{key})" }.join('|'))
'bookshelf'.include?('book')
Regexp.new("^/(#{%w(book chapter).join('|')})")
Benchmark results:
(n > 2)
Warming up --------------------------------------
regex mode 136.908k i/100ms
union mode 135.833k i/100ms
pure regex mode 131.355k i/100ms
include mode 123.399k i/100ms
Calculating -------------------------------------
regex mode 2.422M (± 6.5%) i/s - 12.185M in 5.052242s
union mode 2.416M (± 6.1%) i/s - 12.089M in 5.022020s
pure regex mode 2.478M (± 5.2%) i/s - 12.479M in 5.049099s
include mode 2.047M (± 6.1%) i/s - 10.242M in 5.022063s
Comparison:
pure regex mode: 2478188.8 i/s
regex mode: 2422086.8 i/s - same-ish: difference falls within error
union mode: 2416283.1 i/s - same-ish: difference falls within error
include mode: 2046944.6 i/s - 1.21x slower
(n <= 2)
Warming up --------------------------------------
regex mode 130.949k i/100ms
union mode 136.502k i/100ms
pure regex mode 132.738k i/100ms
include mode 165.892k i/100ms
Calculating -------------------------------------
regex mode 2.397M (± 6.4%) i/s - 12.047M in 5.046537s
union mode 2.436M (± 5.4%) i/s - 12.149M in 5.002772s
pure regex mode 2.364M (± 6.9%) i/s - 11.814M in 5.020348s
include mode 4.042M (± 6.7%) i/s - 20.239M in 5.030716s
Comparison:
include mode: 4041834.5 i/s
union mode: 2435537.5 i/s - 1.66x slower
regex mode: 2396910.8 i/s - 1.69x slower
pure regex mode: 2364418.7 i/s - 1.71x slower
Benchmark source:
require 'benchmark/ips'
SUBJECT = 'bookshelf.xml'
LONG_FORMATS = %w[json yaml xml]
LONG_PURE_REGEX = /json|yaml|xml/
LONG_UNION_REGEX = Regexp.union(LONG_FORMATS)
LONG_FORMAT_REGEX = Regexp.new(LONG_FORMATS.join('|'))
Benchmark.ips do |x|
puts '(n > 2)'
x.report("regex mode") { SUBJECT =~ LONG_FORMAT_REGEX }
x.report("union mode") { SUBJECT =~ LONG_UNION_REGEX }
x.report("pure regex mode") { SUBJECT =~ LONG_PURE_REGEX }
x.report("include mode") do
LONG_FORMATS.any? { |format| SUBJECT.include?(format) }
end
x.compare!
end
SHORT_FORMATS = %w[xml json]
SHORT_PURE_REGEX = /xml|json/
SHORT_UNION_REGEX = Regexp.union(SHORT_FORMATS)
SHORT_FORMAT_REGEX = Regexp.new(SHORT_FORMATS.join('|'))
Benchmark.ips do |x|
puts '(n <= 2)'
x.report("regex mode") { SUBJECT =~ SHORT_FORMAT_REGEX }
x.report("union mode") { SUBJECT =~ SHORT_UNION_REGEX }
x.report("pure regex mode") { SUBJECT =~ SHORT_PURE_REGEX }
x.report("include mode") do
SHORT_FORMATS.any? { |format| SUBJECT.include?(format) }
end
x.compare!
end
http://java-performance.info/regexp-related-methods-of-string/
It's better to encapsulate actions with session
and cookies
into separate services like DAO.
UPD: And Redis
Ignore Rails.cache.delete(cache_key)
Ignore params.delete(:key_id)
namespace :copy_data do
def load_remote_yml(environment, path)
yml = "config/database.#{environment}-#{Time.now.strftime '%Y-%m-%d_%H:%M:%S'}.yml"
begin
get path, yml
config = YAML.load_file(yml)
return config[environment.to_s]
rescue
raise
ensure
`rm -f #{yml}`
end
end
end
Something like:
has_paper_trail
)def filtered_admins(reducers)
reducers
.map { |reducer| @base_scope.public_send(reducer) }
.order("admin_users.created_at DESC")
end
Given:
day = params[:day] || Time.zone.today
Ducalis states as followed:
You can use fetch instead:
params.fetch(:day) { Time.zone.today }
but it is not the same for the nil case:
params = {}
params[:day] || Time.zone.today #=> Time.zone.today result
params = { day: nil }
params.fetch(:day) { Time.zone.today } #=> nil
this should not be suggested as better as the expression result is not the same and the cases may differ.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.