WordPress Issue

I've changed the permalinks on my blog to show the year, month and title. This edited my .htaccess file so that the links worked. But my new problem is that images are not showing. So, I'm making this post as a little test. I'm posting a new image to see if it works.

Alan Turning at Bletchley Park

This worked. So my issue is only with images that were already posted. Hmmm. Will have to work on this.

Update #2: Sadly, I couldn't figure out how to fix it. Since there really weren't that many images and I had them all on my laptop, I just reuploaded them.

Odd Jobs

I am one of those people who considers herself completely replaceable. So, at work, I tend to try to continually make myself useful, so that even if I'm not needed to do what I was originally hired for, I can do something else that is required. I don't think that I'm an expert at anything, but I like to learn enough so that I can solve problems that come up. Basically, I consider myself a generalist.

One drawback of this viewpoint, is that, well, I'm completely replaceable. What will I do, if it turns out that I'm no longer needed? Or, more likely, if the funds just aren't there for me to keep my job? I suppose that I could send out a resume and find another job, but that's not very exciting anymore. I think that I'd like to try to start my own business. So, because of that line of thinking, I sort of have. Not officially, yet, but I have been doing odd computer jobs for people on the side.

So far, I've only done a few, but I've really enjoyed them. I like to see how small businesses work. And, the one thing that I really like about computer work, is that it's usually involved in all aspects of a business. So, I tend to learn all about a business, which is really interesting.

Anyway, I am feeling somewhat comfortable in my real job, which is the one that pays the bills and gives me health insurance. But, I'm not going to turn down any side job. If something does happen with the real job, I'm hoping that these odd jobs will set me up for a business that I could move into.

Here's to the future!

Things that Drive Me Nuts (or Why I’d Rather Build My Own Computers)

I recently purchased two Dell Optiplex 380s. Dual core pentiums with 3gb of ram and windows 7 professional for $434 each. I was quite busy and needed to get them quickly for my Mom's office. Normally, I prefer to build my own systems because I know exactly what I'm getting. But the Dells were the right price and easy to order. After I ordered the Dells, I also ordered four Western Digital enterprise drives (WD5003ABYX) to use for a mirrored raid in each system. I did check that the optiplex systems had space for two more internal drives. I also knew that I'd be buying a separate raid card to put in the systems. I didn't order that ahead of time because I wasn't exactly sure what slots would be present/available in the system.

Yesterday, I finally got to my Mom's house to assemble things. I bought some cheap pcie raid cards the day before when I looked over the systems. And I saw there were two extra power plugs for my raid drives, so I thought I was all set. It was only when I started to install the drives that I saw that I could only install the second drive in the proper place if I used a screwless drive tray. Did Dell provide me with this tray? Did they mention anywhere in the ordering process that I might need it? Do they tell me know where I could get one easily? No, to all. So, now, I'm either going to just let the drive lay in the bottom of the chassis, or have to go on ebay or someplace to try and track down two of these things.

I'm not blaming Dell for this. They sold me an inexpensive system, which is what I wanted. I'm more angry at myself for falling for this again. It seems like every time I buy a prebuilt system, I run into these little issues that drive me nuts. When I build my own system, I always use cases from Antec, which usually come with everything I need. Does building my own system cost more? Yep, usually it does. I have to buy a legit copy of windows, which adds $130 to the cost. For this Dell, if they paid what I have to pay for windows (which I'm sure they don't), it would mean that the cost of all the hardware was only $434 - $130 = $304. There's no way I could build a system (that I'd be happy with) for less than that.

So, now attempting to come up with a hack for sticking this drive in the computer. I could break down and buy the tray on ebay, but that's not fun. What would be fun would be to scan the tray I have and then use a 3d printing system to make myself another one! Unfortunately, I don't have a 3d printer or scanner. So I'll have to come up with something more mundane. Hopefully, it'll be fun.

Validating Nested Attributes

I am sure that there's a better way to do this, but I got this working and I wanted to document it.

I have a rails app with two tables, applicants and references. Applicants have many references and each reference belongs to one applicant. Each applicant is required to submit three references, but may submit a fourth.

app/models/applicants.rb

  has_many  :references, :dependent => :destroy
  accepts_nested_attributes_for :references, :allow_destroy => true

app/models/references.rb

  belongs_to  :applicant

Issue #1. How to set up the applicant form so that it accepts the references.
app/controllers/applicants_controller.rb

  def new
    @applicant = Applicant.new
    # We will accept 4 references at most
    4.times { @applicant.references.build }
  end

app/views/applicants/_form.html.erb

    <%= f.fields_for :references do |builder|%>
  1. <%= render "reference_fields", :f => builder %>
  2. <% end %>

