On 3.2

January 30, 2012 § 2 Comments

Last Rails 3.2 post. I swear.

I mentioned ActiveRecord::Relation#pluck in a previous post because it was one I was particularly excited about. After reading through the rest of the release notes I wanted to highlight a few of the other smaller changes I thought were interesting.

ActiveRecord

ActiveRecord::Relation#uniq

Client.select('DISTINCT name')

is now written

Client.select(:name).uniq

You can also revert the uniqueness with

Client.select(:name).uniq.uniq(false)

Don’t user LOWER for case insensitive searches on MySQL

When querying against our databases there are a bunch of times we don’t care about case. In the case of searching against an email address, a case insensitive search does exactly what we want it to. When you add the :case_sensitive => true to a validates_uniqueness_of it use to wrap that part of the query in a LOWER(). This sucked because it prevents MySQL from using an index. When you put this restriction on your email column and have to do this query every time you save a record. Since MySQL does case insensitive searches, ActiveRecord doesn’t worry about adding the LOWER() around the columns. Time saved all around!

rake db:drop drops both dev and test

rake db:create creates both the development and test databases. rake db:drop now drops the both development and test databases instead of just the development database.

ActiveView

namespace form_for

When you have multiple forms on one page for the same type of objects, you can get conflicting ids form elements. Problem solved with form namespaces.

<%= form_for(@offer, :namespace => 'namespace') do |f| %>
  <%= f.label :version, 'Version' %>:
  <%= f.text_field :version %>
<% end %>

The ids of the form elements have the namespace prepended with and underscore to the front of the original id.

ActiveSupport

Time Ranges

One of the things that I love most about Rails is ActiveSupport. And one of the things I love most about ActiveSupport is how it makes dealing with Time awesome and easy. They have added a few new convenience functions to help with date ranges:

  • Time#all_day
  • Time#all_week
  • Time#all_month
  • Time#all_quarter
  • Time#all_year

You can use these with ActiveRecord queries like so:

Event.where(:created_at => Time.now.all_week)
Event.where(:created_at => Time.now.all_day)

Obviously there are a lot of other additions in 3.2, these are just the few that I know that I am going to have a use for. Enjoy.

On Pluck

January 23, 2012 § Leave a comment

Rails 3.2 has been released and there are a few things in it that I am excited about. I mentioned in a previous post that a few of the things coming in 3.2 were things that I had thought about doing or had already done myself. Turns out I missed one.

ActiveRecord::Relation#pluck

This is the exact same functionality provided by my select-column gem. It allows you to get an array of column values from the database without having to instantiate an ActiveRecord object for each one. So instead of having to do this:

Post.where(:published => true).collect(&:id)

you can simply do:

Post.where(:published => true).pluck(:id)

The place I see this having a lot of nice applications is in caching. I know that I wrote my gem so that I could use it to speed up some methods that would find appropriate records and then cache the ids for quicker look ups later. I am really excited to do a find and replace of collect for pluck in some of my projects.

On Personal Configurations

January 3, 2012 § Leave a comment

In a lot of the Rails projects I work on we use yaml files to set up configuration variables, things like domain urls, facebook and paypal keys, smtp configurations and many more. A lot of these can be different across different environments. The domain we use in our development environment might look like 127.0.0.1:3000 where in production it would look like awesome.com. We use Rails’s database.yml as a template for the rest of our configuration files, so an example of our config/config.yml might look like this:

test:
  name: AppName
  host: 127.0.0.1:3000
  push_endpoint: http://lvho.st:8080/app/cometd

development:
  name: AppName
  host: lvho.st:3000
  push_endpoint: http://lvho.st:8080/app/cometd
  user_dev_tweaks: false

production:
  name: AppName
  host: sweetdomain.com
  push_endpoint: http://sweetdomain.com:8080/app/cometd

We then slurp the current environment’s settings into a global constant in config/application.rb with the following:

CONFIG = YAML.load_file("#{::Rails.root.to_s}/config/config.yml")[::Rails.env].symbolize_keys

See all of the code in the gist for easier reading.

On Riding the Latest Rails

December 29, 2011 § Leave a comment

