Related articles

No items found.
The French newsletter for Ruby on Rails developers. Find similar content for free every month in your inbox!
Register
Share:
Blog
>

Get involved in Rails 6!

Once upon a time there was a Rails developer who wanted to become a Rails contributor. Deep down, he even wanted to become a member of the Rails core team! So one day, he decided to take the first step: he downloaded the Ruby on Rails source code!

So I downloaded the Rails source code:

$ git clone git@github.com:rails/rails.git
$ cd rails
$ ls
actioncable
actionmailbox
actionmailer
actionpack
actiontext
actionview
activejob
activemodel
activerecord
activestorage
activesupport
Brewfile
ci
CODE_OF_CONDUCT.md
CONTRIBUTING.md
Gemfile
Gemfile.lock
guides
MIT-LICENSE
package.json
rails.gemspec
RAILS_VERSION
railties
Rakefile
README.md
RELEASING_RAILS.md
tasks
tmp
tools
version.rb
yarn.lock

Damn... there's so much stuff here... I know most of the Rails components, but there are also a few new features. Luckily, Rails has several guides to help me fill in the gaps.

  • ActionCable is a WebSocket wrapper that allows Rails applications to communicate in real time with the server and clients. If you want your web page to receive notifications from your server without AJAX calls, this is what you need.
  • ActionMailbox allows your application to receive emails and process them in controllers.
  • ActionMailer allows you to send emails from your application.
  • ActionPack includes two main components: ActionDispatch and ActionController.
  • ActionDispatch is responsible for routing an incoming request to the appropriate controller/action for processing.
  • ActionController is responsible for processing the request and providing a response (MVC).
  • ActionText provides a rich text box for your forms (a text box where you can put stylish text, images, etc.)
  • ActionView is a set of tools (layouts, partials, form builders,..) to compile the controller response (MVC).
  • ActiveJob is an interface for scheduling asynchronous tasks.
  • ActiveModel provides help to help you structure your model classes (defining attributes, setting up validations and callbacks,...).
  • ActiveRecord is an ORM, meaning it's the layer that allows your controllers to talk to your database (s) (MVC).
  • ActiveStorage takes care of downloading files for you.
  • ActiveSupport makes Ruby programming even more enjoyable by adding lots of cool features.
  • Railties is the core of the Rails framework. It provides multiple hooks to extend Rails and/or change the initialization process. This allows the components mentioned above and any gems included in your Rails application to extend the Rails framework.
  • The other files are irrelevant to me at this point, I just need to get an idea of how the Rails source code is organized.

Ok, so I have an overview of the structure of the Rails repository. And now?

Well, my goal is to contribute to Rails. The simplest - but still useful - contribution that can be made to an open source project is a contribution to documentation. Let's start with that.

Rails, I need to clone and configure it to have an easy way to update it up front:

$ cd
$ mv rails rails_upstream
$ git clone git@github.com:<username>/rails.git rails_fork
$ cd rails_fork
$ git remote add upstream git@github.com:rails/rails.git
$ git fetch upstream

Now when I need to update my fork, I'm going to do the following:

$ git checkout master
$ git pull upstream master
$ git push

And when asked to rebase my branch on master, I do the following:

$ git checkout master
$ git pull upstream master
$ git push
$ git checkout <my-branch>
$ git rebase master <my-branch>
$ git push -f

Contribution to documentation

By reading the ActiveStorage source code (activestorage/lib/active_storage/service.rb), I noticed a call to ActiveSupport: :notifications.instrument. I didn't know what it was, so I did some research:

The instrumentation API provided by Active Support allows developers to provide hooks that other developers can latch on to. There are several of these as part of Rails. With this API, developers can choose to be notified when certain events occur in their application or in another piece of Ruby code.

It's cool. There are several hooks added by ActiveStorage, so maybe not all of them are mentioned in the Active Support Instrumentation guide. I guessed right, three hooks are missing:

  • service_download_chunk.active_storage
  • service_update_metadata.active_storage
  • preview.active_storage

I think I've found my first Rails:D

$ git checkout -b add-activestorage-instrumentation-hooks-to-guide
$ # apply wanted modifications to guides/source/active_support_instrumentation.md
$ git add guides/source/active_support_instrumentation.md
$ git commit
$ git push -u origin add-activestorage-instrumentation-hooks-to-guide

