Monthly Archives: March 2008

Why I Can’t Stand Charter Communications

Charter Communications

I’ve never enjoyed being a customer of Charter Communications for my cable provider. In fact, I’m drooling with anticipation for the day Verizon brings FiOS to my area. Anyway, it seems every time I have to deal with this company I want to scream. Several years ago, it was issues transferring service to someone else in my apartment. Long story made short, they wouldn’t do it and I had to return all of the equipment and my apartment mates would have to re-subscribe. I basically told them all it seemed they wanted was to get their $50 setup fee again. Talk about extortion.

This time, its my HD DVR receiver that wasn’t working properly. Shows don’t play back very smoothly and the HD service is sometimes pretty chopping. Not what you call a stellar T.V. viewing experience.

I call their customer support. The lady I talked to was pleasant and nicely explained that I should just take the receiver to my local Charter location and they’d swap it for a new one. Since one is down the road I said, no problem. Better than wasting 2-4 hours of my day waiting for a service guy, right? I head down there this afternoon to swap out my box. I walk up to the counter and explain my problem to the young lady. The conversation goes something like this:

Me: Hi, I’m having an issue with my HD DVR receiver and Charter customer service said to come in and swap it out for a new one.
Her: We don’t have anymore right now.
Me: Do you know when you’ll get some in?
Her: Well, we’re supposed to get a shipment of equipment in about an hour, but there’s no guarantee that any HD DVR receivers will be in it.
Me: Is there a number I can call in an hour to see if you got any?
Her: No. We don’t want lots of people calling us to see if we have them. We’re having inventory problems and those phone calls would be too much to handle.

One thought before I continue. Charter doesn’t want customer calling because they can’t handle the same question over and over again? Hmm…

Me: Well, I’m paying for DVR service that isn’t working, I’d like to get this fixed so I can actually use the service.
Her: You can schedule an appointment and we can send out a service person to look at it and swap it out. That’s actually the only way you can get a refund is if a technician comes out to test your equipment. Just swapping it out won’t get you anything other than a new box.
Me: Sure, but then I have to block out 4 hours of my day to wait for them. I really just want a working HD DVR receiver.
Her: We have shorter time windows now. I can schedule you an appointment for Monday.
Me: So basically that’s the quickest way I’ll get a new box?
Her: Yes

So I begrudgingly schedule the appointment for Monday between 5pm and 7pm. Two hours I have to sit around waiting for the cable guy. To the young ladies credit, she apologized for the crappy customer service. So even their own customer service employees know that Charter isn’t the best when it comes to making and keeping their customers happy.

Update: So, I just came home and am having issues with live playback now being choppy and pausing on me. Doesn’t matter if its live programming or recorded. After spending an hour on the phone and getting passed to 4 customer service reps, I was hung up on.

Quick note to Charter here, being transfered rom people who are English speaking to obviously outsource people in India who you can hardly understand is annoying. Note to Charter, this infuriates annoyed customer even more. Perhaps you should improve your customer service and transfer people to where they can get their problems resolved, not to people who can’t help let alone not be understood.

Anyway, being the persistent bastard that I am, I called back and talked to two really pleasant people. Josh, who is a customer service rep, passed me on to his supervisor named Chris. She was able to basically just help me out by crediting me for my service for the weekend since I can’t use it (why should I pay for something I can’t use) until a technician can come out Monday and figure out what the issue is.

I just wanted to post this update to point out that not everyone in Charter’s customer service department is completely useless. There are genuine people who care about their product who want to help you. In the end, I’m getting a credit for 3-4 days of service I can’t use. Though its not perfect, its a decent gesture to at least keep me a happy customer. However, as soon as Verizon FiOS comes through the area, Charter is getting the boot!

AJAX Pagination and Sorting in Ruby On Rails

I recently decided the account section of a Rails application I’m working on will be completely AJAX. Every link the user would click on would just replace a section of the account page giving them the impression that they’ve never left their account section because the URL isn’t changing. However, I needed to do pagination and sorting for lists of different things. So hunting on Google I went.