Note: I wrote this up a few weeks a go, but didn’t publish it for some reason. It is a touch out of date since Rails 3.2 RC1 was recently released, but should be close enough to give you a good idea on how to get up and running on Rails master.

I wanted to play with the latest and greatest for Rails, which at the time of writing is 3.2.0.beta (RC 1 is now out). This means building and installing the rails gem locally. It took me a good while to figure out how to get everything working, so I figured I’d throw it down here for future reference… and for anyone else running into the same problems I did.

I am using rvm to isolate my different gem set ups, so as not to get random version conflicts. These are the lists of commands with notes I ran to get everything up and running:


# create a new gemset to use with rails master
rvm gemset create rails-master
rvm gemset use rails-master

# this is where I am going to put all of the git repos
cd ~/src

# Rails 3.2.0.beta requires the most recent (as in master)
# versions of arel and journey

git clone git://github.com/rails/arel.git
cd arel
gem build arel.gemspec
gem install arel-*.gem

cd ..
git clone git://github.com/rails/journey.git
cd journey
gem build journey.gemspec
gem install journey-*.gem

# now get Rails
cd ..
git clone git://github.com/rails/rails.git
cd rails

# install all of the Rails pieces,
# i.e., ActiveRecord, ActiveSupport, etc...
cat RAILS_VERSION | xargs ruby install.rb

# check to make sure you are riding the correct rails
ruby -r 'rails' -e 'puts Rails::VERSION::STRING'

You can get just the commands in a gist too.

On Not Rolling Your Own Verification or Encryption

November 10, 2011 § Leave a comment

When developing code, there are somethings that you should leave to the experts. Encryption is one of them. When I wrote my encrypted cookies and encrypted cookie sessions gems, one of the the things I didn’t want to do was write any sort of encryption routines. Luckily ActiveSupport has some help in the way of ActiveSupport::MessageEncryptor. It’s used much like ActiveSupport::MessageVerifier which is used for signed cookies in Rails. People much smarter than me have put these pieces together, so it just makes sense to use them. Almost nothing good can come from trying to do this stuff yourself. Here are some examples of a verifier and encryptor being used.

ActiveSupport::MessageVerifier

> secret = ActiveSupport::SecureRandom.hex(10)
 => "379af645b8dcce20b607"

> verifier = ActiveSupport::MessageVerifier.new(secret)
 => #<ActiveSupport::MessageVerifier:0x00000103d7ce50 @secret="379af645b8dcce20b607", @digest="SHA1">

> signed_message = verifier.generate("sign this!")
 => "BAhJIg9zaWduIHRoaXMhBjoGRVQ=--af1e810b074b1abd6d9dcd775f71b1fafa53c218"
# this is "<base 64 encoded and serialized string>--<digest of string>"

> verifier.verify(signed_message)
 => "sign this!"

> verifier.verify(signed_message + "alittleextraontheend")
ActiveSupport::MessageVerifier::InvalidSignature

> verifier.verify("alittleextraatthebeginning" + signed_message)
ActiveSupport::MessageVerifier::InvalidSignature

ActiveSupport::MessgeEncryptor

> secret = ActiveSupport::SecureRandom.hex(20)
 => "c1578de6ec2e1789940729dc9d97b335fc7df588"

> encryptor = ActiveSupport::MessageEncryptor.new(secret)
 => #<ActiveSupport::MessageEncryptor:0x000001295337c8 @secret="c1578de6ec2e1789940729dc9d97b335fc7df588", @cipher="aes-256-cbc">

> encrypted_message = encryptor.encrypt_and_sign("Nothing to see here...")
 => "BAhJIl9YbDZkK0czS3o0ZkI0Yml6K05uYzgzM05meDJjWWU4QWh0YzdFeFFrbC85b3BocHFORWtRWXdDVWIxaW45TEQ5LS1yVkxGTURJYzFWb2pva0UrVkkwTkFnPT0GOgZFRg==--e61e02a818960d66c7865f5624fad63b1564283f"

> encryptor.decrypt_and_verify(encrypted_message)
 => "Nothing to see here..."

If your secret is too short you’ll get a OpenSSL::Cipher::CipherError. Make sure your secret is at least 32 bytes. Using ActiveSupport::SecureRandom.hex(16) should satisfy this requirement, but obviously longer is better. You can also pass in a :digest => <digest> option as a second argument to both initializers to specify a different algorithm to use.