Important: since this commit only changes the documentation, it is important to add [ci skip] to the commit message so that the CI is not overloaded unnecessarily. Now that my branch is pushed, I need to go to https://github.com/rails/railsand open a new pull request.Pull Request:https://github.com/rails/rails/pull/36010

commit 78260d5663702f153f6bae64073f9659de366946
Author: Younes SERRAJ <younes.serraj@gmail.com>
Date:   Wed Apr 17 19:25:46 2019 +0200

    Mention more ActiveStorage hooks in Active Support Instrumentation guide [ci skip]

    Hooks added:
    - `service_download_chunk.active_storage`
    - `service_update_metadata.active_storage`
    - `preview.active_storage`

diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index e5ed283c45..4868b00bbe 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -545,6 +545,14 @@ Active Storage
 | `:key`       | Secure token        |
 | `:service`   | Name of the service |

+### service_download_chunk.active_storage
+
+| Key          | Value                           |
+| ------------ | ------------------------------- |
+| `:key`       | Secure token                    |
+| `:service`   | Name of the service             |
+| `:range`     | Byte range attempted to be read |
+
 ### service_download.active_storage

 | Key          | Value               |
@@ -582,6 +590,23 @@ Active Storage
 | `:service`   | Name of the service |
 | `:url`       | Generated URL       |

+### service_update_metadata.active_storage
+
+| Key             | Value                          |
+| --------------- | ------------------------------ |
+| `:key`          | Secure token                   |
+| `:service`      | Name of the service            |
+| `:content_type` | HTTP Content-Type field        |
+| `:disposition`  | HTTP Content-Disposition field |
+
+INFO. The only ActiveStorage service that provides this hook so far is GCS.
+
+### preview.active_storage
+
+| Key          | Value               |
+| ------------ | ------------------- |
+| `:key`       | Secure token        |
+
 Railties
 --------

Now there is one very difficult thing to do: wait. Wait for a member of the central team to review the withdrawal request and comment or merge it. Wait without reloading the Github page every 5 seconds. Just move on and wait for an email notification: the request has been merged.

Contributing to a Rails component

I've started with ActiveStorage, I'll stick with it for now. I don't have any features to add to it, so from time to time I check the issues on Github for inspiration. The bug I found, related to ActiveStorage and fairly easy to fix, is the following: https://github.com/rails/rails/issues/35953

Great! Now I have my next contribution and this time it's the code. Code goes hand in hand with testing, so I need to prepare my development environment to run the Rails test suite. Scary, but nothing impossible:)

https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#setting-up-a-development-environment

There are mainly two ways to do this: you can either install all the dependencies, or run everything in a virtual machine. Personally, I'm going to do both for the sake of learning, but I'll only mention the easiest method in this blog, that of the virtual machine. I followed this guide first: https://github.com/rails/rails-dev-box

After installing VirtualBox and Vagrant on my Debian 9.8, I ran the following commands:

$ # in the host:
$ cd
$ git clone https://github.com/rails/rails-dev-box.git
$ cd rails-dev-box
$ cp -r ~/rails_fork ./rails
$ vagrant up
$ vagrant ssh
$ # once in the virtual machine:
$ cd /vagrant/rails
$ bundle

Notice that I copied my phonebook Rails_Fork inside the directory rails-dev-box in order to be able to connect via ssh to the virtual machine and access the source code I am working on (to run the tests) .Ok, now that I have my development environment ready to work, I have to run the tests first. I want to make sure that the tests run successfully before changing the ActiveStorage source code (so if they fail, I'll know it's because of my code changes and not a configuration error).

$ # in the virtual machine:
$ cd /vagrant/rails
$ bundle exec rake

And again: wait. Just... wait... for... it... to work.

Done. Yes, it's green! Note: as advised in the documentation, I will edit the code in the host and run the tests in the virtual machine. This way, I don't install any software on the virtual machine and I avoid accidental changes to package versions and the like.

$ git checkout -b active-storage-bmp-variants-support

