in

CodePrairie .NET

South Dakota .NET User Group

chrisortman

  • Rails on Windows

    I really really would like to be able to use rails on windows (not just developing, but in production). My preference would be to use linux, however the powers that be resist non microsoft os's like its nobodys business.

    My first attempt is to use the new FastCGI for IIS. I figured this is my best bet since the more Microsoft technologies that I use, the easier this is to sell to my paycheck signers.

    Setup was pretty simple, I followed these instructions (site not coming up as I write this, worked yesterday though)
    The only issues I had were making sure permissions were setup on directory where my rails app was. To keep things simple I just gave Everyone modify rights to the whole folder.

    My sample rails app is small, it calls a com object that returns xml which I return using render :xml

    My first test is to create 4 threads and request the page from each

     

    require 'open-uri'
    NUM_THREADS = 4
    
    URL = ''
    
    threads = []
    NUM_THREADS.times do |num|
      t = Thread.new(num) do |count|
        begin    
          puts "Starting thread #{count}"
          resp = open(URL)
          puts "Finished thread #{count}"
        rescue OpenURI::HTTPError => err
          puts "Failed on #{count}"
          puts err.io.readlines
        end
      end
      threads << t
    end
    
    threads.each {|t| t.join }

    So far...umm not so good. Generally with 4 requests 1 maybe 2 will succeed with the rest giving me this error:

    500 Server Error
    Error 0x80070102
    The FastCGI process exceeded configured activity timeout

    The CPU is also pegged on the server when I do this.

    So my first step was to try to up the timer for FastCGI. I found this forum post so I added this to my fcgiext.ini file

    RequestTimeout=90
    ActivityTimeout=60

    I reran the tests (after restarting IIS) and was gretted with a Timeout::Error, so I tried setting the timeout like this in my test prog.

    Finally all threads complete, but with a timeout of 90 seconds passed to open uri 3 of the 4 threads hit the timeout and had to retry in order to complete.

    I didn't expect blazing performance, but yuck, this is silly. If I run the same tests but use webrick as the server on the machine all 4 threads get a nice quick result.

  • Getting profile data from ruby (using Powershell)

    Since I'm on windows I'm running this from powershell.

    ruby -r profile myprogram.rb 2> prof.log
    

    This will turn on ruby's profiling which writes to STDERR. the 2> catches that output and puts it into a file.

    Now after you run this there will be a bunch of noise in your prof.log file, so to remove it just do

    gc prof.log | where { $_ -notmatch "^At" } | where { $_ -notmatch "^\+"} > perf.log
    
     
  • Viewing server errors with open-uri

    I've been doing some testing using open-uri but when my server returned an http 500 all I got on the ruby side was an Open::HTTPError. In order to view the actual error page returned by the server I needed to do something like this:

     

    begin    
      resp = open(URL)
      puts "Finished"
    rescue OpenURI::HTTPError => err
      puts "Failed"
      puts err.io.readlines
    end
    Posted Sep 05 2007, 06:49 AM by chrisortman with no comments
    Filed under:
  • Mocking server objects from unit tests

    So heres the problem statement:

    I'd like to be able to use WatiN tests to test my MonoRail views. But the controllers that render these views depend heavily on calling an external webservice that is large (in terms of number of methods and amount of data returned).

    Now I could setup a stub service and have my controllers call that, however I think that keeping track of the data it is supposed to return and when would be very difficult. If only I could create mock instances from my unit tests.

    Hmm, maybe I can, take a look at this nugget:

    MockRepository mocks = new MockRepository();
    AccountControllerImpl mockController = mocks.PartialMock<AccountControllerImpl>();
    using(WebServiceHost host = new WebServiceHost(mockController,new Uri("http://localhost:8901"))) {
     host.AddServiceEndpoint(typeof(IAccountController),new WebHttpBinding(), "Account.svc");
     host.Open();
    
     using (mocks.Record())
     {
      Expect.Call(mockController.Info("")).IgnoreArguments().Return(new XDocument(new XElement("Hello")));
     }
     using (mocks.Playback())
     {
      WatiN.Core.IE ie = new WatiN.Core.IE();
      ie.GoTo("http://localhost:4075/webhost/default.aspx");
      ie.Button(Find.ByValue("Submit")).Click();
    
      Assert.IsTrue(ie.ContainsText("Hello"));
     }            
    }
     

    I then tell my page I'm testing to hit the webservice at a different URL and viola it hits my mock service. To make this really usable I'd probably need to extend RhinoMocks to correctly generate the mock using only the interface (right now I have to use the Implementation class and mark it as InstanceContextMode = Single and have virtual methods)

    Neat?

    Posted Aug 17 2007, 03:49 PM by chrisortman with no comments
    Filed under: ,
  • An Inconvenient Print Job

    Missy: "Could you please print off these 2 recipies and bring them home"

    Chris: "Sure, happy to"

    Chris: "Oh wait...someone is printing 3000 (not exagerating) pages of emails and support incidents. I guess after I refill the tray, twice, so that this crap will finish printing maybe I can schedule some printer time today."

     

    I wonder if I could get this stopped if I called the EPA?

  • Connecting to SQL Server 2005 with Ruby Sequel

    So here I was wanting to query some database tables that get populated during our build process and then modify some text files / source control based on what's in the table. Seemed like a good excuse to use some ruby but low and behold ActiveRecord doesn't seem to care for the structure of our database tables.

    Enter Sequel

    Sequel is an ORM framework for Ruby. Sequel provides thread safety, connection pooling, and a concise DSL for constructing queries and table schemas.

    Sequel makes it easy to deal with multiple records without having to break your teeth on SQL.

    cool, gem install sequel

    But how to connect to SQL server? Sequel supports DBI, but I could find no tailor made examples (plenty of SQLLite, MySql and Postgres though).

    Well first things first, you'd better make sure you have DBI installed and configured correctly. If you are running using the Windows One Click installer version of ruby you are almost there, you just need to copy the ADO driver. For instructions on that see this rails howto

    I however am running under cygwin and installed the ruby cygwin package so I need to install DBI myself.

    Download the ruby-dbi source from http://rubyforge.org/projects/ruby-dbi/

    Extract your sources (tar -xvf dbi-0.1.1.tar.gz)
    cd to your new folder and do these commands
    ruby setup.rb config --with=dbi,dbd_msql,dbd_ado (don't use spaces after the commas it seems picky)
    ruby setup.rb setup
    ruby setup.rb install

    At this point you might want to jump into irb and make sure all is well with the world.
    require 'dbi' should return true.

    Ok, now let's connect to the database.
    I started by working from this post:

    Sequel version 0.1.3 has just been released. This release adds a DBI
    adapter, and thereby support for ODBC, ADO, Frontbase and other
    databases. For example:

    require 'sequel/dbi'
    DB = Sequel.open 'dbi:/odbc:my_dsn'
    DB[:my_table].all #=> returns all rows in the table as hashes
    # etc...

    As well as this:

    require 'dbi'
    
    class Server
     attr_reader :name
     def initialize(name)
      @server_name=name
      @dbh=DBI.connect("DBI:ADO:Provider=SQLNCLI;Data Source=#{name};Integrated Security=SSPI")
     end
     
     def databases
      db=Array.new
      @dbh.select_all('SELECT name FROM master.sys.databases ORDER BY 1') do | row |
       db.<< Database.new(@dbh,row[0])
      end  
      db
     end
    end
    
    class Database
     attr_reader :name
     def initialize(dbh,name)
      @dbh=dbh
      @name=name
     end
    end
    
    
    server=Server.new("localhost")
    server.databases.each {|x| p x.name}

    My first feeble attempt when something like this:

    require 'sequel/dbi'
    
    db = Sequel.open 'dbi:/ado:Provider=SQLNCLI;Data Source=(local)\\sqlexpress;Integrated Security=SSPI'

    Which failed with URI::InvalidURIError because Sequel.open wants to do some URI parsing and I did not give it a valid URI. Thankfully though I can look at source code.

    My first check is in dbi.rb. If your playing along at home it will be in /usr/lib/ruby/gems/1.8/gems/sequel-0.1.9.2/lib/sequel on cygwin and C:\ruby\lib\ruby\gems\1.8\gems\sequel-0.1.9.2\lib\sequel on windows

    The connect method of this class looks interesting

     def connect
            dbname = @opts[:database] =~ /^DBI:/ ? \
              @opts[:database] : @opts[:database] = 'DBI:' + @opts[:database]
            ::DBI.connect(dbname, @opts[:user], @opts[:password])
     end

    So all it really cares about is a value in an @opts has for :database. So to see how I can get that there I need to look at where @opts comes from. Well I'll save you the trouble and tell you it comes from self.connect in database.rb (connect is aliased to open btw) Have a look at this snippet:

    # Converts a uri to an options hash. These options are then passed
        # to a newly created database object.
        def self.uri_to_options(uri)
          {
            :user => uri.user,
            :password => uri.password,
            :host => uri.host,
            :port => uri.port,
            :database => (uri.path =~ /\/(.*)/) && ($1)
          }
        end
        
        # call-seq:
        #   Sequel::Database.connect(conn_string)
        #   Sequel.connect(conn_string)
        #   Sequel.open(conn_string)
        #
        # Creates a new database object based on the supplied connection string.
        # The specified scheme determines the database class used, and the rest
        # of the string specifies the connection options. For example:
        #   DB = Sequel.open 'sqlite:///blog.db'
        def self.connect(conn_string, more_opts = nil)
          uri = URI.parse(conn_string)
          c = @@adapters[uri.scheme.to_sym]
          raise SequelError, "Invalid database scheme" unless c
          c.new(c.uri_to_options(uri).merge(more_opts || {}))
        end

    Looking at this it seems like connect and hence open will take an optional second hash that is merged with what gets parsed from the URI. This is promising because I had seen several examples that just passed a scheme to open so I thought I'd try this

     
    require 'sequel/dbi'
    db = Sequel.open 'dbi:/ado', {:database => 'DBI:ADO:Provider=SQLNCLI;' +
                                              'Data Source=(local)\\sqlexpress;' +
                                              'Integrated Security=SSPI'}

    Hey, that didn't give me an error, in fact it gave me a Sequel::DBI::Database object. Surely it won't work, I'd better check.

    db.execute("SELECT Name from master.sys.databases order by 1").fetch_all

    Well look at that it did work. And there you have it. You've just connected to SQLExpress 2005 with sequel. Happy hunting.

     
    Posted Aug 10 2007, 06:37 AM by chrisortman with 2 comment(s)
    Filed under:
  • Ooo Verizon is l33t

    Look ma, verizon is hip and cool because they're up on my lingo. I wonder what cat they had build their website.

    See if I enter teh text "later" into their text box and click a button it will instantly transform it into cool l33t speak.

    Before:

     

    After:

  • Generating stored procedures to multiple files - SQL2005

    Remember that functionality in Enterprise Manager that let you generate scripts for all your stored procedures to multiple files? I guess no one used that feature because in SQL Management Studio (2005) that feature was removed.

    I found some information here that says it was put back in SP2. However SP2 is a 292MB download. So I started the download, but while it was downloading I figured I'd just write my own script to do this for me.

    I saw some forum posts saying you could do this all using SQL, but that just sounded boring so I thought I'd use Ruby instead.

      1 require 'ftools' 
      2 File.makedirs 'split_sp' 
      3 
      4 File.open('storedprocs.sql','r') do |file| 
      5    
      6   text = file.read 
      7 
      8   text.scan(/CREATE PROCEDURE \[dbo\]\.\[(API_\w+)\]\s*(.*?)'\s*^END$\s*^GO$/m) do |match| 
      9     File.open("split_sp/#{match[0]}.sql",'w') do |write_file| 
     10       write_file.write "CREATE PROCEDURE [dbo].[#{match[0]}]\n" 
     11       write_file.write match[1] 
     12     end 
     13   end 
     14 
     15 end 
    
    Code syntax highlighting by VIM captured with ScreenShot script
    Posted Jul 24 2007, 06:06 PM by chrisortman with no comments
    Filed under:
  • Good Installer Experience

    Jeff Atwood points out some definciencies in the install process for many of today's applications. Having just installed Jing yesterday I wanted to point out how pleasant I found their installer.

     

    Click the check box and then the install button and it's done.

    Not only is the install a breeze, but the app is quite slick as well.

    Posted Jul 20 2007, 09:18 PM by chrisortman with 1 comment(s)
    Filed under:
  • Taking SharedView for a test drive

    I needed to do some training remotely today. Typically I would use GotoMeeting for this, but I have been wanting to give SharedView a try and see how it worked.

    You can grab the download here http://r.office.microsoft.com/r/rlidSV?clid=1033&p1=1&p2=download_msi

    Setup was nice and simple. Once it's installed you enter your windows live ID and you're ready to go.

    There is an option to preview the window you are currently showing which I like.

    Other than app sharing I didn't get too deep into the functionality. I did allow another user to take control of the session for a while. When I move my mouse it would affect him which I don't like. I'd like to be able to give control while I do some other work on my other monitor.

    My coworker that took control for a while thought performance was "herky-jerky" so hopefully that can get a little smoother.

    All in all though I liked what I saw.

  • Visual Studio template information is out of date?

    What? Good question.

    In the middle of working I thought I'd add a new class to my project when low and behold I get a dialog box:

    No Visual Studio template information found. Seel the application log in Event Viewer for more details.

    Ok, so I open up event viewer and find this

    Event Type: Warning
    Event Source: Visual Studio - VsTemplate
    Event Category: None
    Event ID: 1
    Date: 7/11/2007
    Time: 4:31:56 PM
    User: N/A
    Computer:
    Description:
    The Visual Studio template information is out of date. Regenerate the templates by running 'devenv /installvstemplates' or reinstalling Visual Studio. Note: corrective action requires Administrator privileges.

    For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

    Except a lot of them. I have no idea why this suddenly started happening. Well let's check google

    http://traversee.spaces.live.com/blog/cns!660EC1EE75BC1F77!142.entry

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=52248&SiteID=1

    http://geekswithblogs.net/jeelz/archive/2007/04/03/110665.aspx

    Sigh....I'll probably just run the command line as it seems to fix it. Hopefully it doesn't break ViEmu or R# or TD.Net.

  • innerHTML does not work in IE select boxes

    Doing some MonoRail work I have a JS view that needs to update the options in a select box. Things had been working swimminly in Firefox, but then I tested in IE.

    Note to self: BUG: Internet Explorer Fails to Set the innerHTML Property of the Select Object

     

    I searched around and found this commit to the prototype code, but how do I get this change?

    I see a change to the change log in the branch that contains this line

    * Make Element#update work for SELECT tags in IE and Opera. [Tobie Langel]

     

    My next step is then to check the change log on the trunk using svn blame

    Where I see that this branch was merged with the trunk in revision 6725. I wonder what revision the latest and greatest code is based off?

    svn info http://svn.rubyonrails.org/rails/spinoffs/prototype/tags/rel_1-5-1

    Path: rel_1-5-1
    URL: http://svn.rubyonrails.org/rails/spinoffs/prototype/tags/rel_1-5-1
    Repository Root: http://svn.rubyonrails.org/rails
    Repository UUID: 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
    Revision: 7180
    Node Kind: directory
    Last Changed Author: sam
    Last Changed Rev: 6643
    Last Changed Date: 2007-04-30 23:13:14 -0500 (Mon, 30 Apr 2007)

    Nope not what I want. Guess I'll take a chance on running from trunk.

    mkdir prototype
    cd prototype
    svn co http://svn.rubyonrails.org/rails/spinoffs/prototype/trunk .
    rake dist

    copy dist\prototype.js ....

    See if my problem is fixed.....Eureka!

  • Ruby include and extend

    Nice write up by Marc about ruby extend and include. He succinctly explains what each of the methods do, however I think his explanation is for a ruby programmer, not a C# programmer trying to learn more about ruby. Upon further research I found another post that made it quite clear for me.

    The extend method will mix a module’s methods at the class level. The method defined in the Math module can be used as a class/static method.

    The include method will mix a module’s methods at the instance level, meaning that the methods will become instance methods.

    It is much easier for me to relate that to what I am familiar with in C#.

    Posted Jul 07 2007, 09:23 AM by chrisortman with 6 comment(s)
    Filed under:
  • Here's a new one

    Just got this error when trying to invoke MSBUILD from the VS2005 command prompt.

    MSBUILD : warning MSB4056: The MSBuild engine must be called on a single-threaded-apartment.
    Current threading model is "MTA". Proceeding, but some tasks may not function correctly.

    It was working fine, and I have no idea what changed. I retried it and it worked fine the second time....odd

    Posted Jul 05 2007, 03:50 PM by chrisortman with no comments
    Filed under: ,
  • How well does Resharper know me?

    I was in the process of setting up another unit test and realized...I really should just make a Resharper template for this. As I went to create the template I saw one setup exactly as I would want it which is like this:

     

    namespace $NAMESPACE$ 
    {
        using MbUnit.Framework;
        using Rhino.Mocks;
        
        [TestFixture]
        public class $CLASS$ { $END$ }
        
    }

     

    Now, I don't remember at all creating this...so I'm wondering did I create it a while ago and am just having a friday brain fart, or is Resharper really that smart?

    Posted Jun 15 2007, 06:53 AM by chrisortman with no comments
    Filed under:
More Posts « Previous page - Next page »
Powered by Community Server (Commercial Edition), by Telligent Systems