I first came across this article over at Rails on the Run about how to do it with will_paginate, prototype, and low pro. I mucked around with it for about 30 minutes and definitely had some struggles, so I went back to Google. I eventually came across this article at Redline Software’s Weblog about an easier way to do it with will_paginate. The nuts and bolts of it is you can use a helper class to write your pagination links for you very easily (I won’t steal their code and post it here. Check out the link to grab it.)!

But I’m not done yet. Remember, I also need to be able to sort my lists of data. So I ran with the same idea presented by Redline Software and came up with this way to write out the anchor tags for my sort links:

def sort_remote_url(text, value)
    value += "_reverse" if params[:sort] == value
    @template.link_to_remote text, {:url => params.merge(:sort => value)}
end

What sort_remote_url does is take in the text for the link and the value of the sort parameter. When you click on the sort link, it works just like the pagination and updates the current view.

Becoming A Proud Nintendo Wii Owner

Nintendo Wii

I was finally lucky enough to get my hands on a Nintendo Wii. Some people at work had a line on some that they needed for a giveaway and I was able to get the last one at a local Walmart. I’m still stumped as to why on earth these things are still so hard to get, but they are. I ended up paying about $325 for the Wii Console and a second Wiimote and Nunchuck. The first night, I think I played Wii sports for about 6 hours. Man was I sore the next morning. Funny how you try to play the sports like you would in real life. Reminds me of Morpheus asking Neo, “Do you think that’s air you’re breathing?”

Now I have the new Zelda game, which is fun, but hard. It also takes a lot of time to play, which I don’t have a lot of. We’re also borrowing a copy of Mario Party 8, which is kind of silly but is fun to play with friends. I can imagine its hilarious as part of a party or something. I’d like to get a couple more “group” type games like Super Smash Brothers Brawl or Mario Galaxy. I think the game prices are fairly reasonable, but I don’t want to get too far ahead of myself.

Anyway, if you’re lucky enough to find one in a store, I’d definitely get one. Its worth the money!

Sorting Geographical Based Search Results In Ruby on Rails

Ruby on Rails

I’ve spent the last few months on a Ruby on Rails project for a client. I’m integrating a lot of different applications into it, creating quite the “mashup”. One part of the project requires the ability to search the system for results that fit within a radius of a given postal code. So to do this, I need some sort of searching algorithm or application and a geocoding application for zip code relationships. The search results need to be able to be sorted by the different attributes on the results.

So this meant I needed several pieces. One was a searching module. I found ferret and the acts_as_ferret Rails plugin to do full text searching. From what I could gather online, this was one of the best solutions out there. I want to be able to display distances between zip codes, which I can do using GeoKit. So I find myself off and running.

I was able to do everything successfully from getting the right results back to calculating distances (Side note. If you need a start with acts_as_ferret, there’s a good article here at Rails Envy). However, because the distances between zip codes are calculated and not part of the ferret index, I can’t sort by results. Uh oh…

The solution was, in my opinion, a hack, but it works. What I did was let acts_as_ferret handle sorting for everything except distances (it couldn’t do it anyway, so fine). After I get my results back, I decided, well, I guess I can sort them again, right? So, let’s do this:

@total, search_results = MyModel.full_text_search(@search_term, 
  {:sort => s},
  {:include => [:zip_code],
    :conditions => conditions})

This gets me my search results. What about distances? Well, this can be done, even though its an issue performance wise:

for sr in search_results
   sr.destination_distance = round_to(sr.zip_code.distance_to(@search_zip_code), 2)
end

So now each result knows what its distance is from the searched upon zip code. Now what about sorting?

if params[:sort] == "distance"
    search_results = search_results.sort
    @total = search_results.length
elsif params[:sort] == "distance_reverse"
    search_results = search_results.sort
    search_results = search_results.reverse
    @total = search_results.length
end

So now you’re thinking, ok, but how do you know how to sort MyModel? Easy, I decided I’d override <=> for the MyModel class so that a MyModel was less than, greater than, or equal to another MyModel based on distance. So I did this:

