Implement a simple blockchain in Ruby, including basic mining functionality and transaction validation.
Here's a simple implementation of a blockchain in Ruby, including basic mining functionality and transaction validation:

```ruby
require 'digest'

class Block
  attr_reader :index, :timestamp, :data, :previous_hash, :hash

  def initialize(index, data, previous_hash)
    @index = index
    @timestamp = Time.now.to_i
    @data = data
    @previous_hash = previous_hash
    @hash = calculate_hash
  end

  def calculate_hash
    Digest::SHA256.hexdigest("#{@index}#{@timestamp}#{@data}#{@previous_hash}")
  end
end

class Blockchain
  attr_reader :chain

  def initialize
    @chain = [create_genesis_block]
  end

  def create_genesis_block
    Block.new(0, "Genesis Block", "0")
  end

  def add_block(data)
    new_block = Block.new(@chain.length, data, @chain[-1].hash)
    @chain.push(new_block)
  end

  def is_valid?
    for i in 1...@chain.length
      current_block = @chain[i]
      previous_block = @chain[i - 1]

      return false if current_block.hash != current_block.calculate_hash
      return false if current_block.previous_hash != previous_block.hash
    end

    true
  end
end

# Test the blockchain
blockchain = Blockchain.new
blockchain.add_block("Transaction Data 1")
blockchain.add_block("Transaction Data 2")

puts "Blockchain valid? #{blockchain.is_valid?}"

puts "Tampering with data..."
blockchain.chain[1].instance_variable_set(:@data, "Tampered Data")

puts "Blockchain valid? #{blockchain.is_valid?}"
```

This code defines two classes: `Block` and `Blockchain`. The `Block` class represents a single block in the blockchain, and the `Blockchain` class represents the entire chain.

The `Block` class has methods for calculating its hash based on its data. The `Blockchain` class initializes with a genesis block and has methods for adding new blocks to the chain and validating the integrity of the chain.

To test the blockchain, we create a new instance of the `Blockchain` class, add some blocks, and then check if the chain is valid. We also tamper with the data in one of the blocks and re-validate the chain to demonstrate how the validation process works.