arel 7.1.4 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.txt +10 -18
- data/README.md +14 -3
- data/lib/arel/alias_predication.rb +1 -0
- data/lib/arel/attributes/attribute.rb +1 -0
- data/lib/arel/attributes.rb +1 -0
- data/lib/arel/collectors/bind.rb +6 -18
- data/lib/arel/collectors/composite.rb +32 -0
- data/lib/arel/collectors/plain_string.rb +2 -1
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/compatibility/wheres.rb +1 -0
- data/lib/arel/crud.rb +1 -0
- data/lib/arel/delete_manager.rb +1 -0
- data/lib/arel/errors.rb +8 -0
- data/lib/arel/expressions.rb +1 -0
- data/lib/arel/factory_methods.rb +1 -0
- data/lib/arel/insert_manager.rb +6 -0
- data/lib/arel/math.rb +1 -0
- data/lib/arel/nodes/and.rb +1 -0
- data/lib/arel/nodes/ascending.rb +1 -0
- data/lib/arel/nodes/binary.rb +1 -0
- data/lib/arel/nodes/bind_param.rb +20 -2
- data/lib/arel/nodes/case.rb +1 -0
- data/lib/arel/nodes/casted.rb +2 -1
- data/lib/arel/nodes/count.rb +3 -0
- data/lib/arel/nodes/delete_statement.rb +1 -0
- data/lib/arel/nodes/descending.rb +1 -0
- data/lib/arel/nodes/equality.rb +1 -0
- data/lib/arel/nodes/extract.rb +1 -0
- data/lib/arel/nodes/false.rb +2 -0
- data/lib/arel/nodes/full_outer_join.rb +1 -0
- data/lib/arel/nodes/function.rb +3 -0
- data/lib/arel/nodes/grouping.rb +1 -0
- data/lib/arel/nodes/in.rb +1 -0
- data/lib/arel/nodes/infix_operation.rb +1 -0
- data/lib/arel/nodes/inner_join.rb +1 -0
- data/lib/arel/nodes/insert_statement.rb +1 -0
- data/lib/arel/nodes/join_source.rb +1 -0
- data/lib/arel/nodes/matches.rb +1 -0
- data/lib/arel/nodes/named_function.rb +1 -0
- data/lib/arel/nodes/node.rb +1 -0
- data/lib/arel/nodes/outer_join.rb +1 -0
- data/lib/arel/nodes/over.rb +1 -0
- data/lib/arel/nodes/regexp.rb +1 -0
- data/lib/arel/nodes/right_outer_join.rb +1 -0
- data/lib/arel/nodes/select_core.rb +1 -0
- data/lib/arel/nodes/select_statement.rb +1 -0
- data/lib/arel/nodes/sql_literal.rb +1 -0
- data/lib/arel/nodes/string_join.rb +1 -0
- data/lib/arel/nodes/table_alias.rb +1 -0
- data/lib/arel/nodes/terminal.rb +2 -0
- data/lib/arel/nodes/true.rb +2 -0
- data/lib/arel/nodes/unary.rb +1 -0
- data/lib/arel/nodes/unary_operation.rb +1 -0
- data/lib/arel/nodes/unqualified_column.rb +1 -0
- data/lib/arel/nodes/update_statement.rb +1 -0
- data/lib/arel/nodes/values.rb +1 -0
- data/lib/arel/nodes/values_list.rb +23 -0
- data/lib/arel/nodes/window.rb +2 -0
- data/lib/arel/nodes/with.rb +1 -0
- data/lib/arel/nodes.rb +2 -0
- data/lib/arel/order_predications.rb +1 -0
- data/lib/arel/predications.rb +1 -0
- data/lib/arel/select_manager.rb +2 -1
- data/lib/arel/table.rb +2 -13
- data/lib/arel/tree_manager.rb +3 -5
- data/lib/arel/update_manager.rb +1 -0
- data/lib/arel/visitors/depth_first.rb +1 -0
- data/lib/arel/visitors/dot.rb +2 -1
- data/lib/arel/visitors/ibm_db.rb +1 -0
- data/lib/arel/visitors/informix.rb +1 -2
- data/lib/arel/visitors/mssql.rb +1 -0
- data/lib/arel/visitors/mysql.rb +1 -0
- data/lib/arel/visitors/oracle.rb +7 -6
- data/lib/arel/visitors/oracle12.rb +2 -1
- data/lib/arel/visitors/postgresql.rb +2 -1
- data/lib/arel/visitors/reduce.rb +4 -2
- data/lib/arel/visitors/sqlite.rb +1 -0
- data/lib/arel/visitors/to_sql.rb +34 -49
- data/lib/arel/visitors/visitor.rb +4 -2
- data/lib/arel/visitors/where_sql.rb +1 -0
- data/lib/arel/visitors.rb +1 -0
- data/lib/arel/window_predications.rb +1 -0
- data/lib/arel.rb +4 -1
- metadata +22 -6
- data/lib/arel/visitors/bind_substitute.rb +0 -9
- data/lib/arel/visitors/bind_visitor.rb +0 -39
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: dc3719172683caa3fb2bd15ce6ef3ed477a8b2ef
         | 