Now I can add the following changes:

  • modify activestorage/lib/active_storage/engine.rb to fix the problem (here, I'm whitelisting a mime type so ActiveStorage knows it can create BMP variants)
  • modify activestorage/test/models/variant_test.rb to test that ActiveStorage actually succeeds in creating a BMP variant
  • add activestorage/test/fixtures/files/colors.bmp that will be used by the test above
  • modify ActiveStorage/ChangeLog.md to let Rails developers know about the changes introduced by my commit.

It was not very difficult to write this patch. The only part that gave me a bit of a run for my money was testing, as I'm used to RSpec, not Minitest. I read the existing tests to find out how to write my own, then I googled how to test a single file. In my case, I executed:

$ cd /vagrant/rails/activestorage
$ bundle exec ruby -Itest ./test/models/variant_test.rb`

green I like that. I can now commit and push to Github:

$ cd /vagrant/rails
$ git add ./activestorage
$ git commit
$ git push -u origin active-storage-bmp-variants-support

Pull request:https://github.com/rails/rails/pull/36051

commit bcf370d689673031073ba2ac5588afe41cc315c9
Author: Younes SERRAJ <younes.serraj@gmail.com>
Date:   Sun Apr 21 19:07:22 2019 +0200

    Allow ActiveStorage to generate variants of BMP images

diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md
index 54fc949172..d524ecf7d6 100644
--- a/activestorage/CHANGELOG.md
+++ b/activestorage/CHANGELOG.md
@@ -1,3 +1,7 @@
+*   Permit generating variants of BMP images.
+
+    *Younes Serraj*
+
 ## Rails 6.0.0.beta3 (March 11, 2019) ##

 *   No changes.
diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb
index fc75a8f816..cbb205627e 100644
--- a/activestorage/lib/active_storage/engine.rb
+++ b/activestorage/lib/active_storage/engine.rb
@@ -33,6 +33,7 @@ class Engine < Rails::Engine # :nodoc:
       image/jpeg
       image/pjpeg
       image/tiff
+      image/bmp
       image/vnd.adobe.photoshop
       image/vnd.microsoft.icon
     )
@@ -56,6 +57,7 @@ class Engine < Rails::Engine # :nodoc:
       image/jpg
       image/jpeg
       image/tiff
+      image/bmp
       image/vnd.adobe.photoshop
       image/vnd.microsoft.icon
       application/pdf
diff --git a/activestorage/test/fixtures/files/colors.bmp b/activestorage/test/fixtures/files/colors.bmp
new file mode 100644
index 0000000000..3cc1e8764d
Binary files /dev/null and b/activestorage/test/fixtures/files/colors.bmp differ
diff --git a/activestorage/test/models/variant_test.rb b/activestorage/test/models/variant_test.rb
index d98935eb9f..92e3384042 100644
--- a/activestorage/test/models/variant_test.rb
+++ b/activestorage/test/models/variant_test.rb
@@ -144,6 +144,17 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
     assert_equal 33, image.height
   end

+  test "resized variation of BMP blob" do
+    blob = create_file_blob(filename: "colors.bmp")
+    variant = blob.variant(resize: "15x15").processed
+    assert_match(/colors\.bmp/, variant.service_url)
+
+    image = read_image(variant)
+    assert_equal "BMP", image.type
+    assert_equal 15, image.width
+    assert_equal 8, image.height
+  end
+
   test "optimized variation of GIF blob" do
     blob = create_file_blob(filename: "image.gif", content_type: "image/gif")

Note: Sometimes you have multiple commits in your change request. You may be asked to overwrite them to help keep the history as clean as possible. If we ask you, git rebase -i and Git commit --Amend are your friends. So I opened a pull request and... I waited. Yes, there is a lot of expectation in open source contributions. Keep in mind that core contributors have their paid work to take care of, their personal lives, and a lot of problems to read, and a lot of pull requests to review, and their own pull requests to work on, and mailing lists to keep up to date, etc. Yes, that takes time. Yes, we love them for the awesome work they do. Yes, when we start contributing it's frustrating to wait and we're almost banned from Github for refreshing our post request page too often, but that's okay. We're contributing to Rails and it's a great feeling because we can help other developers, we're learning more about Rails, and we're even more appreciative of the work that all of these contributors have done before us.

Closing note

First of all, a big thank you to @eileencodes ❤ for his conference at the RailsConf 2015 Breaking Down the Barrier: Demystifying Contributing to Rails: https://www.youtube.com/watch?v=7zoD6NZy6vY Guys, if you've been playing with Rails for two or three years, you can probably contribute. My advice is this: read the issues on Github, test them to confirm that they are reproducible or ask for more details if needed, read the pull requests, when you find something new for yourself, don't just read the tutorials and documentation but also go read the source code. It doesn't matter if you don't understand everything that's going on, at least you're accumulating knowledge and slowly building an intuitive understanding of how Rails works. Before you know it, you'll be so familiar with the system that contributing to Ruby on Rails will be a breeze.

Peace and love my friends.