Today I Learned Notes to self about software development

    Naming DB indexes

    Rails 7 apps have a limit on autogenerated index names of 63 characters.

    ArgumentError: Index name
    'index_codeblock_submission_on_user_id_and_lesson_id_and_block_id_and_internal_submission_id' on table
    'codeblock_submission' is too long; the limit is 63 characters.
    

    To work around this you can choose a name to use instead of the autogenerated one.

    update the migration with the name key and value:

        add_index :codeblock_submissions, [:user_id, :lesson_id, :block_id, :internal_submission_id], unique: true, name: "index_codeblock_submissions_on_block_lesson_user_submission"
      end
    

    Source

    WSL - Syncing system clock

    WSL2 clock sometimes becomes out of sync with native windows clock. This can apparently happen after resuming from sleep/hibernate but not always.

    To re-sync run:

    sudo hwclock -s
    

    Rails - Extracting controller logic

    In situations where one controller action is responsible for a lot, I’ve usually been able to extract the complicated code into a model method or helper. This works fine when the complicated logic has to do with the model instead of it being a 5 branch if statement on how to decide what to show the user.

    In those situations some people might say that you hecked up and designed your routen poorly. And maybe they’re right.

    Anyway, I was able to turn this complicated controller action:

      def show
        if params.has_key?(:token)
          invite_link = @forum.invite_links.find_by(token: params[:token])
          if invite_link.active?
            if current_user.present? && current_user.is_member_of?(@forum)
              redirect_to forum_posts_path(@forum), alert: "You're already a member of #{@forum.name}."
            elsif current_user.present? && !current_user.is_member_of?(@forum)
              current_user.memberships.create(invite_link: invite_link, forum: @forum)
              redirect_to forum_posts_path(@forum), notice: "You're now a member of #{@forum.name}."
            else
              render "invite_links/sign_up"
            end
          else
            redirect_back_or_to root_path, alert: "Invite link has not been activated."
          end
        else
          redirect_back_or_to root_path, alert: "You don't have access to view that page."
        end
      end
    

    into this:

      def show
        Forums::HandleInviteService.new(@forum, self).process
      end
    

    after realizing that I can just pass the instance of the controller class to a separate Ruby object and then call render, redirect_to, and params on the controller object.

    I’m not the biggest fan of service objects but this seemed to work nicely.

    Heroku - Copying Databases

    Heroku has the CLI command

    heroku pg:copy SOURCE TARGET -a <value>
    

    Which takes a source database and copies the contents to the target database. The problem is that apparently the only way I can specify the database of a specific app is to use the key word DATABASE for both apps.

    copying production data to staging

    heroku pg:copy my-app-production::DATABASE DATABASE --app my-app-staging       
    

    Doing this makes the confirmation message extremely confusing:

    css-float-docs-demo.gif

    It’s not really clear from the warning message which DATABASE will be deleted. You just kinda have to trust that it’s not the source db. The docs seem out of date since they suggested using things like CRIMSON and ORANGE as identifiers for the database but it looks like Heroku stopped that naming convention for database add-ons, or it’s optional and the app pipeline I was working wasn’t using it.

    Either way, this command does do what is should do and when it says “This command will remove everything from DATABASE” it means from the target db, not the source db.

    SSH

    Stands for “Secure Shell”

    Used to access a computer securely over an insecure network.

    This prevents packets from being exposed and understood from other computers connected to the same network (unless it’s the computer you’re ssh-ing to).

    It does this (usually) with public key pairs (asymmetric cryptography) to authenticate devices to each other.

    It go like:

    1. alice: send package to bob w/ alice’s lock on it (pkg 🔒A)
    2. bob: receives package and adds bob’s lock, sends back to alice (pkg 🔒A🔒B)
    3. alice: receives package and unlocks alice’s lock 🔓A, then sends back to bob (pkg 🔒B)
    4. bob: receives package and unlocks bob’s lock 🔓B, reads data (pkg)

    Review web terms with internet basics.

    How it work?

    • When you ssh into pc, you open a TCP connection* (unencrypted) between the source and destination pc.
      • Channel(s) are created to send the data (and enable multipex??? 😕)
    • SSH breaks data down into packets
    • payload (important data in packet) is encrypted
    • server receives packets and decrypts data

    * you can use other connection types like web sockets.

    SSH can mean either:

    • protocol
    • suite of implementation utilities

    Can do:

    • Secure file transer
    • Remote device management and account control
    • Tunneling
    • Forwarding TCP ports an X11 connections

    • good video
    • also good video

    • TCP Forwarding
    • X11 connections

    The ssh or secure shell is a network protocol for operating networking services securely over a network. It uses encryption standards to securely connect and login to the remote system.

    It stores a public key in the remote system and private key in the client system. Thes keys are produced as a pair mathematically. When both are applied to a bi-variable function, it will result in a value which will be used to check whether the pair is valid or invalid. This is the simplest explanation possible. To Learn more, please refer to this page.

    Usage

    Generate ssh key

    ssh-keygen
    

    It will prompt for a key-location (where the key will be saved) and passphrase (i.e. password). The passphrase is optional.

    Use to generate public key for GitHub or Heroku to push/deploy commits without entering password.

    If the key-location is DIR_PATH/keypairforssh, there will be two files

    1. DIR_PATH/keypairforssh
    2. DIR_PATH/keypairforssh.pub

    The .pub is the public key you can share with remote systems. DO NOT share the private key.

    Add private key to the key-agent

    When the key pair is created, it justs exists as a set of two files. In order to connect to the remote system, it has to use the private key.

    Use this

    ssh-add DIR_PATH/keypairforssh
    

    Connecting to remote host via SSH

    username should be a valid user on the remote system and hostname is DNS-recognizable or an IP address so that ssh can contact the remote system and request for connection.

    ssh [username]@hostname
    

    This uses the private key on the local system and public key on the remote system and verifies these are valid pairs. It allows login if and only if key pair is valid and spawns a shell (type depends on the configuration for the user on the remote system) for your use. You can use the remote system as you are using the local system.

    If the private key is not added to the key agent:

    ssh -i /path/to/private/key/file username@hostname
    

    The silly stuff

    copying files

    scp is the thing. It works like ssh and requires key-pair to work.

    scp SOURCE_DIR_PATH DESTINATION_DIR_PATH
    scp ~/Documents/source.txt [username]@[hostname]:~/Documents
    

    Mounting remote filesystem

    A better way to describe “mount” is “attach”.

    The filesystem being mounted is attached to an empty directory of the existing filesystem. That is, the top level directory of the mounted filesystem becomes the directory on the existing filesystem.

    Subdirectories of the mounted filesystem become the subdirectories of the former directory on the existing filesystem, and so on.

    (The directory that was mounted on doesn’t really have to be empty, but after mounting any contents it had are inaccessible, until the filesystem is unmounted). — SO

    sshfs is the tool for this

    sshfs name@server:/path/to/remote/folder /path/to/local/mount/point
    

    name is the username accepted on remote system and server is the remote hostname.

    The nohup command allows you to keep on running commands even after you disconnect your SSH connection.

    SSH Basics