Burke Mountain has been my go-to spot.

Looking forward to Winter

This year, I am hoping for a long, snowy winter.

Last year our winter was cut short on account of COVID. This year our winter will be different because of COVID. Ski resorts are posting their precautions and rules and though they vary from place to place, the bottom line is that things will be different.

Most resorts, as far as I know, are not opening their indoor spaces. So, you won’t be able to enjoy lunch (at least inside) or an after-ski beer. That will be tough! But if we have good snow, I don’t think I’ll care. I’ll just focus on the positive and enjoy some good skiing.

This will be my third season downhill skiing. I did not grow up doing this as a kid. In Texas, snow was an extremely rare oddity. I remember one year we got a “snow” and the news covered it. A kid had made a respectable snowball, but it required all the snow on his front lawn. The grass was green underneath. That was the biggest snow I remember.

Now, I am pretty used to snow. And I’m excited for season three on the slopes. Here’s hoping for a cold, snowy, long winteer. It will be a welcome distraction from all the other crazy things going on in the world.

Another Overstatement

This is yet another Overstatement.

I am moving my blog again - in part as a learning exercize. This site is now running on Nginx, being createed with Jekyll. I configured the server, so here’s hoping it is all working right…

And maybe with this new set up I’ll post a bit more. That would be good for me.

Thank you to all my fans.

Churchless

A lot of people have left the church. I’ve entertained the idea many times myself. But I never really thought the church would leave me.

Today, the United Methodist Church, in which I was baptized, grew up, ordained, and for many years served as one of its clergy, voted to essentially split over the “issue” of homosexuality.

A lot of details remain to be clarified. But the ultimate destiny is now clear. The United Methodist Church will collectively stick it’s head in the sand and declare that homosexuals have no place in their club. Those of us who envision a church defined by more than it’s narrow understanding of human sexuality and who wish for the church to welcome everyone, regardless of anything, will be left to create a new church born from the broken remains.

Among reasons for churches to split, this must rank among the most petty.

This is the message the United Methodist Church has for gay and lesbian people: you are not acceptable. You do not belong. You are not welcome. Think about that. That’s the good news from the UMC. What future is there in that? Do conservatives honestly think that they will march gleefully into righteousness by excluding and condemning a marginalized group in our society that has only recently started to find their place in our culture? Is that the basis of our church? It is so critical that we express this cruel and exclusionary position, rooted in homophobia, that our church can split in half.

The plan that has passed is called the Traditional Plan. How appropriate. What church thinks it’s future lies in clinging to tradition?

Sadly, this move will do little to address the underlying problems facing the UMC. Those who think clarifying the church’s position on homosexuality will lead to a new era of growth are not only out of touch with reality, they also don’t understand the fundamental problems of the UMC. Like our structure. Like the itinerancy. Like our property laden congregations. Like the lack of viability of many of our churches. Like the guaranteed appointment. This is not a plan to address any of the problems facing the church. This is a plan to satisfy a self-righteous agenda attempting to preserve some self-perceived holiness in a misguided attempt to enforce sexual norms that literally have nothing to do with the gospel of Jesus Christ.

I am saddened by this news. But like all bad news, there is also some hope. Perhaps this moment will empower the emergence of a new kind of church, that will address the long-standing issues facing the UMC and at the same time offer some good news for all of God’s people.

In the meantime, I feel churhcless.

A job, however frustrating, is made more pleasurable when it is situated in a context that connects to one's passion.

A Dream Job

There is no such thing as a perfect job.

All jobs have their ups and downs. As I begin a job search, I’m really not thinking so much about the actual job as I am about the community and culture of the company for which I will work. The job will have it’s pros and cons, like all jobs. Hopefully more pros than cons, obviously. But the environment in which I work will really shape my happiness and enjoyment, as well as my effectivenss.

That’s because a job - however frustrating - is made more pleasurable when it is situated in a context that connects to one’s passion. If I find myself reformating huge XML files for some application, the task would be bearable if the mission and culture of the organization inspires my passions.

To that end, I am hoping to find the following things in my next place of employment:

I’m sure there are other things that matter to me - like compensation, benefits, etc. But the above list captures the things that come to my mind as distinctives. I hope I can find a rewarding work place, that empowers my Vermont lifestly, and engages the world with positive change all while leveraging my unique set of talents.

How hard can that be to find?

I think I went off the rails!

My First Rails Project

For my first Ruby on Rails project, I chose to build an app I called: Chamption: A Playbook Manager for Football Coaches. Champion allows a football coach to create a collection of playbooks, add plays to them, create opponents and schedule games against their opponents.

The project turned out to be larger than I expected. Initially, I thought I would just do the “playbook” portion, but as I went along and thought things through, I added the “games” piece and then things just kept expanding. In church, we would call this ‘mission creep.’ So, I had to reign myself in and focus on the core requirements from Flatiron.

Here is a video of the app that introduces the core concepts:

