Today I Learned Notes to self about software development

    Docker Login Issue with WSL2

    Try re-authenticating with Docker Desktop and then restart Docker, WSL, and VSCode (which should say something like “updating”).

    Then you should be good to go.

    (trying to log in via CLI in WSL won’t work don’t try)

    • https://github.com/microsoft/WSL/issues/7174

    Passing Variables to View Partials

    Sometimes the multiple ways that variables are passed to partials confuses me.

    locals

    Using locals, whenever you render a partial you must declare the same variable. If you attempt to render the same partial in a different view template without declaring the same local variable, you’ll get an error.

    <%= render :partial => 'form', :locals => { :post => @post } %>
    

    local_assigns

    In cases where sometimes you want to pass a variable to a partial but other times you don’t, use local_assigns. Be aware that you will need to check for the existense of a variable in the partial before you use it.

    <%= render article, full: true %>
    <!-- in template -->
    <h2><%= article.title %></h2>
    
    <% if local_assigns[:full] %>
      <%= simple_format article.body %>
    <% else %>
      <%= truncate article.body %>
    <% end %>
    

    object

    Every partial also has a local variable with the same name as the partial (minus the leading underscore). You can pass an object in to this local variable via the :object option:

    <%= render partial: "customer", object: @new_customer %>
    

    If you see the super shorthand syntax:

    <%= render @customer %>
    

    it uses object: @customer.

    Local Variables in Collections

    These work essentially the same as with single object view partials. To customize the name of the local variable, use the :as option:

    <%= render partial: "product", collection: @products, as: :item %>
    

    You can also still create local variables using locals like before:

    <%= render partial: "product", collection: @products,
               as: :item, locals: {title: "Products Page"} %>
    

    Read more in the Rails Guide.

    How to reconfigure a Rails app to not use a database

    Since the removal of the free Heroku plan, most of my throw-away prototype apps that I deployed have been shutdown. However, there are a few of them that don’t use a database that I expected to continue to work when Heroku shut off the database but didn’t.

    I did a little research and found that you can reconfigure a Rails app to not use a database. This allowed my apps to run purely on the new Eco dynos, without paying for the database connection.

    The steps I followed to reconfigure my Rails 6 app are as follows:

    Comment out/remove the following:

    // package.json
    "@rails/activestorage": "^6.0.0",
    
    // app/javascript/packs/application.js
    require("@rails/activestorage").start()
    
    # bin/setup
    system! 'bin/rails db:prepare'
    
    # config/environments/development.rb
    config.active_storage.service = :local # For Rails >= 5.2
    config.active_record.migration_error = :page_load
    config.active_record.verbose_query_logs = true
    
    # config/environments/test.rb
    config.active_storage.service = :test # For Rails >= 5.2
    
    # config/environments/production.rb
    config.active_storage.service = :local # For Rails >= 5.2
    config.active_record.dump_schema_after_migration = false
    
    # spec/rails_helper.rb
    ActiveRecord::Migration.maintain_test_schema!
    
    # test/test_helper.rb
    fixtures :all # In case you're using fixtures
    
    # Only for Rails >= 5.0
    #config/initializers/new_framework_defaults.rb
    Rails.application.config.active_record.belongs_to_required_by_default = true
    

    Delete app/models/application_record.rb.


    You can run your Rails app in production mode locally to make sure there are no errors.

    RAILS_ENV=production rails assets:clobber
    RAILS_ENV=production rails webpacker:compile # assuming you have webpacker
    RAILS_SERVE_STATIC_FILES=1 RAILS_ENV=production rails s
    

    If there are no errors (with the exception of missing Heroku ENV keys), then you should be good to go!

    If you are creating a new Rails app from scratch and don’t want to use a database, you can run rails new with the --skip-active-record flag.

    WSL spring issues

    I’ve been working in a Rails 5 app recently and ran into some strange issues with the rails console that I didn’t fully understand. Random queries or Ruby expressions would crash the console without allowing me to see the result. Some of these commands weren’t super urgent, I could write the query and display the results on a webpage just fine. Other times I could perform the work in a different IRB, which also worked. Eventually, after I was unable to run generators, I was annoyed enough to investigate, which was difficult.

    [4] pry(main)> Octokit.repository?("appdev-projects/photogram-final")
    /home/jello/.rvm/gems/ruby-2.7.3/gems/pry-0.10.4/lib/pry/exceptions.rb:29: warning: $SAFE will become a normal global variable in Ruby 3.0
    /home/jello/.rvm/gems/ruby-2.7.3/gems/pry-0.10.4/lib/pry/exceptions.rb:29: warning: $SAFE will become a normal global variable in Ruby 3.0
    Traceback (most recent call last):
    /home/jello/.rvm/gems/ruby-2.7.3/gems/spring-2.0.2/lib/spring/application.rb:171:in `fork': cannot load such file -- yajl (LoadError)
    /home/jello/.rvm/gems/ruby-2.7.3/gems/spring-2.0.2/lib/spring/application.rb:171:in `fork': undefined method `reject!' for nil:NilClass (NoMethodError)
    /home/jello/.rvm/gems/ruby-2.7.3/gems/spring-2.0.2/lib/spring/application.rb:171:in `fork': undefined method `[]' for nil:NilClass (NoMethodError)
    /home/jello/.rvm/gems/ruby-2.7.3/gems/spring-2.0.2/lib/spring/application.rb:171:in `fork': undefined method `reject!' for nil:NilClass (NoMethodError)
    /home/jello/.rvm/gems/ruby-2.7.3/gems/spring-2.0.2/lib/spring/application.rb:171:in `fork': undefined method `reject!' for nil:NilClass (NoMethodError)
    

    It appeared to be both a Spring issue and a Windows issue. The first few suggestions just said to stop spring with spring stop then run whatever command that was not working again. This didn’t work for me (spring would auto-start). Updating spring didn’t resolve the issue either, as I could only update so much on a Rails 5.0 app.

    The only thing that did work was disabling spring with an environment variable.

    DISABLE_SPRING=1 rails console
    

    Thanks to this SO answer.

    Rails Delegate

    It’s fairly common that I’m in a situation like this:

    class Submission < ApplicationRecord
      belongs_to :student
    end
    
    
    class Student < ApplicationRecord
      has_many :submissions
    end
    

    And I need to do something like:

    submission.student.full_name
    

    which really isn’t the worst. BUT there is a neat way you can Rails will let you call full_name directly on submission, using delegate (which I always forget about).

    class Submission < ApplicationRecord
      belongs_to :student
      delegate :full_name, to: :student
    end
    
    
    class Student < ApplicationRecord
      has_many :submissions
    end
    

    and that makes it possible to do submission.full_name