def <=>(item)
    if self.destination_distance < item.destination_distance
      return -1
    elsif self.destination_distance > item.destination_distance
      return 1
    else
      return 0
    end
end

So you can see with the example above, I can sort by just calling sort. To reverse the sort, just call reverse after sorting.

So there you go, sorting by distance values. There are definitely drawbacks with this method. First, you have to iterate over all of the search results to set the distance on them. Second, what if I need to sort by some other calculated value? Since I overroad <=> for distance, I can’t really do it for another value. But for now, this works. Maybe I, or someone else, can come up with a better solution.

Uploading and Resizing Images in Ruby on Rails

ImageMagick

In my previous article on using ImageMagick and Mini-Magick to manipulate images in Ruby on Rails, I talked about how to install all of the goodies you’d need to work with images in Rails. I thought I’d expand on this a little bit more and give an example on how I used this cool stuff to upload images and resize them in my Rails application.

You’ll need to set up some HTML code to upload the file to the server. Something like this will suffice:

<% form_tag :action => 'upload', :multipart => true, :id => 'upload_form' do -%>
     <input style="margin-left: 5px;" type="file" id="imageone_file" name="imageone[file]" />
<% end -%>

Now you’ll want to build a model (based on ActiveRecord or not) to save your image for you. For my use, I did based my image model on an ActiveRecord class since I wanted to at least store the file name of the image in my database. But doing that is up to you. Anyway, on to saving the image. In your class, you want to grab the data for the image file in the posted form and save it to the file system. Something like this will suffice:

def image_save(file)
    @file = file
    @content_type = file.content_type.chomp
    @original_filename = base_part_of(file.original_filename)
    @extension = @original_filename[@original_filename.rindex(".") .. @original_filename.length].strip.chomp
    
    self.file_name = "#{epoch_time()}#{@extension}"
    
    is_saved = false
    begin
      if self.file
        if self.content_type =~ /^image/
          # Make the directory for the id of the listing if it doesn't exist
          Dir.mkdir("#{RAILS_ROOT}/public/images/originals/") unless File.exists?("#{RAILS_ROOT}/public/images/originals/")
          
          # What's the new file name?
          
          # Create the temporary file
          File.open("#{RAILS_ROOT}/public/images/originals/#{self.file_name}", "wb") do |f|
            f.write(@file.read)
            f.close
          end
          
          # Crop the image to the sizes we need
          crop()
          
          is_saved = true
        end
      end
    rescue
    end
    
    return is_saved
end

So what are we doing here? First, we grab the content type of the file, its original file name, and the extension of the file. We save this information out to attributes defined on the model itself, i.e.

attr_accessor :file, :content_type, :original_filename, :extension

Then we check to make sure the directory where we want to save the original file exists, and if not, create it. Then we save the file itself. Once we have the file saved, you’ll notice I call a method called crop(). This is my method that resizes the original image and saves the resized images to the file system. How do I do that? Check this out:

  def crop()
    image = MiniMagick::Image.from_file("#{RAILS_ROOT}/public/images/originals/#{self.file_name}")
    if !image.nil?
      # Resize to 360x360
      image.resize "360x360"
      image.write("#{RAILS_ROOT}/public/images/360x360/#{self.file_name}")

      # Resize to 240x240
      image.resize "240x240"
      image.write("#{RAILS_ROOT}/public/images/240x240/#{self.file_name}")

      # Resize to 120x120
      image.resize "120x120"
      image.write("#{RAILS_ROOT}/public/images/120x120/#{self.file_name}")

      # Resize to 80x80
      image.resize "80x80"
      image.write("#{RAILS_ROOT}/public/images/80x80/#{self.file_name}")
      
      # Resize to 40x40
      image.resize "40x40"
      image.write("#{RAILS_ROOT}/public/images/40x40/#{self.file_name}")
    end
  end

As you can tell, I needed several different image sizes. You start with the lowest size and work your way down. Not doing this gets you funky sized images. MiniMagick makes it really easy to just open the file and set the new size for the image and then just write it out to where you want it. Nice!