To exemplify some of the code, let’s look at how you create a user and also add a profile for that user. The user is a coach, and when they create an account, they can add some additional details that are stored in a separate table. If they choose to log in with Facebook, an empty profile is created for them. First, let’s look at how the models are configured:

class User < ApplicationRecord

  has_secure_password
  
  has_one :profile, dependent: :destroy
  has_many :playbooks
  has_many :plays, -> { distinct }, through: :playbooks 
  has_many :games
  has_many :opponents, through: :games

  validates :name, presence: true
  validates :name, length: { minimum: 2 }
  validates :email, presence: true
  validates :email, uniqueness: true
  validates_format_of :email,:with => /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/

  accepts_nested_attributes_for :profile
  
end

You will notice that the user model uses has_secure_password in order to use bcrypt to encrypt the password. If the user comes from Facebook, a dummy password is supplied just to make sure it passes the validations. Also, you will notice that a number of other validations are set up to ensure the user name is of a certain length and the email is valid and unique. The email address serves as the user’s identity. Finally, notice that a user has one profile and can accept nested attribues for profiles.

Now, let’s look at the profile model:

class Profile < ApplicationRecord
  belongs_to :user
end

This one is super simple. It simply belongs to a user. This, along with the relationship set up in the user model, sets up the one to one relaionship with a user, so that a user has one and only one profile.

Most of the work of creating a new user is handled in the user controller, so let’s look at that:

class UsersController < ApplicationController
  
  before_action :require_login
  skip_before_action :require_login, only: [:new, :create]

  def new
    @user = User.new
    @user.profile = Profile.new
  end

  def create
    @user = User.new(user_params(:name, :email, :nickname, :password, profile_attributes: [:role, :nickname]))
    if @user.save
      session[:user_id] = @user.id
      redirect_to @user
    else
      render 'new'
    end
  end

  def show
    if params[:id].to_i == current_user.id 
      @user = current_user 
    else
      redirect_to current_user 
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update 
    @user = User.find_by(id: params[:id])
    @user.update(user_params(:name, :email, :nickname, profile_attributes: [:role, :nickname]))
    redirect_to user_path @user 
  end

  def index
    @users = User.all
  end

  private

  def user_params(*args)
      params.require(:user).permit(*args)
  end

  def require_login
    return head(:forbidden) unless logged_in?
  end
end

In this code, you are required to be logged in for all the routes except for the new and create routes. These are the ones of interest here. You don’t need to be logged in for those, becuase you are creating a new account, hence can’t be logged in, right? If you look at the create method, if creates a new user based on the input the user provided, and if the user can be saved, it then logs that user in and displays the user’s show page, which is their profile page. If the user can’t be saved, that means one of the validations didn’t pass, so the create form is shown again with errors displayed.

To see how the errors are handled, let’s look at the new user form:

<div class='row justify-content-center'>
  <div class='col-5'>
    <h1 class='display-22'>Sign Up</h1>

    <%= render partial: 'shared/error_messages', locals: { item: @user } %>
    <%= render partial: 'form', locals: { submit_msg: 'Create Coach' } %>

    <p>Already have an account? <%= link_to "Log in here.", login_path %></p>
    <p><%= link_to('Or log in with Facebook!', '/auth/facebook') %></p>

  </div>
</div>

Here I made use of partials. The first partial is used across all forms to show errors. It is stored in the shared folder and passed the object that has errors as a local variable. This allows the error partial to be generic. Here it is:

<% if item.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-danger">
      <p>The form contains <%= pluralize(item.errors.count, "error") %>.</p>
    <ul>
    <% item.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
    </div>
  </div>
<% end %>

Finally, let me show you the partial for the new user form itself. It uses a local variable to customize the text on the submit button:

<%= form_for @user do |f| %>
  <div class="form-group">
    <%= f.label 'Name' %>
    <%= f.text_field :name, class: 'form-control' %>
  </div>
  <div class='form-group'>
    <%= f.label 'Email' %>
    <%= f.text_field :email, class: 'form-control' %>
  </div>
  <%= f.fields_for :profile do |ff| %>
    <div class='form-group'>
      <%= ff.label 'Nickname' %>
      <%= ff.text_field :nickname, class: 'form-control' %>
    </div>
    <div class='form-group'>
      <%= ff.label 'Role' %>
      <%= ff.text_field :role, class: 'form-control' %>
    </div>
  <% end %>
  <div class="form-group">
    <%= f.label 'Password' %>
    <%= f.password_field :password, class: 'form-control' %>
  </div>
  <%= f.submit submit_msg, class: 'btn btn-primary' %>
<% end %>

This project was challenging for me - and I learned a lot. I started off trying to use bootstrap which turned out to be a daunting learning experience in and of itself. And then the general scope of my project expanded, and I had to learn a lot more stuff. I must say I like learning new things…but I also like getting something done. At times, these interests were in conflict. I reminded myself of one of Steve Job’s famous qoutes: “Real artists ship.” So, now, I’m done!