app/views/applicants/_reference_fields.html.erb

<%= f.label :firstname, "Firstname" %>
<%= f.text_field :firstname %>
<%= f.label :lastname, "Lastname" %>
<%= f.text_field :lastname %>
<%= f.label :email, "Email" %>
<%= f.text_field :email %>
<%= f.label :institution, "Institution"%>
<%= f.text_field :institution %>

That's basically all I have to do to get the values for the references from the applicants form.

Issue #2. References must have all fields filled in to be an acceptable reference.
The easy way to fix this would be to add the validations to the reference model, like this:

validates_presence_of :firstname, :lastname, :email, :institution

Problem! In our form, we have spaces for four references, but we're only requiring three. Thus, the last reference can be empty. The usual way to fix this is to add this lambda to the applicant model:

  accepts_nested_attributes_for :references, :allow_destroy => true
        :reject_if => lambda { |a| a[:firstname].blank? || a[:lastname].blank? || a[:email].blank? || a[:institution].blank?}

Problem! If the applicant accidentally leaves off one of the fields in the required references, that field will not be shown in the refreshed page. So then, the applicant will no longer have three reference fields.

My Solution (and I'm sure there's a better way to do this, but I don't know how).

Write my own validations.

Take the validates_presence_of line out of the reference model.

app/models/applicant.rb

validate :check_if_have_at_least_three_references

  def check_if_have_at_least_three_references
    all_refs = []
    references.each do |reference|
      if (reference.lastname.empty? || reference.firstname.empty? || reference.email.empty? || reference.institution.empty?)
        reference.destroy # If any fields are empty, we're not saving it
      else
        all_refs << reference # Add good references to the array to see how many we get
      end
    end
    errors[:reference] << " : Three references are required" if all_refs.size < 3
  end

Basically, I just look at each reference and if it's valid, I put it in an array. Then, I check that there are at least three values in the array. If not, I add something to its errors object, which is how we mark an object as invalid.

Here's the bit that I'm sure could be improved, but I don't know how.

app/controllers/applicants_controller.rb

  def create
    @applicant = Applicant.new(params[:applicant])

    if @applicant.save
      ApplicantMailer.thanks_for_applying(@applicant).deliver
      @applicant.references.each do |reference|
        unless (reference.firstname.blank? || reference.lastname.blank? || reference.email.blank? || reference.institution.blank?)
          ApplicantMailer.request_for_recommendation(reference).deliver
        end
      end
      redirect_to(root_path, :notice => "A confirmation email has been sent to #{@applicant.email}. Requests for letters of recommendation have been sent to your references.")
    else
      render :action => "new"
    end
  end

For reasons I don't fully understand, I have to check the references here again, to ignore a blank fourth reference record. I had thought that the reference.destroy in my validation would have gotten rid of the empty one, but it doesn't. So my very bad hack is to check it again here. The reason is because we send email to each of the references, asking them to send in a letter of recommendation. Sending email to a blank email address will cause problems, so we delete if anything is blank. This works, so I'm sticking with it for now.

Issue #3. If there is a problem with the reference fields, an error box is not drawn around the fields when the error is shown.

I didn't care so much about drawing around the individual fields of the reference. All I wanted was one box around all the references saying that three were required. (Since this app is for people applying for a postdoctoral position, I'm assuming that they'll understand what the problem is if there's a single box around the references.)

I used a scaffold to set up the applicants table. This gave me a stylesheet with this class.

.field_with_errors {
  padding: 2px;
  background-color: red;
  display: table;
}

I basically copied this class to one called .references_with_errors, that looks like this:

.references_with_errors {
	padding: 2px;
	border-style: solid;
	border-color: red;
}

app/models/applicant.rb

  def reference_errors?
    errors[:reference].empty? ? "" : "references_with_errors"
  end

app/views/applicants/_form.html.erb

	
Please list at least three references.
    <%= f.fields_for :references do |builder|%>
  1. <%= render "reference_fields", :f => builder %>
  2. <% end %>

If I wanted to, I could have changed the classes on the divs in the reference_fields partial to mark them, but I didn't think that was necessary.

Anyway, this works for me. Unfortunately, I have no tests written for this because I'm still learning how to write proper tests. So, my testing scheme is to just try submitting a form again and again with different problems. It doesn't fail any more, so for now I'm happy with how it works.

Server Updated

I had noticed that my webpages from my server at Slicehost were very, very slow. A quick look showed that I was out of memory and using a lot of swap space. A few times, I even caused my system to crash because I ran out of memory. Today, I cloned my server to a new one with more memory. This is my first post using the new server. I'm testing things to make sure everything is working. So far, so good.

EDIT: That was very, very easy. In fact, I'm a bit astonished at how easy it was.