| 4 | 
            +
              data.tar.gz: 74b4f1d7d44871db56c62907ed1c4ba51040bf6e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bedb8b1701ee99fca067c4a52f92d096648d25d67d4809408ede3eeb40298b3fc83a9fdccf1f4195c32f871ee430eba29f11dedd19b12032639a8b03bc7ec54c
         | 
| 7 | 
            +
              data.tar.gz: 97a3b3155db8b0c57ca4616598d45d8aad7592c56a6882e0e7f5369eeac221802cae5cd60b4d72a92d755eb13be4b39aedc9ea967e1c6faac28953a3414d1f39
         | 
    
        data/History.txt
    CHANGED
    
    | @@ -1,29 +1,21 @@ | |
| 1 | 
            -
            ===  | 
| 1 | 
            +
            === 9.0.0 / 2017-11-14
         | 
| 2 2 |  | 
| 3 | 
            -
            *  | 
| 4 | 
            -
             | 
| 5 | 
            -
              *  | 
| 6 | 
            -
             | 
| 7 | 
            -
            === 7.1.3 / 2016-10-07
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            * bug fixes
         | 
| 10 | 
            -
             | 
| 11 | 
            -
              * Remove union mapping as :binary node when performing DepthFirst enumeration
         | 
| 12 | 
            -
              * Fix invalid BindParam output in Dot visitor
         | 
| 13 | 
            -
              * Add Arel::Nodes::Casted to dot visitor
         | 
| 14 | 
            -
              * Use Arel::Nodes::BindParam in Oracle visitor for queries using both LIMIT and OFFSET
         | 
| 3 | 
            +
            * Enhancements
         | 
| 4 | 
            +
              * `InsertManager#insert` is now chainable
         | 
| 5 | 
            +
              * Support multiple inserts
         | 
| 15 6 |  | 
| 16 | 
            -
            ===  | 
| 7 | 
            +
            === 8.0.0 / 2017-02-21
         | 
| 17 8 |  | 
| 18 | 
            -
            *  | 
| 9 | 
            +
            * Enhancements
         | 
| 19 10 |  | 
| 20 | 
            -
              *  | 
| 11 | 
            +
              * Remove deprecated type casting support in Arel
         | 
| 12 | 
            +
              * Frozen all string literals in Arel
         | 
| 21 13 |  | 
| 22 14 | 
             
            === 7.1.1 / 2016-07-27
         | 
| 23 15 |  | 
| 24 | 
            -
            *  | 
| 16 | 
            +
            * Bug Fixes
         | 
| 25 17 |  | 
| 26 | 
            -
              *  | 
| 18 | 
            +
              * Fix warning in `Casted#hash`
         | 
| 27 19 |  | 
| 28 20 | 
             
            === 7.1.0 / 2016-07-19
         | 
| 29 21 |  | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            # Arel
         | 
