Passing Additional Arguments to FactoryGirl Factories

I wanted to create a factory that would link various states to my model, but from a specified list instead of automatically generated. I discovered that these are transient attributes:

FactoryGirl.define do
  factory :business do
    name "MyString"
#
#
#
    trait :with_states do
      ignore do
        state_list []
      end
      # add association equal to state code
      after(:create) do |business, evaluator|
        evaluator.state_list.each do |state_code|
          business.states << State.find_by(state_code: state_code)
        end
      end
    end
  end
end

This factory can now be called with:

  FactoryGirl.create(:business, :with_states. state_list: %w(KY IN))

Of course, now that I'm passing in the attributes, I can probably just use:

FactoryGirl.define do
  factory :business do
    name "MyString"
#
#
#
    ignore do
      with_states []
    end
    # add association equal to state code
    after(:create) do |business, evaluator|
      evaluator.with_states.each do |state_code|
        business.states << State.find_by(state_code: state_code)
      end
    end
  end
end

and then the call is even simpler:

  FactoryGirl.create(:business, with_states: %w(KY IN))

Rails 4, Empty Hashes, Strong Parameters, exception_notification and filtering out my new ActionController::ParameterMissing errors

I'm finally coming around to the "strong parameters" pattern encouraged (required?) in Rails 4.

One thing that I did notice was that missing the base parameter raised an ActionController::ParameterMissing error. I discovered this via controllers tests generated by rspec-rails when I created a controller scaffold, which generates tests for "Invalid Params":

In the controller spec:

describe "with invalid params" do
  it "re-renders the &#039;new&#039; template" do
    # Trigger the behavior that occurs when invalid params are submitted
    User.any_instance.stub(:save).and_return(false)
    post :create, {:user => {  }}, valid_session
    response.should render_template("new")
  end 
end

In the controller:

  def user_params
    params.require(:licensee).permit(:parameter1, :parameter2)
  end

Despite the fact that params[:licensee] exists, the empty hash triggers the ActionController::ParameterMissing error. That's fine. I can expect { post :create, {:user => { }}, valid_session }.to raise_error(ActionController::ParameterMissing), or eliminate the test altogether.

However, with exception_notifier, I don't really want to be notified about these errors, so I configured my environment files to filter this exception (and also CanCan::AccessDenied).

  config.middleware.use ExceptionNotification::Rack,
    :ignore_exceptions => %w(CanCan::AccessDenied ActionController::ParameterMissing) + ExceptionNotifier.ignored_exceptions,
    :email => {
      :email_prefix => "[#{Rails.env}] project name exception: ",
      :sender_address => %{"Exception Notifier" <exceptions@example.com>},
      :exception_recipients => [ `git config user.email`.chomp ]
   }

Bundler reports errors across several different projects when running `bundle install`

When running bundle install, I was getting the following for several projects:

Bundler gave the error "Could not find {gem_name_version} in any of the sources" while processing "{project_path}/Gemfile". Perhaps you forgot to run "bundle install"?
.
.
.

I found someone else was having the same problem too.

In my case, I had uninstalled and reinstalled a version of ruby using rbenv and began seeing this error reported for every project using the same ruby version as the one I had uninstalled and reinstalled. I haven't exactly gotten to the bottom of why this happens, but going around and running bundle install in each of the project directories got rid of the error.

method_missing: undefined method `increment_open_transactions` database_cleaner

When using database_cleaner (0.9.1) with rails (4.1.0)