One of my thoughts is to submit these two gems into Rails so that people don’t make the mistake of trying to roll their own encryption systems for cookies. We’ll see how it goes.

On New Milestones

November 7, 2011 § Leave a comment

Earlier this year I got the itch to start doing some open source stuff. I hadn’t done anything of the sort before, so I didn’t really have any idea where to begin.  There have definitely been some bumps along the way, but I think that I have made some progress.  Looking back on my progress I identified a few milestones I hit along the way.  They weren’t obvious at the time, and I certainly can’t say that I meant to achieve each one, but I can clearly see them now.  Each one helped me a little more on my way to being an open source contributor.  Each one also elicited different thoughts and feelings.  Now in no particular order and mostly for me to remember what I was thinking…

First Repository Uploaded to GitHub

I signed up for GitHub back at the end of 2008.  I forked a few repos here and there just because there was a button to do it.  I didn’t really know anything about git and didn’t do anything with repos I had forked.  I didn’t actually upload a repo of my own until the end of March 2011.  I had been working with subdomains in Rails 3 and experimenting with the new cookie jar chaining.  I found a use case for adding another cookie jar that assigned the domain of the cookie.  I abstracted it out, gave a poor project name and put it up on GitHub. [tld-cookies]

It was a bit nerve-racking putting something you have made out there for whole world to see.  I am sure artists feel the same way when they show their paintings or writing to the general public.  I had no expectations that people would look at it or care about it, but still it was out there for people to scoff at if they saw fit to.  Nervous as I was, I felt something that I wasn’t expecting… liberation.  Even if no one ever used my code, I was now a contributing member of the open source community.  It felt great.

Two more repos went up almost immediately.

First Gem Published

When I pushed my first repos, the code was more or less in it’s finalized state, so the gem(s) followed quickly behind.  I remember having my RubyGems.org dashboard up all day watching the those first downloads trickle in.  I quickly realized that the first dozen or so were mirrors downloading all the new and updated gems.  Not going to lie, was a little sad when I realized that.  That first gem still sits at 50 downloads, probably because of it’s bad name, but some of the other ones have a few hundred downloads.

It’s awesome.  Some of my peers, not my coworkers, are using my code.  Building things that people use is awesome, whether it’s a website or a library.  As a software developer, I get a thrill when websites I work on get traction and usage.  Building successful businesses is my end goal, but with that being said, I get a very different and more personal thrill when I see some of my code being used by other developers.  It is a type of validation of your technical skills and it feels great.

First Gist Uploaded

We are a rails shop at work.  One of the things that I was getting annoyed with when dealing with debug statements was where to print these statements out to.  Do I print them to the log file or to standard out?  The log file is the obvious choice, but if you are working in the console, then using puts so you don’t have to switch terminal windows might be preferable.  I spent some time and came up with a useful little function.  I realized that this might be useful to others so I put it up on GitHub as a gist, and called it a day.  Looking back, this was really the first time I just casually threw something out there that I thought might be interesting, but wasn’t a fully functioning library.

First Issue Filed Against Me

Then came the bugs… I had my first GitHub issue opened against me about two months after I published my first gems.  Now here is the funny thing, I got excited.  Like watching the downloads trickle in on RubyGems.org, someone opening a bug against you means they care enough about what you are doing to want/need it to work right.  Obviously I want it to work as well, but I know that I am bound to let bugs slip through.  When someone took the time to report a bug and identify the potential source of the problem, I knew that I was doing something right.  Well, something was wrong but the situation was right… right? [bug]

First Issue Filed Against Me Fixed

Fixing the issue and pushing out a new version was satisfying.  I had the satisfaction of knowing that I cared enough about a little side project and the people using it to fix the issues and rerelease the gem.

Dealing With Future Compatibility

When I first pushed out my encrypted-cookie-store gem it was Rails 3.0 only. I figured I’d update it when 3.1 was released because I wasn’t expecting people to really care that much about it. Turns out I was mistaken. Not long after it was pushed out I got a request to add 3.1 compatibility. Well, one of my customers was asking for it and I was going to have to do it sooner or later, so I fired up rvm and got to work on figuring out what changed between 3.0 and 3.1. It wasn’t that big of a deal, but having different methods defined based on the which gems are installed seems like a less than ideal way to go about things. Thus concluded my first attempt at programing against an unreleased version of a project.

