wrstudios/frodata

View on GitHub
lib/frodata/entity.rb

Summary

Maintainability
C
7 hrs
Test Coverage

Class has too many lines. [237/100]
Open

  class Entity
    # The Entity type name
    attr_reader :type
    # The FrOData::Service's identifying name
    attr_reader :service_name
Severity: Minor
Found in lib/frodata/entity.rb by rubocop

This cop checks if the length a class exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.

Class Entity has 33 methods (exceeds 20 allowed). Consider refactoring.
Open

  class Entity
    # The Entity type name
    attr_reader :type
    # The FrOData::Service's identifying name
    attr_reader :service_name
Severity: Minor
Found in lib/frodata/entity.rb - About 4 hrs to fix

    Assignment Branch Condition size for process_links is too high. [24.52/15]
    Open

        def self.process_links(entity, xml_doc)
          entity.instance_eval do
            new_links = instance_variable_get(:@links) || {}
            schema.navigation_properties[name].each do |nav_name, details|
              xml_doc.xpath("./link[@title='#{nav_name}']").each do |node|
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    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

    Method has too many lines. [17/10]
    Open

        def to_xml
          namespaces = XML_NAMESPACES.merge('xml:base' => service.service_url)
          builder = Nokogiri::XML::Builder.new do |xml|
            xml.entry(namespaces) do
              xml.category(term: type,
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.

    Method process_links has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.
    Open

        def self.process_links(entity, xml_doc)
          entity.instance_eval do
            new_links = instance_variable_get(:@links) || {}
            schema.navigation_properties[name].each do |nav_name, details|
              xml_doc.xpath("./link[@title='#{nav_name}']").each do |node|
    Severity: Minor
    Found in lib/frodata/entity.rb - About 2 hrs to fix

    Cognitive Complexity

    Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

    A method's cognitive complexity is based on a few simple rules:

    • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
    • Code is considered more complex for each "break in the linear flow of the code"
    • Code is considered more complex when "flow breaking structures are nested"

    Further reading

    Method has too many lines. [15/10]
    Open

        def self.process_links(entity, xml_doc)
          entity.instance_eval do
            new_links = instance_variable_get(:@links) || {}
            schema.navigation_properties[name].each do |nav_name, details|
              xml_doc.xpath("./link[@title='#{nav_name}']").each do |node|
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.

    Assignment Branch Condition size for to_xml is too high. [19.13/15]
    Open

        def to_xml
          namespaces = XML_NAMESPACES.merge('xml:base' => service.service_url)
          builder = Nokogiri::XML::Builder.new do |xml|
            xml.entry(namespaces) do
              xml.category(term: type,
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    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

    Method has too many lines. [14/10]
    Open

        def instantiate_property(property_name, value_xml)
          prop_type = schema.get_property_type(name, property_name)
          prop_type, value_type = prop_type.split(/\(|\)/)
    
          if prop_type == 'Collection'
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.

    Assignment Branch Condition size for get_property is too high. [19.34/15]
    Open

        def get_property(property_name)
          prop_name = property_name.to_s
          # Property is lazy loaded
          if properties_xml_value.has_key?(prop_name)
            property = instantiate_property(prop_name, properties_xml_value[prop_name])
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    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

    Method has too many lines. [13/10]
    Open

        def get_property(property_name)
          prop_name = property_name.to_s
          # Property is lazy loaded
          if properties_xml_value.has_key?(prop_name)
            property = instantiate_property(prop_name, properties_xml_value[prop_name])
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.

    Complex method FrOData::Entity::process_links (39.6)
    Open

        def self.process_links(entity, xml_doc)
          entity.instance_eval do
            new_links = instance_variable_get(:@links) || {}
            schema.navigation_properties[name].each do |nav_name, details|
              xml_doc.xpath("./link[@title='#{nav_name}']").each do |node|
    Severity: Minor
    Found in lib/frodata/entity.rb by flog

    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

    Method has too many lines. [12/10]
    Open

        def self.process_metadata(entity, metadata)
          entity.instance_eval do
            new_links = instance_variable_get(:@links) || {}
            schema.navigation_properties[name].each do |nav_name, details|
              href = metadata["#{nav_name}@odata.navigationLink"]
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks if the length of a method exceeds some maximum value. Comment lines can optionally be ignored. The maximum allowed length is configurable.

    Complex method FrOData::Entity#to_xml (28.5)
    Open

        def to_xml
          namespaces = XML_NAMESPACES.merge('xml:base' => service.service_url)
          builder = Nokogiri::XML::Builder.new do |xml|
            xml.entry(namespaces) do
              xml.category(term: type,
    Severity: Minor
    Found in lib/frodata/entity.rb by flog

    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

    FrOData::Entity#to_xml refers to 'xml' more than self (maybe move it to another class?)
    Open

            xml.entry(namespaces) do
              xml.category(term: type,
                           scheme: 'http://docs.oasis-open.org/odata/ns/scheme')
              xml.author { xml.name }
    
    
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Feature Envy occurs when a code fragment references another object more often than it references itself, or when several clients do the same series of manipulations on a particular type of object.

    Feature Envy reduces the code's ability to communicate intent: code that "belongs" on one class but which is located in another can be hard to find, and may upset the "System of Names" in the host class.

    Feature Envy also affects the design's flexibility: A code fragment that is in the wrong class creates couplings that may not be natural within the application's domain, and creates a loss of cohesion in the unwilling host class.

    Feature Envy often arises because it must manipulate other objects (usually its arguments) to get them into a useful form, and one force preventing them (the arguments) doing this themselves is that the common knowledge lives outside the arguments, or the arguments are of too basic a type to justify extending that type. Therefore there must be something which 'knows' about the contents or purposes of the arguments. That thing would have to be more than just a basic type, because the basic types are either containers which don't know about their contents, or they are single objects which can't capture their relationship with their fellows of the same type. So, this thing with the extra knowledge should be reified into a class, and the utility method will most likely belong there.

    Example

    Running Reek on:

    class Warehouse
      def sale_price(item)
        (item.price - item.rebate) * @vat
      end
    end

    would report:

    Warehouse#total_price refers to item more than self (FeatureEnvy)

    since this:

    (item.price - item.rebate)

    belongs to the Item class, not the Warehouse.

    FrOData::Entity has at least 7 instance variables
    Open

      class Entity
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Too Many Instance Variables is a special case of LargeClass.

    Example

    Given this configuration

    TooManyInstanceVariables:
      max_instance_variables: 3

    and this code:

    class TooManyInstanceVariables
      def initialize
        @arg_1 = :dummy
        @arg_2 = :dummy
        @arg_3 = :dummy
        @arg_4 = :dummy
      end
    end

    Reek would emit the following warning:

    test.rb -- 5 warnings:
      [1]:TooManyInstanceVariables has at least 4 instance variables (TooManyInstanceVariables)

    FrOData::Entity has at least 26 methods
    Open

      class Entity
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Too Many Methods is a special case of LargeClass.

    Example

    Given this configuration

    TooManyMethods:
      max_methods: 3

    and this code:

    class TooManyMethods
      def one; end
      def two; end
      def three; end
      def four; end
    end

    Reek would emit the following warning:

    test.rb -- 1 warning:
      [1]:TooManyMethods has at least 4 methods (TooManyMethods)

    FrOData::Entity#to_xml has approx 12 statements
    Open

        def to_xml
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A method with Too Many Statements is any method that has a large number of lines.

    Too Many Statements warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements counts +1 for every simple statement in a method and +1 for every statement within a control structure (if, else, case, when, for, while, until, begin, rescue) but it doesn't count the control structure itself.

    So the following method would score +6 in Reek's statement-counting algorithm:

    def parse(arg, argv, &error)
      if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
        return nil, block, nil                                         # +1
      end
      opt = (val = parse_arg(val, &error))[1]                          # +2
      val = conv_arg(*val)                                             # +3
      if opt and !arg
        argv.shift                                                     # +4
      else
        val[0] = nil                                                   # +5
      end
      val                                                              # +6
    end

    (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)

    FrOData::Entity#instantiate_property has approx 8 statements
    Open

        def instantiate_property(property_name, value_xml)
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A method with Too Many Statements is any method that has a large number of lines.

    Too Many Statements warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements counts +1 for every simple statement in a method and +1 for every statement within a control structure (if, else, case, when, for, while, until, begin, rescue) but it doesn't count the control structure itself.

    So the following method would score +6 in Reek's statement-counting algorithm:

    def parse(arg, argv, &error)
      if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
        return nil, block, nil                                         # +1
      end
      opt = (val = parse_arg(val, &error))[1]                          # +2
      val = conv_arg(*val)                                             # +3
      if opt and !arg
        argv.shift                                                     # +4
      else
        val[0] = nil                                                   # +5
      end
      val                                                              # +6
    end

    (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)

    FrOData::Entity#self.process_links contains iterators nested 2 deep
    Open

              xml_doc.xpath("./link[@title='#{nav_name}']").each do |node|
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A Nested Iterator occurs when a block contains another block.

    Example

    Given

    class Duck
      class << self
        def duck_names
          %i!tick trick track!.each do |surname|
            %i!duck!.each do |last_name|
              puts "full name is #{surname} #{last_name}"
            end
          end
        end
      end
    end

    Reek would report the following warning:

    test.rb -- 1 warning:
      [5]:Duck#duck_names contains iterators nested 2 deep (NestedIterators)

    FrOData::Entity#self.with_properties has approx 7 statements
    Open

        def self.with_properties(new_properties = {}, options = {})
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A method with Too Many Statements is any method that has a large number of lines.

    Too Many Statements warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements counts +1 for every simple statement in a method and +1 for every statement within a control structure (if, else, case, when, for, while, until, begin, rescue) but it doesn't count the control structure itself.

    So the following method would score +6 in Reek's statement-counting algorithm:

    def parse(arg, argv, &error)
      if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
        return nil, block, nil                                         # +1
      end
      opt = (val = parse_arg(val, &error))[1]                          # +2
      val = conv_arg(*val)                                             # +3
      if opt and !arg
        argv.shift                                                     # +4
      else
        val[0] = nil                                                   # +5
      end
      val                                                              # +6
    end

    (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)

    FrOData::Entity#self.from_json has approx 7 statements
    Open

        def self.from_json(json, options = {})
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A method with Too Many Statements is any method that has a large number of lines.

    Too Many Statements warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements counts +1 for every simple statement in a method and +1 for every statement within a control structure (if, else, case, when, for, while, until, begin, rescue) but it doesn't count the control structure itself.

    So the following method would score +6 in Reek's statement-counting algorithm:

    def parse(arg, argv, &error)
      if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
        return nil, block, nil                                         # +1
      end
      opt = (val = parse_arg(val, &error))[1]                          # +2
      val = conv_arg(*val)                                             # +3
      if opt and !arg
        argv.shift                                                     # +4
      else
        val[0] = nil                                                   # +5
      end
      val                                                              # +6
    end

    (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)

    FrOData::Entity#self.process_links has approx 10 statements
    Open

        def self.process_links(entity, xml_doc)
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A method with Too Many Statements is any method that has a large number of lines.

    Too Many Statements warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements counts +1 for every simple statement in a method and +1 for every statement within a control structure (if, else, case, when, for, while, until, begin, rescue) but it doesn't count the control structure itself.

    So the following method would score +6 in Reek's statement-counting algorithm:

    def parse(arg, argv, &error)
      if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
        return nil, block, nil                                         # +1
      end
      opt = (val = parse_arg(val, &error))[1]                          # +2
      val = conv_arg(*val)                                             # +3
      if opt and !arg
        argv.shift                                                     # +4
      else
        val[0] = nil                                                   # +5
      end
      val                                                              # +6
    end

    (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)

    FrOData::Entity#get_property has approx 7 statements
    Open

        def get_property(property_name)
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A method with Too Many Statements is any method that has a large number of lines.

    Too Many Statements warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements counts +1 for every simple statement in a method and +1 for every statement within a control structure (if, else, case, when, for, while, until, begin, rescue) but it doesn't count the control structure itself.

    So the following method would score +6 in Reek's statement-counting algorithm:

    def parse(arg, argv, &error)
      if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
        return nil, block, nil                                         # +1
      end
      opt = (val = parse_arg(val, &error))[1]                          # +2
      val = conv_arg(*val)                                             # +3
      if opt and !arg
        argv.shift                                                     # +4
      else
        val[0] = nil                                                   # +5
      end
      val                                                              # +6
    end

    (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)

    FrOData::Entity#self.process_metadata has approx 7 statements
    Open

        def self.process_metadata(entity, metadata)
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A method with Too Many Statements is any method that has a large number of lines.

    Too Many Statements warns about any method that has more than 5 statements. Reek's smell detector for Too Many Statements counts +1 for every simple statement in a method and +1 for every statement within a control structure (if, else, case, when, for, while, until, begin, rescue) but it doesn't count the control structure itself.

    So the following method would score +6 in Reek's statement-counting algorithm:

    def parse(arg, argv, &error)
      if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
        return nil, block, nil                                         # +1
      end
      opt = (val = parse_arg(val, &error))[1]                          # +2
      val = conv_arg(*val)                                             # +3
      if opt and !arg
        argv.shift                                                     # +4
      else
        val[0] = nil                                                   # +5
      end
      val                                                              # +6
    end

    (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)

    FrOData::Entity#to_xml contains iterators nested 2 deep
    Open

                  property_names.each do |name|
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A Nested Iterator occurs when a block contains another block.

    Example

    Given

    class Duck
      class << self
        def duck_names
          %i!tick trick track!.each do |surname|
            %i!duck!.each do |last_name|
              puts "full name is #{surname} #{last_name}"
            end
          end
        end
      end
    end

    Reek would report the following warning:

    test.rb -- 1 warning:
      [5]:Duck#duck_names contains iterators nested 2 deep (NestedIterators)

    Method process_metadata has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
    Open

        def self.process_metadata(entity, metadata)
          entity.instance_eval do
            new_links = instance_variable_get(:@links) || {}
            schema.navigation_properties[name].each do |nav_name, details|
              href = metadata["#{nav_name}@odata.navigationLink"]
    Severity: Minor
    Found in lib/frodata/entity.rb - About 45 mins to fix

    Cognitive Complexity

    Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

    A method's cognitive complexity is based on a few simple rules:

    • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
    • Code is considered more complex for each "break in the linear flow of the code"
    • Code is considered more complex when "flow breaking structures are nested"

    Further reading

    Complex method FrOData::Entity#get_property (23.7)
    Open

        def get_property(property_name)
          prop_name = property_name.to_s
          # Property is lazy loaded
          if properties_xml_value.has_key?(prop_name)
            property = instantiate_property(prop_name, properties_xml_value[prop_name])
    Severity: Minor
    Found in lib/frodata/entity.rb by flog

    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

    Method to_xml has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
    Open

        def to_xml
          namespaces = XML_NAMESPACES.merge('xml:base' => service.service_url)
          builder = Nokogiri::XML::Builder.new do |xml|
            xml.entry(namespaces) do
              xml.category(term: type,
    Severity: Minor
    Found in lib/frodata/entity.rb - About 35 mins to fix

    Cognitive Complexity

    Cognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.

    A method's cognitive complexity is based on a few simple rules:

    • Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one
    • Code is considered more complex for each "break in the linear flow of the code"
    • Code is considered more complex when "flow breaking structures are nested"

    Further reading

    FrOData::Entity#self.process_links calls 'node.attributes['type']' 3 times
    Open

                next if node.attributes['type'].nil?
                next unless node.attributes['type'].value =~ /^application\/atom\+xml;type=(feed|entry)$/i
                link_type = node.attributes['type'].value =~ /type=entry$/i ? :entity : :collection
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.

    Reek implements a check for Duplicate Method Call.

    Example

    Here's a very much simplified and contrived example. The following method will report a warning:

    def double_thing()
      @other.thing + @other.thing
    end

    One quick approach to silence Reek would be to refactor the code thus:

    def double_thing()
      thing = @other.thing
      thing + thing
    end

    A slightly different approach would be to replace all calls of double_thing by calls to @other.double_thing:

    class Other
      def double_thing()
        thing + thing
      end
    end

    The approach you take will depend on balancing other factors in your code.

    FrOData::Entity assumes too much for instance variable '@properties_xml_value'
    Open

      class Entity
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Classes should not assume that instance variables are set or present outside of the current class definition.

    Good:

    class Foo
      def initialize
        @bar = :foo
      end
    
      def foo?
        @bar == :foo
      end
    end

    Good as well:

    class Foo
      def foo?
        bar == :foo
      end
    
      def bar
        @bar ||= :foo
      end
    end

    Bad:

    class Foo
      def go_foo!
        @bar = :foo
      end
    
      def foo?
        @bar == :foo
      end
    end

    Example

    Running Reek on:

    class Dummy
      def test
        @ivar
      end
    end

    would report:

    [1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar

    Note that this example would trigger this smell warning as well:

    class Parent
      def initialize(omg)
        @omg = omg
      end
    end
    
    class Child < Parent
      def foo
        @omg
      end
    end

    The way to address the smell warning is that you should create an attr_reader to use @omg in the subclass and not access @omg directly like this:

    class Parent
      attr_reader :omg
    
      def initialize(omg)
        @omg = omg
      end
    end
    
    class Child < Parent
      def foo
        omg
      end
    end

    Directly accessing instance variables is considered a smell because it breaks encapsulation and makes it harder to reason about code.

    If you don't want to expose those methods as public API just make them private like this:

    class Parent
      def initialize(omg)
        @omg = omg
      end
    
      private
      attr_reader :omg
    end
    
    class Child < Parent
      def foo
        omg
      end
    end

    Current Support in Reek

    An instance variable must:

    • be set in the constructor
    • or be accessed through a method with lazy initialization / memoization.

    If not, Instance Variable Assumption will be reported.

    FrOData::Entity#self.process_links calls 'node.attributes['type'].value' 2 times
    Open

                next unless node.attributes['type'].value =~ /^application\/atom\+xml;type=(feed|entry)$/i
                link_type = node.attributes['type'].value =~ /type=entry$/i ? :entity : :collection
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.

    Reek implements a check for Duplicate Method Call.

    Example

    Here's a very much simplified and contrived example. The following method will report a warning:

    def double_thing()
      @other.thing + @other.thing
    end

    One quick approach to silence Reek would be to refactor the code thus:

    def double_thing()
      thing = @other.thing
      thing + thing
    end

    A slightly different approach would be to replace all calls of double_thing by calls to @other.double_thing:

    class Other
      def double_thing()
        thing + thing
      end
    end

    The approach you take will depend on balancing other factors in your code.

    FrOData::Entity#[] calls 'get_property(property_name)' 3 times
    Open

          if get_property(property_name).is_a?(::FrOData::Properties::Complex)
            get_property(property_name)
          else
            get_property(property_name).value
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.

    Reek implements a check for Duplicate Method Call.

    Example

    Here's a very much simplified and contrived example. The following method will report a warning:

    def double_thing()
      @other.thing + @other.thing
    end

    One quick approach to silence Reek would be to refactor the code thus:

    def double_thing()
      thing = @other.thing
      thing + thing
    end

    A slightly different approach would be to replace all calls of double_thing by calls to @other.double_thing:

    class Other
      def double_thing()
        thing + thing
      end
    end

    The approach you take will depend on balancing other factors in your code.

    FrOData::Entity#self.process_links calls 'node.attributes' 4 times
    Open

                next if node.attributes['type'].nil?
                next unless node.attributes['type'].value =~ /^application\/atom\+xml;type=(feed|entry)$/i
                link_type = node.attributes['type'].value =~ /type=entry$/i ? :entity : :collection
                new_links[nav_name] = {
                  type: link_type,
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.

    Reek implements a check for Duplicate Method Call.

    Example

    Here's a very much simplified and contrived example. The following method will report a warning:

    def double_thing()
      @other.thing + @other.thing
    end

    One quick approach to silence Reek would be to refactor the code thus:

    def double_thing()
      thing = @other.thing
      thing + thing
    end

    A slightly different approach would be to replace all calls of double_thing by calls to @other.double_thing:

    class Other
      def double_thing()
        thing + thing
      end
    end

    The approach you take will depend on balancing other factors in your code.

    FrOData::Entity assumes too much for instance variable '@properties'
    Open

      class Entity
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Classes should not assume that instance variables are set or present outside of the current class definition.

    Good:

    class Foo
      def initialize
        @bar = :foo
      end
    
      def foo?
        @bar == :foo
      end
    end

    Good as well:

    class Foo
      def foo?
        bar == :foo
      end
    
      def bar
        @bar ||= :foo
      end
    end

    Bad:

    class Foo
      def go_foo!
        @bar = :foo
      end
    
      def foo?
        @bar == :foo
      end
    end

    Example

    Running Reek on:

    class Dummy
      def test
        @ivar
      end
    end

    would report:

    [1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar

    Note that this example would trigger this smell warning as well:

    class Parent
      def initialize(omg)
        @omg = omg
      end
    end
    
    class Child < Parent
      def foo
        @omg
      end
    end

    The way to address the smell warning is that you should create an attr_reader to use @omg in the subclass and not access @omg directly like this:

    class Parent
      attr_reader :omg
    
      def initialize(omg)
        @omg = omg
      end
    end
    
    class Child < Parent
      def foo
        omg
      end
    end

    Directly accessing instance variables is considered a smell because it breaks encapsulation and makes it harder to reason about code.

    If you don't want to expose those methods as public API just make them private like this:

    class Parent
      def initialize(omg)
        @omg = omg
      end
    
      private
      attr_reader :omg
    end
    
    class Child < Parent
      def foo
        omg
      end
    end

    Current Support in Reek

    An instance variable must:

    • be set in the constructor
    • or be accessed through a method with lazy initialization / memoization.

    If not, Instance Variable Assumption will be reported.

    FrOData::Entity#self.extract_metadata calls 'key =~ /@odata/' 2 times
    Open

          metadata = json.select { |key, val| key =~ /@odata/ }
          json.delete_if { |key, val| key =~ /@odata/ }
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    Duplication occurs when two fragments of code look nearly identical, or when two fragments of code have nearly identical effects at some conceptual level.

    Reek implements a check for Duplicate Method Call.

    Example

    Here's a very much simplified and contrived example. The following method will report a warning:

    def double_thing()
      @other.thing + @other.thing
    end

    One quick approach to silence Reek would be to refactor the code thus:

    def double_thing()
      thing = @other.thing
      thing + thing
    end

    A slightly different approach would be to replace all calls of double_thing by calls to @other.double_thing:

    class Other
      def double_thing()
        thing + thing
      end
    end

    The approach you take will depend on balancing other factors in your code.

    Complex method FrOData::Entity::process_metadata (21.8)
    Open

        def self.process_metadata(entity, metadata)
          entity.instance_eval do
            new_links = instance_variable_get(:@links) || {}
            schema.navigation_properties[name].each do |nav_name, details|
              href = metadata["#{nav_name}@odata.navigationLink"]
    Severity: Minor
    Found in lib/frodata/entity.rb by flog

    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

    FrOData::Entity#instantiate_property performs a nil-check
    Open

          if klass.nil?
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A NilCheck is a type check. Failures of NilCheck violate the "tell, don't ask" principle.

    Additionally, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.

    Example

    Given

    class Klass
      def nil_checker(argument)
        if argument.nil?
          puts "argument isn't nil!"
        end
      end
    end

    Reek would emit the following warning:

    test.rb -- 1 warning:
      [3]:Klass#nil_checker performs a nil-check. (NilCheck)

    FrOData::Entity#is_new? performs a nil-check
    Open

          self[primary_key].nil?
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A NilCheck is a type check. Failures of NilCheck violate the "tell, don't ask" principle.

    Additionally, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.

    Example

    Given

    class Klass
      def nil_checker(argument)
        if argument.nil?
          puts "argument isn't nil!"
        end
      end
    end

    Reek would emit the following warning:

    test.rb -- 1 warning:
      [3]:Klass#nil_checker performs a nil-check. (NilCheck)

    FrOData::Entity#self.from_json performs a nil-check
    Open

          return nil if json.nil?
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A NilCheck is a type check. Failures of NilCheck violate the "tell, don't ask" principle.

    Additionally, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.

    Example

    Given

    class Klass
      def nil_checker(argument)
        if argument.nil?
          puts "argument isn't nil!"
        end
      end
    end

    Reek would emit the following warning:

    test.rb -- 1 warning:
      [3]:Klass#nil_checker performs a nil-check. (NilCheck)

    FrOData::Entity#self.from_xml performs a nil-check
    Open

          return nil if xml_doc.nil?
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A NilCheck is a type check. Failures of NilCheck violate the "tell, don't ask" principle.

    Additionally, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.

    Example

    Given

    class Klass
      def nil_checker(argument)
        if argument.nil?
          puts "argument isn't nil!"
        end
      end
    end

    Reek would emit the following warning:

    test.rb -- 1 warning:
      [3]:Klass#nil_checker performs a nil-check. (NilCheck)

    FrOData::Entity#self.process_links performs a nil-check
    Open

                next if node.attributes['type'].nil?
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A NilCheck is a type check. Failures of NilCheck violate the "tell, don't ask" principle.

    Additionally, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.

    Example

    Given

    class Klass
      def nil_checker(argument)
        if argument.nil?
          puts "argument isn't nil!"
        end
      end
    end

    Reek would emit the following warning:

    test.rb -- 1 warning:
      [3]:Klass#nil_checker performs a nil-check. (NilCheck)

    FrOData::Entity#self.process_metadata performs a nil-check
    Open

              next if href.nil?
    Severity: Minor
    Found in lib/frodata/entity.rb by reek

    A NilCheck is a type check. Failures of NilCheck violate the "tell, don't ask" principle.

    Additionally, type checks often mask bigger problems in your source code like not using OOP and / or polymorphism when you should.

    Example

    Given

    class Klass
      def nil_checker(argument)
        if argument.nil?
          puts "argument isn't nil!"
        end
      end
    end

    Reek would emit the following warning:

    test.rb -- 1 warning:
      [3]:Klass#nil_checker performs a nil-check. (NilCheck)

    Complex method FrOData::Entity::process_properties (20.1)
    Open

        def self.process_properties(entity, xml_doc)
          entity.instance_eval do
            unless instance_variable_get(:@context)
              context = xml_doc.xpath('/entry').first.andand['context']
              instance_variable_set(:@context, context)
    Severity: Minor
    Found in lib/frodata/entity.rb by flog

    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 each_key instead of each.
    Open

            schema.navigation_properties[name].each do |nav_name, details|
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for uses of each_key and each_value Hash methods.

    Note: If you have an array of two-element arrays, you can put parentheses around the block arguments to indicate that you're not working with a hash, and suppress RuboCop offenses.

    Example:

    # bad
    hash.keys.each { |k| p k }
    hash.values.each { |v| p v }
    hash.each { |k, _v| p k }
    hash.each { |_k, v| p v }
    
    # good
    hash.each_key { |k| p k }
    hash.each_value { |v| p v }

    Use options[:context] = metadata['@odata.context'] instead of options.merge!(context: metadata['@odata.context']).
    Open

          options.merge!(context: metadata['@odata.context'])
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    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)

    Line is too long. [117/80]
    Open

        # Instantiating properties takes time, so we can lazy load properties by passing xml_value and lookup when needed
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    Line is too long. [95/80]
    Open

                link_type = node.attributes['type'].value =~ /type=entry$/i ? :entity : :collection
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    Use a guard clause instead of wrapping the code inside a conditional expression.
    Open

          if klass.nil?
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    Use a guard clause instead of wrapping the code inside a conditional expression

    Example:

    # bad
    def test
      if something
        work
      end
    end
    
    # good
    def test
      return unless something
      work
    end
    
    # also good
    def test
      work if something
    end
    
    # bad
    if something
      raise 'exception'
    else
      ok
    end
    
    # good
    raise 'exception' if something
    ok

    Space inside parentheses detected.
    Open

        def set_property_lazy_load(name, xml_value )
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    Checks for spaces inside ordinary round parentheses.

    Example:

    # bad
    f( 3)
    g = (a + 3 )
    
    # good
    f(3)
    g = (a + 3)

    private (on line 236) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    Open

        def self.extract_metadata(json)
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for private or protected access modifiers which are applied to a singleton method. These access modifiers do not make singleton methods private/protected. private_class_method can be used for that.

    Example:

    # bad
    
    class C
      private
    
      def self.method
        puts 'hi'
      end
    end

    Example:

    # good
    
    class C
      def self.method
        puts 'hi'
      end
    
      private_class_method :method
    end

    Example:

    # good
    
    class C
      class << self
        private
    
        def method
          puts 'hi'
        end
      end
    end

    Rename is_new? to new?.
    Open

        def is_new?
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop makes sure that predicates are named properly.

    Example:

    # bad
    def is_even?(value)
    end
    
    # good
    def even?(value)
    end
    
    # bad
    def has_value?
    end
    
    # good
    def value?
    end

    Use Hash#key? instead of Hash#has_key?.
    Open

          if properties_xml_value.has_key?(prop_name)
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop (by default) checks for uses of methods Hash#haskey? and Hash#hasvalue? where it enforces Hash#key? and Hash#value? It is configurable to enforce the inverse, using verbose method names also.

    Example: EnforcedStyle: short (default)

    # bad Hash#haskey? Hash#hasvalue?

    # good Hash#key? Hash#value?

    Example: EnforcedStyle: verbose

    # bad Hash#key? Hash#value?

    # good Hash#haskey? Hash#hasvalue?

    Use Hash#key? instead of Hash#has_key?.
    Open

          if properties.has_key? prop_name
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop (by default) checks for uses of methods Hash#haskey? and Hash#hasvalue? where it enforces Hash#key? and Hash#value? It is configurable to enforce the inverse, using verbose method names also.

    Example: EnforcedStyle: short (default)

    # bad Hash#haskey? Hash#hasvalue?

    # good Hash#key? Hash#value?

    Example: EnforcedStyle: verbose

    # bad Hash#key? Hash#value?

    # good Hash#haskey? Hash#hasvalue?

    Line is too long. [83/80]
    Open

            property = instantiate_property(prop_name, properties_xml_value[prop_name])
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    private (on line 236) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    Open

        def self.process_properties(entity, xml_doc)
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for private or protected access modifiers which are applied to a singleton method. These access modifiers do not make singleton methods private/protected. private_class_method can be used for that.

    Example:

    # bad
    
    class C
      private
    
      def self.method
        puts 'hi'
      end
    end

    Example:

    # good
    
    class C
      def self.method
        puts 'hi'
      end
    
      private_class_method :method
    end

    Example:

    # good
    
    class C
      class << self
        private
    
        def method
          puts 'hi'
        end
      end
    end

    Unused block argument - details. If it's necessary, use _ or _details as an argument name to indicate that it won't be used.
    Open

            schema.navigation_properties[name].each do |nav_name, details|
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for unused block arguments.

    Example:

    # bad
    
    do_something do |used, unused|
      puts used
    end
    
    do_something do |bar|
      puts :foo
    end
    
    define_method(:foo) do |bar|
      puts :baz
    end

    Example:

    #good
    
    do_something do |used, _unused|
      puts used
    end
    
    do_something do
      puts :foo
    end
    
    define_method(:foo) do |_bar|
      puts :baz
    end

    Unused block argument - val. If it's necessary, use _ or _val as an argument name to indicate that it won't be used.
    Open

          metadata = json.select { |key, val| key =~ /@odata/ }
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for unused block arguments.

    Example:

    # bad
    
    do_something do |used, unused|
      puts used
    end
    
    do_something do |bar|
      puts :foo
    end
    
    define_method(:foo) do |bar|
      puts :baz
    end

    Example:

    #good
    
    do_something do |used, _unused|
      puts used
    end
    
    do_something do
      puts :foo
    end
    
    define_method(:foo) do |_bar|
      puts :baz
    end

    Use Hash#key? instead of Hash#has_key?.
    Open

          elsif navigation_properties.has_key? prop_name
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop (by default) checks for uses of methods Hash#haskey? and Hash#hasvalue? where it enforces Hash#key? and Hash#value? It is configurable to enforce the inverse, using verbose method names also.

    Example: EnforcedStyle: short (default)

    # bad Hash#haskey? Hash#hasvalue?

    # good Hash#key? Hash#value?

    Example: EnforcedStyle: verbose

    # bad Hash#key? Hash#value?

    # good Hash#haskey? Hash#hasvalue?

    Line is too long. [87/80]
    Open

              # Doing lazy loading here because instantiating each object takes a long time
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    private (on line 236) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    Open

        def self.process_metadata(entity, metadata)
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for private or protected access modifiers which are applied to a singleton method. These access modifiers do not make singleton methods private/protected. private_class_method can be used for that.

    Example:

    # bad
    
    class C
      private
    
      def self.method
        puts 'hi'
      end
    end

    Example:

    # good
    
    class C
      def self.method
        puts 'hi'
      end
    
      private_class_method :method
    end

    Example:

    # good
    
    class C
      class << self
        private
    
        def method
          puts 'hi'
        end
      end
    end

    Redundant RuntimeError argument can be removed.
    Open

            raise RuntimeError, "Unknown property type: #{prop_type}"
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for RuntimeError as the argument of raise/fail.

    It checks for code like this:

    Example:

    # Bad
    raise RuntimeError, 'message'
    
    # Bad
    raise RuntimeError.new('message')
    
    # Good
    raise 'message'

    Unused block argument - val. If it's necessary, use _ or _val as an argument name to indicate that it won't be used.
    Open

          json.delete_if { |key, val| key =~ /@odata/ }
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for unused block arguments.

    Example:

    # bad
    
    do_something do |used, unused|
      puts used
    end
    
    do_something do |bar|
      puts :foo
    end
    
    define_method(:foo) do |bar|
      puts :baz
    end

    Example:

    #good
    
    do_something do |used, _unused|
      puts used
    end
    
    do_something do
      puts :foo
    end
    
    define_method(:foo) do |_bar|
      puts :baz
    end

    Line is too long. [102/80]
    Open

                next unless node.attributes['type'].value =~ /^application\/atom\+xml;type=(feed|entry)$/i
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    Avoid comma after the last item of a hash.
    Open

          'xmlns:gml'       => 'http://www.opengis.net/gml',
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for trailing comma in array and hash literals.

    Example: EnforcedStyleForMultiline: consistent_comma

    # bad
    a = [1, 2,]
    
    # good
    a = [
      1, 2,
      3,
    ]
    
    # good
    a = [
      1,
      2,
    ]

    Example: EnforcedStyleForMultiline: comma

    # bad
    a = [1, 2,]
    
    # good
    a = [
      1,
      2,
    ]

    Example: EnforcedStyleForMultiline: no_comma (default)

    # bad
    a = [1, 2,]
    
    # good
    a = [
      1,
      2
    ]

    private (on line 236) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    Open

        def self.process_links(entity, xml_doc)
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop checks for private or protected access modifiers which are applied to a singleton method. These access modifiers do not make singleton methods private/protected. private_class_method can be used for that.

    Example:

    # bad
    
    class C
      private
    
      def self.method
        puts 'hi'
      end
    end

    Example:

    # good
    
    class C
      def self.method
        puts 'hi'
      end
    
      private_class_method :method
    end

    Example:

    # good
    
    class C
      class << self
        private
    
        def method
          puts 'hi'
        end
      end
    end

    Use %r around regular expression.
    Open

                next unless node.attributes['type'].value =~ /^application\/atom\+xml;type=(feed|entry)$/i
    Severity: Minor
    Found in lib/frodata/entity.rb by rubocop

    This cop enforces using // or %r around regular expressions.

    Example: EnforcedStyle: slashes (default)

    # bad
    snake_case = %r{^[\dA-Z_]+$}
    
    # bad
    regex = %r{
      foo
      (bar)
      (baz)
    }x
    
    # good
    snake_case = /^[\dA-Z_]+$/
    
    # good
    regex = /
      foo
      (bar)
      (baz)
    /x

    Example: EnforcedStyle: percent_r

    # bad
    snake_case = /^[\dA-Z_]+$/
    
    # bad
    regex = /
      foo
      (bar)
      (baz)
    /x
    
    # good
    snake_case = %r{^[\dA-Z_]+$}
    
    # good
    regex = %r{
      foo
      (bar)
      (baz)
    }x

    Example: EnforcedStyle: mixed

    # bad
    snake_case = %r{^[\dA-Z_]+$}
    
    # bad
    regex = /
      foo
      (bar)
      (baz)
    /x
    
    # good
    snake_case = /^[\dA-Z_]+$/
    
    # good
    regex = %r{
      foo
      (bar)
      (baz)
    }x

    Example: AllowInnerSlashes: false (default)

    # If `false`, the cop will always recommend using `%r` if one or more
    # slashes are found in the regexp string.
    
    # bad
    x =~ /home\//
    
    # good
    x =~ %r{home/}

    Example: AllowInnerSlashes: true

    # good
    x =~ /home\//

    There are no issues that match your filters.

    Category
    Status