{my home path}/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/activerecord-4.1.0/lib/active_record/dynamic_matchers.rb:26:in `method_missing': undefined method `increment_open_transactions' for ActiveRecord::Base:Class (NoMethodError)
    from {my home path}/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/database_cleaner-0.9.1/lib/database_cleaner/active_record/transaction.rb:13:in `start'
    from {my home path}/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/database_cleaner-0.9.1/lib/database_cleaner/base.rb:73:in `start'
    from {my home path}/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/database_cleaner-0.9.1/lib/database_cleaner/configuration.rb:75:in `block in start'
    from {my home path}/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/database_cleaner-0.9.1/lib/database_cleaner/configuration.rb:75:in `each'
    from {my home path}/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/database_cleaner-0.9.1/lib/database_cleaner/configuration.rb:75:in `start'

Somehow we were using an old version of database_cleaner,

gem "database_cleaner",   "~> 0.9.1"

because the fix was authored a year ago.

gem "database_cleaner", "~> 1.2.0"

I guess that will teach me to dig too deeply before simply trying the latest version of a gem.

Getting Fast File Finder Functionality Out of Vim

Problem:

All of these other editors have handy functionality to quickly find a file

Solution:

ctrlp.vim is a plugin that allows you to do that.

The plugin's page has full instructions, but the most important detail after work done in yesterday's post to declutter my vim windows:

After pressing Ctrl-P, use <c-t> or <c-v>, <c-x> to open the selected entry in a new tab or in a new split.

Otherwise, you'll end up replacing your file in the currently open window with the file you're opening.

Avoiding Scattered Vim Windows in MacVim

Problem:

I open too many windows in vim, which get buried in the clutter on my Mac OS X desktop.

Solution:

Open files in MacVim in an existing window using a tab

mvim --remote-tab new_file_to_open.rb

Open files in MacVim in an existing window using a split

mvim --remote-send ":split `pwd`/new_file_to_open.rb<CR>"

I packaged this in a zsh script called spvim. It will only handle relative paths for now, which in 99% of what I'm trying to open, anyway.

for i in $*
do
  mvim --remote-send ":split `pwd`/$i<CR>"
done

Open files in MacVim in an existing windows using a vertical split:

mvim --remote-send ":vsplit `pwd`/new_file_to_open.rb<CR>"

I packaged this in a zsh script called vspvim:

for i in $*
do
  mvim --remote-send ":vsplit `pwd`/$i<CR>"
done

Sources/Learning More:

(I believe most of these options are available in vim as well... I actually have gvim aliased to mvim because I'm still in the habit of calling gvim).

usage: vim [arguments] [file ..]       edit specified file(s)
   or: vim [arguments] -               read text from stdin
   or: vim [arguments] -t tag          edit file where tag is defined
   or: vim [arguments] -q [errorfile]  edit file with first error

Arguments:
   --           Only file names after this
   -g           Run using GUI (like "gvim")
   -f  or  --nofork Foreground: Don&#039;t fork when starting GUI
   -v           Vi mode (like "vi")
   -e           Ex mode (like "ex")
   -E           Improved Ex mode
   -s           Silent (batch) mode (only for "ex")
   -d           Diff mode (like "vimdiff")
   -y           Easy mode (like "evim", modeless)
   -R           Readonly mode (like "view")
   -Z           Restricted mode (like "rvim")
   -m           Modifications (writing files) not allowed
   -M           Modifications in text not allowed
   -b           Binary mode
   -l           Lisp mode
   -C           Compatible with Vi: &#039;compatible&#039;
   -N           Not fully Vi compatible: &#039;nocompatible&#039;
   -V[N][fname]     Be verbose [level N] [log messages to fname]
   -D           Debugging mode
   -n           No swap file, use memory only
   -r           List swap files and exit
   -r (with file name)  Recover crashed session
   -L           Same as -r
   -A           start in Arabic mode
   -H           Start in Hebrew mode
   -F           Start in Farsi mode
   -T <terminal>    Set terminal type to <terminal>
   -u <vimrc>       Use <vimrc> instead of any .vimrc
   -U <gvimrc>      Use <gvimrc> instead of any .gvimrc
   --noplugin       Don&#039;t load plugin scripts
   -p[N]        Open N tab pages (default: one for each file)
   -o[N]        Open N windows (default: one for each file)
   -O[N]        Like -o but split vertically
   +            Start at end of file
   +<lnum>      Start at line <lnum>
   --cmd <command>  Execute <command> before loading any vimrc file
   -c <command>     Execute <command> after loading the first file
   -S <session>     Source file <session> after loading the first file
   -s <scriptin>    Read Normal mode commands from file <scriptin>
   -w <scriptout>   Append all typed commands to file <scriptout>
   -W <scriptout>   Write all typed commands to file <scriptout>
   -x           Edit encrypted files
   --remote <files> Edit <files> in a Vim server if possible
   --remote-silent <files>  Same, don&#039;t complain if there is no server
   --remote-wait <files>  As --remote but wait for files to have been edited
   --remote-wait-silent <files>  Same, don&#039;t complain if there is no server
   --remote-tab[-wait][-silent] <files>  As --remote but use tab page per file
   --remote-send <keys> Send <keys> to a Vim server and exit
   --remote-expr <expr> Evaluate <expr> in a Vim server and print result
   --serverlist     List available Vim server names and exit
   --servername <name>  Send to/become the Vim server <name>
   --startuptime <file> Write startup timing messages to <file>
   -i <viminfo>     Use <viminfo> instead of .viminfo
   -h  or  --help   Print Help (this message) and exit
   --version        Print version information and exit

Java code to test if a string is a valid java identifier.

public class IdentifierTest {
 
    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) {
        for(String arg : args) {
            boolean start = true;
            boolean validIdentifier = true;
            arg.toCharArray() 
            // commenter pointed out my error
            //for(byte b : arg.getBytes()) {
            for(char b : arg.toCharArray()) {
                if(start) {
                    validIdentifier = validIdentifier && Character.isJavaIdentifierStart(b);
                    start = false;
                } else {
                    validIdentifier = validIdentifier && Character.isJavaIdentifierPart(b);
                }
            }
            System.out.println("Identifier ""
            + arg + "" is "
            + (validIdentifier ? "" : "not ")
            + "valid");
        }
    }
}

Output:
>java IdentifierTest Test $ds ds$ 2" is not valid

Haskell resources

In order to reclaim some of our programming mojo that has waned from years of maintenance programming and meetings, a couple of us programmers decided to go and try to learn a completely new language--Haskell.

I think this expedition was spurred by a blog post titled Great resources to learn Haskell. I'm as much a math geek as I am a computer geek--I competed on my high school Math Team--so a functional programming language is a natural fit for my hobbyist interest.

Resources that I've used so far:

Learn You a Haskell for a Great Good! is an entertaining introduction to Haskell that reminds me a lot of Why's (Poignant) Guide to Ruby, but without the comic strip story telling.

Haskell for C Programmers is a online book that resonates well with me, because of my deep roots in C programming.

Trying to dig up IT relevant podcasts

Any suggestions?

InfoWorld Podcasts: These look promising...

  • Infoworld Daily - includes a general tech news segment which is repeated in the NetworkWorld 360 podcast as well.
  • The Virtualization Report
  • Storage Sprawl
  • The SOA Report
  • ...a few discontinued ones are out there, too.
Enterprise 2.0 podcasts - looks like recordings from a conference? I'll have to download and check them out tonight. Not as promising as the Infoworld ones. I see that a lone spammer has managed to post spam comments in "response" to a few of the links.
NetworkWorld podcasts: Again, some promise here.
  • NetworkWorld's Twisted Pair (this sounds more like entertainment, but possibly relevant news)
  • NetworkWorld Panorama
  • NetworkWorld 360 - includes a general tech news segment.
  • Voices from the IT Roadmap
  • NetworkWorld's Newsmaker of the Week
  • Forrester Fundamentals
  • Network Downtime (entertainment)
  • Converging on Microsoft
  • Cisco News and Reviews
  • JavaWorld's Java Technology Insider
  • LinuxCast