First Pull Request for One of My Projects

Now having someone open an issue against you and pointing you in the direction of the problem is nice and all, but having someone open a pull request against your project because they liked/needed it enough to fix the issue themselves, that is an awesome feeling. My little sparse matrix library was getting some love from across the Atlantic. Couldn’t have been happier.

First Issue Opened Against Another Project

Almost as scary as putting your own code out there is opening an issue against a well established project like Rails. You keep asking yourself, “Am I doing something wrong?” or “Do I just not understand what is going on?” I mean, what if your issue is just a result of you being stupid and not knowing what you are doing? These guys are busy and don’t really need to deal with bugs that probably aren’t actually bugs. So you run every test case you can think of, and then some that have nothing to do with your issue, you know, just in case. Then you hope that everyone is nice to the newbie. PS – They were.

First Pull Request to Another Project

It made me even more nervous to offer up a fix. Opening that Pull Request was nerve racking. I was patching one of the most used methods in ActiveRecord, so I obviously didn’t want to mess up. My pull request went through a couple of iterations, mostly on my test cases, but was finally accepted and merged into master 11 days after I opened the initial issue. Once again everyone was great and very helpful.

Started Blog

And then the blog started. I won’t lie to you, the last bit of motivation I needed to finally get this blog up and running was bit of selfishness. I realized that I needed some way to let people know about the stuff I had put out there that might be useful to them. This obvious thought happened when I came across a blog of someone working on a similar problem with encrypted cookies saying that they were thinking about packing it up and submitting it to rails. Since I liked the way I was doing it better, I figured I needed something other than the GitHub page as a way to promote it. Since then I have started writing on more topics than just the gems I have written. A blog, when properly utilized, is much more than just an advertising platform for your own code.

Being Asked to Contribute to a Project

The most recent development in my open source career is being asked to contribute to SciRuby. They liked the work I was doing on a sparse matrix library I was working on, and asked if they could include it in their offerings. Obviously I was ecstatic. Then I started thinking about the state of the code and how much work was left to do on it. Then I started worrying. It is very much still in an alpha/incomplete state. But now that I know that I have some people that are interested in it, I should be able to get working on it some more. Get that math side of my education some more use.

Conclusions

I have come a long way with my contributions to the open source community. From using to creating to contributing, each of these milestones has been a new challenge and a new experience. This isn’t a how to get a start in OSS, but it a list of things that you can look at for next steps when you are stuck and want to get more involved. It’s easy and most people will be excited that you want to help or are offering something up they can use. Even if you don’t want to write something, use OSS. That is your true first step.

On the Differences of Months

July 28, 2011 § Leave a comment

Dealing with dates is hard.  Dealing date calculations is harder.  Luckily, in the Rails world we have ActiveSupport to help us with a lot of this.  It actually does so much, that I usually forget how much of a pain dealing with dates is suppose to be.  However, there are times now and then that I am reminded.  Little edge cases that haven’t yet been built into ActiveSupport.  One such edge case is determining the number of months between two dates. Why do months have to have different numbers of days?

This particular use case can be very useful when dealing with recurring payments.  Calculating the number of payment cycles a subscriber has gone through can tell you how much revenue they have generated.  I have put together two class methods for the Time object that will calculate just this.  One is a simple loop that takes time proportional to the time between the start and end times, and the other a more efficient direct calculation of the same number.

The simple loop looks like:

def months_between2(start_date, end_date)
  return -months_between2(end_date, start_date) if end_date < start_date

  count = 1

  while true
    return count - 1 if (start_date + count.months) > end_date
    count += 1
  end
end

It just starts at the start_date and keeps adding months until it passes the end_date. Not particularly difficult, but should get the job done for most cases.  All the complexity of the more efficient version comes from checks dealing with the various cases arising from different months having a different number of days. Anyways, the source code for that one looks much nicer over on GitHub.

On the Size of a String

July 21, 2011 § Leave a comment