| 2 2 |  | 
| 3 3 | 
             
            * http://github.com/rails/arel
         | 
| 4 | 
            +
            * [API Documentation](http://www.rubydoc.info/github/rails/arel)
         | 
| 4 5 |  | 
| 5 6 | 
             
            ## DESCRIPTION
         | 
| 6 7 |  | 
| @@ -97,7 +98,7 @@ users.where((users[:bitmap] >> 1).gt(0)).project(Arel.sql('*')) | |
| 97 98 | 
             
            # => SELECT * FROM "users"  WHERE ("users"."bitmap" >> 1) > 0
         | 
| 98 99 |  | 
| 99 100 | 
             
            users.where((~ users[:bitmap]).gt(0)).project(Arel.sql('*'))
         | 
| 100 | 
            -
            # => SELECT FROM "users" WHERE  ~ "users"."bitmap" > 0
         | 
| 101 | 
            +
            # => SELECT * FROM "users" WHERE  ~ "users"."bitmap" > 0
         | 
| 101 102 | 
             
            ```
         | 
| 102 103 |  | 
| 103 104 | 
             
            Joins resemble SQL strongly:
         | 
| @@ -149,7 +150,14 @@ The `OR` operator works like this: | |
| 149 150 | 
             
            users.where(users[:name].eq('bob').or(users[:age].lt(25)))
         | 
| 150 151 | 
             
            ```
         | 
| 151 152 |  | 
| 152 | 
            -
            The `AND` operator behaves similarly.
         | 
| 153 | 
            +
            The `AND` operator behaves similarly. Here is an example of the `DISTINCT` operator:
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            ```ruby
         | 
| 156 | 
            +
            posts = Arel::Table.new(:posts)
         | 
| 157 | 
            +
            posts.project(posts[:title])
         | 
| 158 | 
            +
            posts.distinct
         | 
| 159 | 
            +
            posts.to_sql # => 'SELECT DISTINCT "posts"."title" FROM "posts"'
         | 
| 160 | 
            +
            ```
         | 
| 153 161 |  | 
| 154 162 | 
             
            Aggregate functions `AVG`, `SUM`, `COUNT`, `MIN`, `MAX`, `HAVING`:
         | 
| 155 163 |  | 
| @@ -180,7 +188,7 @@ users.project(users[:age].average.as("mean_age")) | |
| 180 188 | 
             
            # => SELECT AVG(users.age) AS mean_age FROM users
         | 
| 181 189 | 
             
            ```
         | 
| 182 190 |  | 
| 183 | 
            -
            ### The  | 
| 191 | 
            +
            ### The Advanced Features
         | 
| 184 192 |  | 
| 185 193 | 
             
            The examples above are fairly simple and other libraries match or come close to matching the expressiveness of Arel (e.g. `Sequel` in Ruby).
         | 
| 186 194 |  | 
| @@ -207,6 +215,7 @@ products. | |
| 207 215 |  | 
| 208 216 | 
             
            #### Complex Joins
         | 
| 209 217 |  | 
| 218 | 
            +
            ##### Alias
         | 
| 210 219 | 
             
            Where Arel really shines is in its ability to handle complex joins and aggregations. As a first example, let's consider an "adjacency list", a tree represented in a table. Suppose we have a table `comments`, representing a threaded discussion:
         | 
| 211 220 |  | 
| 212 221 | 
             
            ```ruby
         | 
| @@ -232,6 +241,7 @@ comments_with_replies = \ | |
| 232 241 |  | 
| 233 242 | 
             
            This will return the reply for the first comment.
         | 
| 234 243 |  | 
| 244 | 
            +
            ##### CTE
         | 
| 235 245 | 
             
            [Common Table Expressions (CTE)](https://en.wikipedia.org/wiki/Common_table_expressions#Common_table_expression) support via:
         | 
| 236 246 |  | 
| 237 247 | 
             
            Create a `CTE`
         | 
| @@ -254,6 +264,7 @@ users. | |
| 254 264 | 
             
            #    FROM users INNER JOIN cte_table ON users.id = cte_table.user_id
         | 
| 255 265 | 
             
            ```
         | 
| 256 266 |  | 
| 267 | 
            +
            #### Write SQL strings
         | 
| 257 268 | 
             
            When your query is too complex for `Arel`, you can use `Arel::SqlLiteral`:
         | 
| 258 269 |  | 
| 259 270 | 
             
            ```ruby
         | 
    
        data/lib/arel/attributes.rb
    CHANGED
    
    
    
        data/lib/arel/collectors/bind.rb
    CHANGED
    
    | @@ -1,35 +1,23 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module Arel
         | 
| 2 4 | 
             
              module Collectors
         | 
| 3 5 | 
             
                class Bind
         | 
| 4 6 | 
             
                  def initialize
         | 
| 5 | 
            -
                    @ | 
| 7 | 
            +
                    @binds = []
         | 
| 6 8 | 
             
                  end
         | 
| 7 9 |  | 
| 8 10 | 
             
                  def << str
         | 
| 9 | 
            -
                    @parts << str
         | 
| 10 11 | 
             
                    self
         | 
| 11 12 | 
             
                  end
         | 
| 12 13 |  | 
| 13 14 | 
             
                  def add_bind bind
         | 
| 14 | 
            -
                    @ | 
| 15 | 
            +
                    @binds << bind
         | 
| 15 16 | 
             
                    self
         | 
| 16 17 | 
             
                  end
         | 
| 17 18 |  | 
| 18 | 
            -
                  def value | 
| 19 | 
            -
             | 
| 20 | 
            -
                  def substitute_binds bvs
         | 
| 21 | 
            -
                    bvs = bvs.dup
         | 
| 22 | 
            -
                    @parts.map do |val|
         | 
| 23 | 
            -
                      if Arel::Nodes::BindParam === val
         | 
| 24 | 
            -
                        bvs.shift
         | 
| 25 | 
            -
                      else
         | 
| 26 | 
            -
                        val
         | 
| 27 | 
            -
                      end
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                  def compile bvs
         | 
| 32 | 
            -
                    substitute_binds(bvs).join
         | 
| 19 | 
            +
                  def value
         | 
| 20 | 
            +
                    @binds
         | 
| 33 21 | 
             
                  end
         | 
| 34 22 | 
             
                end
         | 
| 35 23 | 
             
              end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Arel
         | 
| 4 | 
            +
              module Collectors
         | 
| 5 | 
            +
                class Composite
         | 
| 6 | 
            +
                  def initialize(left, right)
         | 
| 7 | 
            +
                    @left = left
         | 
| 8 | 
            +
                    @right = right
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def << str
         | 
| 12 | 
            +
                    left << str
         | 
| 13 | 
            +
                    right << str
         | 
| 14 | 
            +
                    self
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def add_bind bind, &block
         | 
| 18 | 
            +
                    left.add_bind bind, &block
         | 
| 19 | 
            +
                    right.add_bind bind, &block
         | 
| 20 | 
            +
                    self
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def value
         | 
| 24 | 
            +
                    [left.value, right.value]
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  protected
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  attr_reader :left, :right
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Arel
         | 
| 3 | 
            +
              module Collectors
         | 
| 4 | 
            +
                class SubstituteBinds
         | 
| 5 | 
            +
                  def initialize(quoter, delegate_collector)
         | 
| 6 | 
            +
                    @quoter = quoter
         | 
| 7 | 
            +
                    @delegate = delegate_collector
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def << str
         | 
| 11 | 
            +
                    delegate << str
         | 
| 12 | 
            +
                    self
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def add_bind bind
         | 
| 16 | 
            +
                    self << quoter.quote(bind)
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def value
         | 
| 20 | 
            +
                    delegate.value
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  protected
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  attr_reader :quoter, :delegate
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
    
        data/lib/arel/crud.rb
    CHANGED
    
    
    
        data/lib/arel/delete_manager.rb
    CHANGED
    
    
    
        data/lib/arel/errors.rb
    ADDED
    
    
    
        data/lib/arel/expressions.rb
    CHANGED
    
    
    
        data/lib/arel/factory_methods.rb
    CHANGED
    
    
    
        data/lib/arel/insert_manager.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 1 2 | 
             
            module Arel
         | 
| 2 3 | 
             
              class InsertManager < Arel::TreeManager
         | 
| 3 4 | 
             
                def initialize
         | 
| @@ -33,10 +34,15 @@ module Arel | |
| 33 34 | 
             
                    end
         | 
| 34 35 | 
             
                    @ast.values = create_values values, @ast.columns
         | 
| 35 36 | 
             
                  end
         | 
| 37 | 
            +
                  self
         | 
| 36 38 | 
             
                end
         | 
| 37 39 |  | 
| 38 40 | 
             
                def create_values values, columns
         | 
| 39 41 | 
             
                  Nodes::Values.new values, columns
         | 
| 40 42 | 
             
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def create_values_list(rows)
         | 
| 45 | 
            +
                  Nodes::ValuesList.new(rows)
         | 
| 46 | 
            +
                end
         | 
| 41 47 | 
             
              end
         | 
| 42 48 | 
             
            end
         | 
    
        data/lib/arel/math.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/and.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/ascending.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/binary.rb
    CHANGED
    
    
| @@ -1,8 +1,26 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 1 2 | 
             
            module Arel
         | 
| 2 3 | 
             
              module Nodes
         | 
| 3 4 | 
             
                class BindParam < Node
         | 
| 4 | 
            -
                   | 
| 5 | 
            -
             | 
| 5 | 
            +
                  attr_accessor :value
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(value)
         | 
| 8 | 
            +
                    @value = value
         | 
| 9 | 
            +
                    super()
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def hash
         | 
| 13 | 
            +
                    [self.class, self.value].hash
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def eql?(other)
         | 
| 17 | 
            +
                    other.is_a?(BindParam) &&
         | 
| 18 | 
            +
                      value == other.value
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  alias :== :eql?
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def nil?
         | 
| 23 | 
            +
                    value.nil?
         | 
| 6 24 | 
             
                  end
         | 
| 7 25 | 
             
                end
         | 
| 8 26 | 
             
              end
         | 
    
        data/lib/arel/nodes/case.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/casted.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 1 2 | 
             
            module Arel
         | 
| 2 3 | 
             
              module Nodes
         | 
| 3 4 | 
             
                class Casted < Arel::Nodes::Node # :nodoc:
         | 
| @@ -29,7 +30,7 @@ module Arel | |
| 29 30 |  | 
| 30 31 | 
             
                def self.build_quoted other, attribute = nil
         | 
| 31 32 | 
             
                  case other
         | 
| 32 | 
            -
                    when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Table, Arel::Nodes::BindParam, Arel::SelectManager, Arel::Nodes::Quoted
         | 
| 33 | 
            +
                    when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Table, Arel::Nodes::BindParam, Arel::SelectManager, Arel::Nodes::Quoted, Arel::Nodes::SqlLiteral
         | 
| 33 34 | 
             
                      other
         | 
| 34 35 | 
             
                    else
         | 
| 35 36 | 
             
                      case attribute
         | 
    
        data/lib/arel/nodes/count.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/equality.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/extract.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/false.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/function.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/grouping.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/in.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/matches.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/node.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/over.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/regexp.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/terminal.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/true.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/unary.rb
    CHANGED
    
    
    
        data/lib/arel/nodes/values.rb
    CHANGED
    
    
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Arel
         | 
| 3 | 
            +
              module Nodes
         | 
| 4 | 
            +
                class ValuesList < Node
         | 
| 5 | 
            +
                  attr_reader :rows
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(rows)
         | 
| 8 | 
            +
                    @rows = rows
         | 
| 9 | 
            +
                    super()
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def hash
         | 
| 13 | 
            +
                    @rows.hash
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def eql? other
         | 
| 17 | 
            +
                    self.class == other.class &&
         | 
| 18 | 
            +
                      self.rows == other.rows
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  alias :== :eql?
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         |