How to read Crystal documentation?

Today, I wanted to generate a SHA256 hash of a string. Based on the documentation here and the stackoverflow post here I figured out the following working code:

require "openssl"

enc = OpenSSL::Digest.new("sha256")
res = enc.update("helloworld")
puts res

However, where does it say in the documentation that the name of the algorithm for this purpose should be “sha256”? How can I find the acceptable arguments to OpenSSL::Digest.new().

Another one was when setting permissions for creating directories. I tried and failed to generate correct permissions using:

Dir.mkdir_p(destdir, mode = 774)

Here it says that Dir.mkdir_p(destdir, mode = 511) creates a new directory at the given path, including any non-existing intermediate directories. The linux-style permission mode can be specified, with a default of 777 (0o777). I believe this needs to be fixed (that is, the default is 511). But why does it not say that the mode has to specified in the octal format. When I tried 0o774, things worked.

In general, what is the recommended way of finding set of possible arguments and/or their type.

Thank you. BTW Crystal and Kemal combination is really awesome. I hope this language really takes off.

2 Likes

What you are finding is just lack of documentation. Many things were added to the standard library without proper documentation. We are always thankful if people send PRs with more documentation on things that are missing.

As for mode = 511, that’s a bug in the doc generator: the actual value is 0o777 but the doc generator, for some reason, converts that to it’s base 10 value, which is 511. There’s no need for the value to be octal, but it’s usual to write it in octal.

1 Like

Thank you @asterite. Unfortunately, I only work on either personal projects, or projects of 2-3 people. So not too familiar with how PRs work in a big project like Crystal. But would love to contribute to the documentation when I come across things such as these that can be clarified or improved upon. Are there any quick guides on how the PRs work for a such large projects?

https://github.com/crystal-lang/crystal/blob/master/CONTRIBUTING.md Would be a good place to start.

The instructions above are good, but if it’s just API documentation then it’s just like sending a PR to a project of any size. Be sure to run crystal tool format on the files you change (though this can be done later).

Thanks @Blacksmoke16 and @asterite. Will look into this.

This is the perfect opportunity @curious2learn to submit a PR for the docs. So the next person who stumbles upon that doc page will see the code and save time. Most importantly, you get to contribute to something special!

Okay. So I cloned the Crystal repository, created a new branch and added the above simple example in the file openssl/digest/digest.cr. This is the code I added.

# # Generate SHA256 hash of a string
# 
# ```
# enc = OpenSSL::Digest.new("sha256")
# enc.update("helloworld")             # => 1a16eef5663e63cf4e88692c9c24dba001c5693e2ae92e944215d041456440b8
# ```

I find such small examples in the API docs very helpful. Before I create a pull request, I want to see how this looks in the generated documentation (to make sure that I have not screwed it up). How do I generate docs locally to check this out?

Regarding the file permissions, I suppose there is no way to correct that because of the error in the doc generator that @asterite has pointed out.

1 Like

I’d also include the require "openssl", having copy pastable examples is :100:.

Should just be able to run make docs.

Definitely. Will include that line.

I typed make docs in the root crystal folder, but got the following error:

Makefile:62: *** Could not locate llvm-config, make sure it is installed and in your PATH, or set LLVM_CONFIG.  Stop.

Here I found the suggestion that I should run brew link llvm --force. Is that correct?

Not sure, can give it a try I guess?

I installed LLVM and then ran make docs as suggested by @Blacksmoke16.
I got the following response:

Using /usr/local/opt/llvm/bin/llvm-config [version=8.0.0]
./bin/crystal docs -b https://crystal-lang.org/api/latest src/docs_main.cr

Then I opened crystal/docs/OpenSSL/Digest.html, but it does not reflect the changes I made. Can anyone help me with how I can see these changes?

Thanks.

Where exactly did you add the comment block in the file?

The following. I am going to add the line you suggested. But this is what I have in the
src/openssl/digest/digest.cr. I added these lines after the require lines but before the module OpenSSL. Do I need to add these after the module declaration?

Edit: I tried adding after the module declaration, but that did not help either.

# # Generate SHA256 hash of a string
# 
# ```
# enc = OpenSSL::Digest.new("sha256")
# enc.update("helloworld")             # => 1a16eef5663e63cf4e88692c9c24dba001c5693e2ae92e944215d041456440b8
# ```

You’re adding the docs to the OpenSSL module. So it would show up /crystal/docs/OpenSSL.html. You probably want to add it to the update method within the Digest class. Like:

    # Generate SHA256 hash of *data*.
    #
    # ```
    # require "openssl"
    #
    # OpenSSL::Digest.new("sha256").update("helloworld") # => 1a16eef5663e63cf4e88692c9c24dba001c5693e2ae92e944215d041456440b8
    # ```
    def update(data : String | Slice)

Also, @asterite do you know if there is any reason this class takes a string and not an OpenSSL::Algorithm? Would make more sense as you wouldn’t have to validate the string like it’s currently doing since all the valid ones would be in the enum?

@Blacksmoke16 , sorry but it does not show up in /crystal/docs/OpenSSL.html either :(

Just to be clear, by crystal/docs/OpenSSL.html, im talking about the docs directory in your crystal folder. I.e. where you run make docs from. You can open the docs/index.html in your browser to see a local version of the docs generated from your code.

Your change are of course not going to be visible on any other live version of the docs.

Could also try deleting the ./docs directory, then rerun make docs, just to see if that helps.

I understood that you were asking me to look at the local version of the docs generated. That is what I am/was looking at.

As you suggested I also tried deleting the docs directory in the local crystal folder. Running make docs generated that directory as expected, but the new version does not contain the example either. Is there any way I can send the src/openssl/digest/digest.cr file that I modified, so that you can take a look at the lines where I added the example. Maybe something is wrong with my setup.

Just push up your changes and I could look at your branch on your fork.

Thanks for your patience and sorry for so many questions.

I have created a new branch, but I have not forked the crystal repo. I just cloned it. Can I just push to the one I cloned from, or do I need to create a fork? git remote -v shows this for push

origin	https://github.com/crystal-lang/crystal.git (push)

If I can just push to this one, do I first merge my changes in master before pushing or should I just try to push the branch that I have created (if that is even possible)?

Thanks!