In computer programs, number constants can be interesting and bewildering things.  Trying to figure out why one was chosen over another can be really confusing.  For a good while I was confused as to why ActiveRecord would set a string attribute to be a VARCHAR(255) in the database.  It limits the size of the string attributes to 255 characters long.  256 is a bit more natural when choosing constants in computer science.  255 is commonly used to denoted the last index in a 0-based array of 256 elements.  So why 255?  The short answer is “because of InnoDB and UTF-8 character sets.”

InnoDB has a limitation on the size of a key for a single column index of 767 bytes.  When the table is encoded with a UTF-8 character set, each characters has the possibility of using 3-bytes to represent its intended character.  That means in order to be able to fully index a UTF-8 encoded varchar column, the string must be able to be represented in 767 bytes.  767 / 3 = 255 2/3.  This means that the largest UTF-8 encoded varchar column can be 255 characters long, hence the ActiveRecord default string attribute size.

Problems on the Way

As bigger and bigger pushes are made for complete internationalization, we’ll see more things encoded with UTF-16 and UTF-32.  Characters using these encodings might require up to 4 bytes to represent their value.  When this happens, ActiveRecord will need to reduce the size of indexable string attributes to 191 characters.

For Fun

Here is a truly awesome magic number that seems to come out of no where, 0x5f3759d5.

On Cross Subdomain Cookies

July 12, 2011 § 1 Comment

The first Ruby gem I ever wrote was tld-cookies.  While it is very poorly named, probably should have been called root-domain-cookies or something like that, it adds a nice little bit of functionality to the Rails 3 cookie jars.

One of the things about Rails 3 that I thought was really cool, was the way cookies were accessed. It’s not a big and fancy piece of code, but to me it is just a slick way to do things. The chaining of the different cookie jars makes it trivial to create the cookies you want and need.

cookies.permanent.signed[:awesome_cookie] = "cookies awesomeness"
cookies.signed[:awesome_cookie]
 => "cookies awesomeness"

At the time I was working on a project at work that required the use of a lot of dynamic subdomains, and we wanted to be able to write cookies across all of the subdomains as well as for individual subdomains. In Rails 3 you could set the domain when you write to the cookie like:

cookies.signed[:awesome_cookie]     = { :value => "cookies awesomeness",           :domain => "example.com" }
cookies.signed[:awesome_cookie_sub] = { :value => "cookies awesomeness subdomain", :domain => "sub.example.com" }

Now that is a lot of extra work and looks pretty ugly. You could set the default domain for you cookies like this:

Rails.application.config.session_store :cookie_store, :key => '_app_name_session', :domain => :all

But I guess I’d rather explicitly say when a cookie is to be used across all subdomains. To this point I tld-cookies add a tld cookie jar to your Rails 3 app which sets the domain for the cookie to be the root domain, i.e. example.com.

cookies.tld.signed[:tld_cookie] = "ACROSS ALL SUBDOMAINS!!!"
cookies.signed[:tld_cookie]
 => "ACROSS ALL SUBDOMAINS!!!"

As you can see above, you use it similarly to how you would use the permanent cookie jar. The slight difference is when you want to delete the cookie you have to use the tld accessor.

So yeah, first Ruby gem. Poorly named, fun little learning project.

On Rails irb Logging

June 26, 2011 § Leave a comment

When dealing with Rails apps logging debug statements is one of first methods turned to when trying to diagnose a problem.  A lot of times logger.debug is used and will write its output to log/development.log.  This is great when you are running the server, but when you fire up the console and want to work there, you previously had two options. One is to change all of the logger.debug statements into puts so they show up in the console’s terminal window.  The other is two just keep switching back and forth between the console and a tail of the file.

Now you can toggle the app’s logger so that it writes to STDOUT.  Just throw this in your .irbrc file and call toggle_console_logging from the console’s command line.

def toggle_console_logging
  if ActiveRecord::Base.logger == Rails.logger
    l = Logger.new(STDOUT)
    l.level = Rails.logger.level
    set_logger l and return "console"
  else
    set_logger Rails.logger and return "log file"
  end
end

def set_logger(logger)
  ActiveRecord::Base.logger = logger
  ActiveRecord::Base.clear_active_connections!
end

You can check out the gist here.

Where Am I?

You are currently browsing the Rails category at The On Blog.