Saturday, 26 June 2010

formelement is null in ASP.Net MVC Validation

I'm buidling a really simple MVC application as a demo and I've been getting a Javascript "formelement is null" error. A quick google throws up a bunch of 'make sure you add the correct .js files" but I had all those
    
    
    
Turns out that I had added a Master page using a template and thet template contains a
element. This screwa up the validation. Removing that tag fixes the problem

Posted by kevin at 7:31 PM in General

Tuesday, 18 August 2009

Microsoft Mouse Preventing Screen Saver Working

I've just installed Windows 2008 R2 and I could not get the screen saver or power management to work. Turns out I needed to install the correct drivers for my mouse. This is the Wireless Laser 5000, the drivers can be found here.

Posted by kevin at 8:53 PM in General

Thursday, 16 April 2009

Problem When Upgrading From Rails 2.2.2 to 2.3.2

I've just installed the latest Active* gems to move my Rails install to 2.3.2. When I ran a console I got the following error

Loading development environment (Rails 2.3.2)
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:443:in `load_missing_constant':NameError: uninitialized constant ApplicationController 

I googled this and found a couple of posts on the issue but nothing obvious that I was doing. After generating a 2.3.3 app and comparing files the solution was obvious and easy. I 2.2.2 the ApplicationController class is in a file called Application.rb, in 2.3.2 this has changed to application_controller.rb. Changing the file name has fixed my problem.

Posted by kevin at 6:37 PM in Ruby

Thursday, 2 April 2009

DevWeek 2009 Demos

Are now available on the Rock Solid Knowledge site. I've upload the 'So you think you now JavaScript', 'Design for Testing' and Day of 'Ruby and Rails' talks. Andy's already put up the 'Day of Patterns' and 'Patterns Dartboard' talks

Posted by kevin at 2:19 PM in General

Wednesday, 1 April 2009

Ruby idioms in ASP.Net MVC

In Rails there is a mechanism by which you can mimic variadic methods (Ruby also supports true variadic methods) by treating the last parameter as a hash. I can write a function definition like this

def pass_a_hash(s, h) 
  puts s
  h.each { |key, value| puts "#{key} => #{value}"} if h.class == Hash  
end

and call it either like

pass_a_hash "kevin", {:a => "b", :c => "d"}
or
pass_a_hash "kevin", :a => "b", :c => "d"
either way this prints
kevin
a => b
c => d

The second style is much neater, it hides the use of the hash and instead makes it seem like we are using named parameters. This is used all over Rails, especially on web pages where you need to specify things such as controllers and actions. You will often see code like:

<%= link_to "Add", :action => :add, :controller => :students %>

Here we are calling the 'link_to' method passing a string and a hash of options, just like above

Microsoft (bless 'em) have tried to mimic this in ASP.Net MVC by letting you can write code similar to the 'link_to' Rails method. On an ASP.Net view you can do something like:

<%= Html.RouteLink("Add", new {action = "add", controller = "students"}) %>

And this adds a link to the page with the text "Add" and a url something like http://server.com/students/add. This is similar to ActionLink and they both eventually call into a method called GenerateRouteLink. In the ASP.Net case the second parameter is not a hash (oh for first class hashes in C#) but an instance of an anonymous class. Using Reflector we can see what this method does.

Internally RouteLink creates a RoutedDictionary passing the anonymous instance as a parameter to its constructor

    return htmlHelper.RouteLink(linkText, new RouteValueDictionary(routeValues));

The RouteValueDictionary constructor looks like this

public RouteValueDictionary(object values)
{
    this._dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
    this.AddValues(values);
}

and AddValues does this:

private void AddValues(object values)
{
    if (values != null)
    {
        foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
        {
            object obj2 = descriptor.GetValue(values);
            this.Add(descriptor.Name, obj2);
        }
    }
}

public void Add(string key, object value)
{
    this._dictionary.Add(key, value);
}

So AddValues uses reflection to build a dictionary of name/value pairs

Just like in Rails, when the element is rendered this dictionary is interrogated and the values used to build the URL.

Neat, but still more ceremony than in Ruby!

Posted by kevin at 5:45 PM in Ruby

Ruby Essence vs Ceremony

Last week at DevWeek Tim Ewald and I tried to show some of the elegance of Ruby and I'd like to try and repeat that example here.

We started with a Lion class in honour of the news story that week about "Christian the Lion" (hey, look it up yourselves!). The class is very simple

class Lion

  attr_accessor :message, :name

  def speak
    @message
  end

  def to_s
    "#{self.name} says #{self.message}"
  end

  @@lions = {}

  def self.create message, name
    if @@lions[name] == nil
      @@lions[name] = Lion.new(message, name)
    end
    return @@Lions[name]
  end

  def initialize(message, name)
    @message = message
    @name = name
  end

end

The bit we care about is the self.create method. The idea here is that we provide a function to only allow the creation of one lion with any given name (this was a demo so it didn't need to make sense). To do this there is a class level dictionary (a static) in which to store new lions. We only add lions to this dictionary if they are unique, otherwise we return an existing lion. The code as it is written is not very Ruby-ish, it reads more like C++, C# or Java code than Ruby and that's what I'd like to change.

The first step is to remove the 'return' keyword. In Ruby the last statement in a method is the return value so we can change the code to look like this:

def self.create message, name
  if @@lions[name] == nil
    @@lions[name] = Lion.new(message, name)
  end
  @@Lions[name]
end

The 'if' statement isn't very idiomatic either and in Ruby this can be reduced to

def self.create message, name
  @@lions[name] = Lion.new(message, name) if @@lions[name] == nil 
  @@lions[name]
end

We're still not quite there though. Ruby (like C#) has a 'null co-alescing' operator, which lets me say "if 'x' is not null, use it, else do 'y'", and I can rewrite the above 'if' using this operator (|| in Ruby). It also means I can do away with the final return statement

def self.create message, name
  @@lions[name] || @@lions[name] = Lion.new(message, name)
end

Which says, if @@lions[name] is not null return the value, else assign Lion.new to @@lions[name] and return that value

One line to do what it would take four lines to do in other languages and no keywords. As my friend Stu Halloway would put it, essence over ceremony!

Posted by kevin at 5:34 PM in Ruby

Friday, 27 March 2009

Dev Week 2009

Just finished DevWeek 2009

It's been another great week. Spent time with people I haven't seen for a while. I've enjoyed giving the talks and hope you have enjoyed listening to them. I always love spending time hanging out the speakers, there are so many really smart people there. Just spent a day with Tim Ewald - it always blows me away how good a presenter Tim is and how much he knows, this time on Ruby and Rails.

Hopefully I'll be back for Software Architect in Sept/Oct and at DevWeek next year.

Posted by kevin at 6:10 PM in Net

Monday, 16 March 2009

VSTS Load/Web Testing and Browser Definitions

When you add a VSTS load test or when you configure a web test you can specify the browser(s) to use for the test. The data for each type of browser is held in files with a .browser extension in the C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\Templates\LoadTest\Browsers directory.

You can add your own browsers to this list by copying and renaming one of these files and changing the details within the file. The files are XML so this is easy to do, they look something like this

<Browser Name="Netscape 6.0">
  <Headers>
    <Header Name="User-Agent" Value="Mozilla/5.0 (Windows; U; Windows NT 5.0; en; rv:1.0) Netscape/6.0" />
    <Header Name="Accept" Value="image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*" />
    <Header Name="Accept-Language" Value="{{$IEAcceptLanguage}}" />
    <Header Name="Accept-Encoding" Value="GZIP" />
  </Headers>
</Browser>

Remember to change the Name attribute on the Browser element otherwise you'll see the same browser listed twice inside visual studio.

After making the changes you will need to re-start Visual Studio to see your new browser listed.

Posted by kevin at 7:08 AM in Net

Friday, 12 December 2008

Ruby 1.9 and Active Record

I'm trying to use ActiveRecord outside of Rails and with Ruby 1.9. I kept getting an error

/opt/local/lib/ruby1.9/gems/1.9.1/gems
        /activerecord-2.2.2/lib/active_record/base.rb:394:in `<class:Base>': 
        undefined method `cattr_accessor' for ActiveRecord::Base:Class 
        (NoMethodError)
	from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord-
        2.2.2/lib/active_record/base.rb:391:in 
        `<module:ActiveRecord>'
	from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord-           
        2.2.2/lib/active_record/base.rb:4:
        in `<top (required)>'
	from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord-
        2.2.2/lib/active_record.rb:34:
        in `require'
	from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord-
        2.2.2/lib/active_record.rb:34:
        in `<top (required)>'
	from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord-
        2.2.2/lib/activerecord.rb:1
        :in `require'
	from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord-
        2.2.2/lib/activerecord.rb:1:
        in `<top (required)>'
	from SimpleTest.rb:2:in `require'
	from SimpleTest.rb:2:in `
'

so and undefined method cattr_accessor in ActiveRecord::Base.

Trying the same code in 1.8 worked fine. After much searching I discovered that ActiveSupport had to be installed. This looked like it was installed when I installed ActiveRecord, but it possibly wasn't a complete install.

so after a

sudo gem install ActiveSupprt

I'm good to go

Posted by kevin at 11:51 AM in Ruby

Tuesday, 2 December 2008

Running the latest version of Rails

By this I mean running the latest Gem version not Edge. In config/environment.rb is a line that says something like

RAILS_GEM_VERSION = '2.1.0' unless defined? RAILS_GEM_VERSION

You can either set this to a specific version or if you want to run off the latest installed (Gem) version then simply comment out the line

Posted by kevin at 5:39 PM in Ruby

Monday, 10 November 2008

Rails - Routing

It's been a while since my last post, that's a mixture of being at PDC and battling with Rails routing so that I understand it better and so that I can bend it to my will! I've finally got something working to my liking but it's taken a while.

Routing is a huge part of Rails and, like most things in Rails, I'm not going to be able to do it full justice in this post.

Rails provides a flexible and convenient routing mechanism, which sounds like marketing speak but is true. If the application uses RESTful routes then much of the work is done for it, although only if you want to work exactly the way Rails expects, otherwise you have to understand the routing to get it to fit into your scheme.

Routing information is stored in a file called routes.rb which is in the config directory. The route data 'draws' routes by mapping from resources to HTTP verbs/URLs and vice versa. This means that for a given HTTP verb (GET say) and a given URL ("/blog/foo") there is a map to a specific controller/action pair.

When a controller is generated from a script an entry is automatically placed in /config/routes.rb. For a 'blogs' controller the entry would look like this:

map.resources :blogs

This entry sets up a bunch of routes for the "blogs" controller in this application. There are several ways to see these routes. The generated BlogsController class will have a set of commented methods that show which URLs will be directed to which methods (shown here but shortened for convenience)

  # GET /blogs
  # GET /blogs.xml
  def index

  # GET /blogs/1
  # GET /blogs/1.xml
  def show

  # GET /blogs/new
  # GET /blogs/new.xml
  def new

  # GET /blogs/1/edit
  def edit

  # POST /blogs
  # POST /blogs.xml
  def create

  # PUT /blogs/1
  # PUT /blogs/1.xml
  def update

  # DELETE /blogs/1
  # DELETE /blogs/1.xml
  def destroy

However this does not tell the whole story, for example these routes have names and these names can be used in your code to add references to the URLs.

Another way to look at the roots available is to get Rails to list them. One way of doing this is to execute the rake routes command:

$ rake routes

                    blogs GET    /blogs                       {:controller=>"blogs", :action=>"index"}
          formatted_blogs GET    /blogs.:format               {:controller=>"blogs", :action=>"index"}
                          POST   /blogs                       {:controller=>"blogs", :action=>"create"}
                          POST   /blogs.:format               {:controller=>"blogs", :action=>"create"}
                 new_blog GET    /blogs/new                   {:controller=>"blogs", :action=>"new"}
       formatted_new_blog GET    /blogs/new.:format           {:controller=>"blogs", :action=>"new"}
                edit_blog GET    /blogs/:id/edit              {:controller=>"blogs", :action=>"edit"}
      formatted_edit_blog GET    /blogs/:id/edit.:format      {:controller=>"blogs", :action=>"edit"}
                     blog GET    /blogs/:id                   {:controller=>"blogs", :action=>"show"}
           formatted_blog GET    /blogs/:id.:format           {:controller=>"blogs", :action=>"show"}
                          PUT    /blogs/:id                   {:controller=>"blogs", :action=>"update"}
                          PUT    /blogs/:id.:format           {:controller=>"blogs", :action=>"update"}
                          DELETE /blogs/:id                   {:controller=>"blogs", :action=>"destroy"}
                          DELETE /blogs/:id.:format           {:controller=>"blogs", :action=>"destroy"}

The format is probably screwed as you look at this but hopefully it's still easy to work out what is going on. This lists the VERB/URL mapping to Controller/action, in this case the routes are only shown for the "blogs" resource, the actual listing is much longer and contains all resources as well as the default routing behaviour. The list is fairly straightforward, it shows the name of the route (if there is one), the HTTP verb, the URL and the controller/action these map to. For example the 'blog' named route says that sending a URL of the form blog/[:id] (e.g. /blogs/1) with the HTTP GET verb results in a call to the blogs controller's show method. In this case the value '1' at the end of the URL will be available as the :id value in the params collection. Notice that not all routes are /controller/action style, but that some simply rely on /controller and the HTTP verb to work out the method to call.

The names of the routes are very useful. For example in the above there are routes named 'blogs', 'blog' and 'new_blog' amongst others. These names can be used to display a URL for that route. As an example in views/blogs/index.html.erb there is a line like this:

<%= link_to 'New blog', new_blog_path %>

that says to use the path generated from the new_blog route to get the URL to display.

This is all well and good, and nice and easy to use and if you simply want to use the Rails conventions then you are good. However there are going to be occasions when simply using the defaults does not work. Luckily, for those cases the routing infrastructure is extensible. In the case of this blog I wanted to do two things, I wanted to support multiple blog authors, and I wanted blog IDs to be friendlier. In fact both these things are related, although I've only tackled the first issue at the moment, but the second issue is resolvable using a similar mechanism.

These issues are to do with the way that Rails identifies resources. It does this via the 'id' primary key. So to get to a blog you would send a GET to http://localhost/blogs/1 where blogs is the name of the controller and 1 is the id of the blog. This isn't ideal for a user. The id is an internal representation that the database uses to identify the blog. An end user doesn't want to say 'go to blog 1', they want to say "kevin's blog" or "harry's blog". To support that blogs should have 'nicknames' and these nicknames then get used to identify the blog, meaning that the url becomes http://localhost/blogs/kevin. Similarly with blog entries, the URL to the entry should include the nickname of the blog and maybe the title of the entry. So something like http://localhost/blog/kevin/my-title rather than http://localhost/blog_entry/1/1, where 'blog-entry' is the name of the controller, the first '1' is the id of the blog and the second '1' is the id of the entry. Fixing this requires several steps some of which I'll cover here. At this point I've not fully converted the code to produce URLs like the above but I'm a large step towards it. That step means not relying on the default routes drawn for REST based controllers and rewriting some of the usage of named routes in the controller and views.

The first thing I wanted to prevent was the user having to use the 'blog_entry' name for the controller. This is an internal representation and, as a user, I don't like the name. I wanted something shorter, so I've chosen 'blog' as the alias for the controller, you can guarantee that at some point in the future I'll have come up with something else! I also want to use a 'nickname' as an identifier to show whose blog entries we were looking at. This meant I wanted a URL something like http://localhost/blog/kevin to retrieve all blog entries for "kevin". I did this by modifying routes.rb.

In routes.rb I took out the entry for map.resources blog_entries and added explicit entries for routing. The entries look like this:

  map.blog_entries 'blog/:nickname',
            :controller => "blog_entries",
            :action => "index",
            :conditions => {:method => :get}

  map.connect 'blog/:nickname',
            :controller => "blog_entries",
            :action => "create",
            :conditions => {:method => :post}

  map.new_blog_entry 'blog/:nickname/new',
        :controller => "blog_entries",
        :action => "new",
        :conditions => {:method => :get}

There are many more entries and there are also also entries for formatted output (basically, I did a rake routes, copied and pasted the code and edited it). The above entries show a number of things: there are two named routes (blog_entries and new_blog_entry), and one unnamed route (the call to map.connect). As an aside notice the the named routes are named with a call to map.some_function. This function does not exist and shows the power of Ruby as a language. Internally the map class will override the method_missing method to add this named route. The routes specify the HTTP verb, the controller to call and the action to use on that controller. Notice that all the routes all specify an extra paramter, :nickname. This will be part of the URL and be passed into code in the params collection in much the same way that :id is passed. Once these routes have been defined you can then use them in code.

The nickname is associated with an individual blog and through that with the entries in that blog. This means that to use the nickname we always need to load the blog associated with it. In the BlogEntriesController class I added a "before_filter" entry. before_filters are code that gets executed before the action. The before_filter looks like this:

  before_filter :get_associated_blog

  protected
  def get_associated_blog
    if params[:nickname]
      @blog = Blog.find_by_nickname(params[:nickname])
    else
      @blog = nil
    end
  end

This finds the associated blog (if it can) and stores it as a member variable of the class. The action is then called, and the action can decide what to do if the blog hasn't been found which will typically be to redirect somewhere.

Modifying routing - recreate mapped routes; unnamed and named; use link_to with params to generate url! Needed to add another column: ruby script/generate migration add_usershortname_to_user user_id:string then migrate: rake db:migrate

  def show
    if @blog
      # work here
    else
      redirect_to(:controller => "blogs")
    end
  end

This is nice and easy. However you can also use the nickname to build URLs. For example when we create a new blog entry we want to re-direct back to the blog for this nickname. The code for that looks something like:

  def create
    
    if @blog       
        @blog_entry = BlogEntry.new(params[:blog_entry])

          if @blog_entry.save
            flash[:notice] = 'BlogEntry was successfully created.'
            format.html { redirect_to(:nickname => @blog.nickname) }

Notice that the redirect_to uses the nickname. This ensures that we redirect back to http://localhost/blog/kevin rather than http://localhost/blog.

Another place the nicknames are used are in the views. If we use the standard Rails mapping for routes then we can use the helper functions directly, something like:

<%= link_to 'Edit', edit_blog_path(@blog) %> |
<%= link_to 'Back', blogs_path %>

Where we use the default 'blogs' routing to build URLs for an edit entry and to get to the blogs controller's index page. Now that we've amended the blog_entry routes though we also need to track down and edit the uses of link_to (and url_for and any other use of these paths) in the view files. The primary change is to add the :nickname value to all the links. This is why we made @blog an instance variable in the BlogEntriesController class, so that it would be available in the views. The views will look something like:

<%= link_to 'Show', blog_entry_path(:nickname => blog_entry.blog.nickname, :id => blog_entry.id) %>
<%= link_to 'Edit', edit_blog_entry_path(:nickname => blog_entry.blog.nickname, :id => blog_entry.id) %>
<%= link_to 'Delete', blog_entry_path(:nickname => blog_entry.blog.nickname, 
                        :id => blog_entry.id), :confirm => 'Are you sure?', :method => :delete  %>
<%= link_to 'New Entry', new_blog_entry_path(:nickname => @blog.nickname) %>

Notice that for each of these routes we set the :nickname and the :id values. In fact this was the trickiest part of the entire procedure, figuring out what parameters I needed to pass to the link_to methods. For example there are times when I have to explicitly set :id to an empty string and others where the :id isn't needed at all.

There are some other changes I had to make along the way, notably:

  • Added foreign key constraints to blog table.
  • Change admin interface to add name
  • Change/add a create blog UI

Now that's done I intend to go back and fix up the 'blogs' routing so that it also supports nicknames.

Posted by kevin at 7:39 AM in Ruby

Wednesday, 22 October 2008

Rendering and Layouts

I'm assuming that most people reading this are .Net folk and that you will have at least a passing familiarity with ASP.Net, so occasionally I'll draw comparisons with Microsoft's framework. ASP.Net has had, since 2.0, the concept of Master pages. These are pages that provode the overall structure of parts of a web site. ASP.Net lets a page author design a template that contains content placeholders, this template is called a 'master page', individual pages can then specify that they want to use a specific master page and also specify which content replaces which placeholder within the page. Internally this turns out to be a fairly convoluted mechanism as the master page and the content page have to be woven together so that the right events get delivered to the right thing at the right time.

Rails, as you would expect, has a similar mechanism which known as 'layouts'.

In a Rails app, content is defined in a template. If you use the default generators of Rails 2.0 these templates are in the form of .erb files. A .erb file is essentially an HTML page with "turd-lets" of code embedded into it between <% %> and <%= %> symbols. This is just like other templating technologies such as ASP, ASP.Net, JSP or PHP

Templates are part of the view (obviously) and a typical template renders content for an action. For example in the rblog application there is a BlogsController class this has an index action with an associated index template. Of course none of this is mandatory, this is though the default behaviour if you use the scaffolding. The templates live in app/views and this index template lives in app/views/blogs/index.html.erb

The template looks something like this:

<h1>Latest Output</h1>


<div id='blog-entries-main-body'>
	<div id='blog-entries'>
		<% for blog_entry in @blog_entries %>
			<div class='blog-entry-surround'>
			    <span class="blog-title"><%=h blog_entry.title %></span>
			    <div><%=h blog_entry.entry %></div>
			    <span class="blog-author"><%=h blog_entry.author_id %></span>
  			</div>
		<% end %>
	</div>
</div>

The template is a mixture of HTML and ruby. This Ruby code iterates over a collection of blog_entries (stored in @blog_entries) and for each one formats some output.

The action that causes this particular view to be rendered looks like:

def index
    @blog_entries = BlogEntry.find(:all, :order => 'updated_at DESC', :limit => 10)
    @blogs = Blog.find(:all)

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @blogs }
    end
  end

The first thing to note is that there are two member variables initialized, @blogs and @blog_entries. These are initialized in the controller and are also available in the view, that's where the view gets its @blog_entries reference from.

The other piece of interest is the respond_to section. This says that if the format is html use the default rendering (the '#' is a comment, so the 'index.html.erb' on that line is there as an aide memoire), and if the format is XML then use the XML renderer.

This means that when a request comes into /blogs then the index action of the blogs controller is executed, the @blogs and @blog_entries objects are created, control passes to the view and the output is rendered. However the output looks like this...

200810170814.jpg

There is some extra stuff in here, for example there is styling and also things like a Register and Login button. This extra HTML comes from the layouts.

The layouts live in the app/layouts directory and by default there is one layout per controller, this is generated as part of the scaffolding. This means that if nothing explicit is done a default layout will be used, however there are various other ways to specify the layout needed, as will be seen.

The layout used for the blogs page looks like this

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>RBlog: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'general' %>
</head>
<body>
<div class="header" id="header">
	<div id="header-message">
		Welcome to RBlog
	</div>
	<div id="flash">
		<p><%= flash[:notice] %></p>
	</div>
	<div id="logon">
		<%= link_to "Register", :action => "register", :controller => "authenticate"  %> 
		<%= link_to "Login", :action => "login", :controller => "authenticate" %>
	</div>
</div>

<div class="main" id="main">
<%= yield  %>
</div>
<div class="sidebar" id="sidebar">
	<div id="bloglist">
		<div id="blogs-list-title">Blogs</div>
		<% for blog in @blogs %>
		    <div class="blog-title"><%= link_to h(blog.title), blog %></div>
		<% end %>
	</div>
</div>

<div class="footer" id="footer">
	
</div>

</body>
</html>

The highlights are:

  • The use of <%= controller.action_name %> to get the name of the action used to show this page
  • <%= stylesheet_link_tag 'general' %> to load a stylesheet, more than one can be specified
  • The use if 'flash' to display messages
  • The use of link_to to display URLs
  • Access to data members from the controller (for blog in @blogs)
  • The call to yield

It's the last one that's most interesting here. It's the call to yield that says 'take the default rendered output from the view and display it at this point in the page'. One thing to note here is that the view 'code' has already been executed at this point, i.e. the view template is rendered, that output is saved, then the layout is executed and the output from the template inserted into the layout.

This layout is called 'blogslisting.html.erb' so is not the default layout for the blogs controller, this means that the code has to explicitly specify this layout to use. Like many things in Rails there is a great deal of flexibility in doing this.

A global or default layout can be specified in app/controllers/application.rb , this contains the base class that all controllers derive from. A 'layout' declaration can be added In the class definition.

class ApplicationController < ActionController::Base
  layout "general"

A layout can also be specified per controller

class BlogsController < ApplicationController

  layout "blogslisting"

And this can be further overwritten on a per action basis. So if a given controller wants different layouts for each action it can have code something like this:

  def show
    
    @blog = Blog.find(params[:id])

    respond_to do |format|
      format.html {render(:layout => "layouts/blog" )}
      format.xml  { render :xml => @blog }
    end
  end

Where the code in the format.html block says to render with the layout with the 'layouts/blogs' layout file.

This piece is already much longer than I though it would be so it's time to stop. There's more to be said about this, such as getting multiple content into the layout (multiple calls to yield), and sharing content with partial page templates. More on that soon.

Posted by kevin at 7:07 AM in Ruby

Friday, 10 October 2008

Rails - Database Access

One of the driving forces of Rails is to make things easier for developers. It does this partly by taking decisions out of developers hands. It's an 'opinionated' framework, and one of the opinions it has is on the pattern to use for database access. Its choice in this case is the 'active record' pattern.

Rails has an ActiveRecord module and the model classes all derive from

ActiveRecord::Base
for example
BlogEntry < ActiveRecord::Base

it is this module that provides the active record support for the framework.

Like much of the rest of Rails, ActiveRecord follows naming conventions. Here for example the BlogEntry class represents a row in the blog_entries table. How does this happen?

Looking back to the Learning Rails - Part 2 post you will see that this script was run

script/generate scaffold blog_entry ...

This script created two files, the file with the model class BlogEntry definition and a "migration". The migrations are "scripts" that help create and mange the database definitions, essentially they are DDL for Rails.

Migrations are used to both set up and tear down databases. The files contain class definitions that specify the steps to take when managing the database.

Migrations are timestamped so that it is easy to apply migrations in the correct order and to rollback those migrations in reverse order if needs be. The migrations live in the db/migrate directory. Currently there are 4 migrations in there

20080925064318_create_sessions.rb       
20080925065056_create_blogs.rb
20080925064319_create_users.rb          
20080925065210_create_blog_entries.rb

The first is a fairly standard Rails migration that creates the session tables (run rake db:sessions:create to create this), the others are specific to this application. Each migration has a date-time as part of the file name and it's this name that determines the order in which the migrations are run. The 20080925065210_create_blog_entries.rb looks like this

class CreateBlogEntries < ActiveRecord::Migration
  def self.up
    create_table  :blog_entries do |t|
      t.string    :title,             :null => false
      t.text      :entry,             :null => false
      t.integer   :author_id,         :null => false
      t.datetime  :entry_added_date
      t.datetime  :entry_last_edited
      t.timestamps
    end
  end

  def self.down
    drop_table :blog_entries
  end
end

So it's a class that derives from ActiveRecord::Migration and provides two class methods (static methods to C#/C++ folks), up and down (it's the "self" that indicates that these are class methods and not instance methods). You can run the migration from the command line by using the Rake command

rake db:migrate

This runs any migrations that have not yet been run. How does it know which migrations to run? Tthere is a database table that holds the information about the migrations that have been run.

$ mysql -u root
mysql> use rblog_development
mysql> show tables;

shows something like

+-----------------------------+
| Tables_in_rblog_development |
+-----------------------------+
| blog_entries                |
| blogs                       |
| schema_migrations           |
| sessions                    |
| users                       |
+-----------------------------+

and

mysql> select * from schema_migrations;


+----------------+
| version        |
+----------------+
| 20080923152418 |
| 20080923152427 |
| 20080923152435 |
| 20080925064318 |
| 20080925064319 |
| 20080925065056 |
| 20080925065210 |
+----------------+

on my machine as I type this. Notice that the last entry in the table matches the datetime portion of the name of the last migration file.

When a migration is run (assuming it has not yet been added to the database), then the self.up method is executed. This method creates or modifies database entries. In the case of the blog_entries migration it creates the table and adds the eight columns from these five entries.

(title, entry, author_id, entry_added_date, entry_last_edited and timestamps

mysql shows this

mysql> show create table blog_entries;
+--------------+---------------------------------+
| Table        | Create Table                    |
+--------------+---------------------------------+
| blog_entries | CREATE TABLE `blog_entries` (
`id` int(11) NOT NULL auto_increment,
`title` varchar(255) NOT NULL,
`entry` text NOT NULL,
`author_id` int(11) NOT NULL,
`entry_added_date` datetime default NULL,
`entry_last_edited` datetime default NULL,
`created_at` datetime default NULL,
`updated_at` datetime default NULL,
PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1           |
+--------------+---------------------------------+

Notice that timestamps turns into two columns, and that an id column has been added as a primary key

A migration can also be rolled back. Running rake db:migrate rollback will rollback the last migration, or a specific version can be specified. For example rake db:migrate VERSION=20080925065056

Running the migrations this way runs the migrations in reverse order up to the specified migration, on the way the self.down mwthod of each migration is called. For the blog_entries migration that would drop the table. The down method should undo whatever the up method did!

One of the interesting (and frustrating) things about Rails is the way the migrations and the models work together. Running the script/generate scaffold blog_entry creates two files, the migration and the model. Looking in the model file there is ... nothing, just the class definition. The knowledge about the members of this class is in the migrations. This takes DRY (Do Not Repeat Yourself) to the limit but it can mean looking in several files (there maybe more than one migration per model) to find everything that the class uses. If the migrations get too "spread out", i.e. there are three or more migrations with modifications to one table then it is worth amalgamating those migrations into one file.

Posted by kevin at 3:37 PM in Ruby

Monday, 29 September 2008

Rails - Testing

Now that we have a Rails app up and running, all be it a simple one, it's time to think about testing. When you generate an application you also get a test structure created for us. This structure lets us create unit, functional and integration tests. Each kind of test has a different scope and I'll start, as we should, with unit tests.

Looking in the test/unit directory there's a single ruby source file for each model created previously, each of these files looks like this

class BlogEntryTest < ActiveSupport::TestCase
  # Replace this with your real tests.
  def test_truth
    assert true
  end
end

Pretty straightforward, assert that true is true. (If this is your first glance at Ruby code the first line says that BlogEntryTest derives from TestCase and the 'def' statement defines a method).

Before running the test I create the test database

mysqladmin -u root create rblog_test

There are two ways (at least) to run this test, running

ruby -I test test/unit/blog_entry_test.rb 

(-I test here includes the test directory in the search path) or

rake test:units

Running the first command line on my machine gives this:

Loaded suite test/unit/blog_entry_test
Started
E
Finished in 0.033476 seconds.

  1) Error:
test_truth(BlogEntryTest):
ActiveRecord::StatementInvalid: Mysql::Error: Table 'rblog_test.users' doesn't exist: DELETE FROM `users`

This shows us that the database tables don't exist. Running

rake db:test:prepare

fixes this and re-running the test now succeeds.

Started
.
Finished in 0.095619 seconds.

It's also possible to run

rake test:units

This will run all the unit tests

Started
...
Finished in 0.056533 seconds.

3 tests, 3 assertions, 0 failures, 0 errors

Now that there's some confidence that the testing framework is in place it's time to start thinking about real tests.

The user class represents a user of the system, either a user with a blog or a user posting comments. This user must have a username, email and password. The user class looks like this

class User < ActiveRecord::Base
  validates_presence_of :name
  validates_presence_of :email
  validates_uniqueness_of :email
  validates_confirmation_of :password
  validate :password_non_blank

This suggest some tests. Does the user have a name and email, is the emil unique and does the password have some data! The first test checks that the user is valid

class UserTest < ActiveSupport::TestCase
  def test_empty_user_is_invalid
    user = User.new
    assert !user.valid?
    assert !user.errors.empty?
    assert user.errors.invalid?(:name)
    assert user.errors.invalid?(:email)
    assert_equal "Missing password", user.errors.on_base
  end

The test creates a User then calls the valid? method (if you're new to Ruby the ? on the end of a method is part of the method name and indicates that the method returns a boolean, a ! on the end indicates that the method mutates data) . The test asserts that the user is not valid and then asserts that the appropriate errors have been added to the errors collection.

The code has other tests for the user, checking that the password and password_confirmation match and that the password is not blank. There is also a test that a User is valid if all the fields are set correctly, none of these are shown here but the code is available here not that there's much to see at the moment!

The final test for the moment checks that the User must have a unique email. The code looks like this:

def test_user_unique_email
  user = User.new(:name => "Test Name",
                  :email => users(:kevin).email,
                  :password => "wibble",
                  :password_confirmation => "wibble")

  assert !user.save
  assert_equal "has already been taken", user.errors.on(:email)
  assert_equal ActiveRecord::Errors.default_error_messages[:taken], user.errors.on(:email)      
end

The thing of interest in this code is the line

:email => users(:kevin).email,

This loads a fixture named :kevin. Fixtures are test data defined in a yml file (YAML Ain't a Markup Language) file. Fixtures have names and cen be loaded by name in the test code. The fixture looks like this:

kevin:
  email: kevin@test.com
  hashed_password: hash
  name: Kevin

The fixture data is loaded into the database, then the line 'users(:kevin).email' loads the fixture and gets its email value. This means that the test tries to save a user with the same email address as one that already exists, and that should fail.

Posted by kevin at 11:33 AM in Ruby

Thursday, 25 September 2008

Learning Rails - Part 2

I wanted to make this a series about Rails and about Ruby. To that end I'm going to write a series of entries on building an MVC application. As I said in the previous post I am a Ruby and Rails neophyte, so I'll be learning as I go along, regard this as a developer's journal. The aim being that you can learn from the mistakes that I make. If this really gets going I also hope to do some screencasts along the way.

What am I going to write - a blog of course (is there any other sort of web app out there today :) ). I chose blogging software because

  • Everybody understands what a blog is, so no trying to figure out the behaviour
  • It gives me a chance to play with different formats (html and RSS)
  • At some point I'll need to write support for the various APIs (atom, etc)
  • There'll be chances to use AJAX
  • I can learn how to deploy to Apache
  • It shouldn't take too long to get things going

I'm going to rely heavily on the 'Agile Development With Rails' book, and hopefully any feedback I get. I'm learning Ruby at the same time as Rails and Ruby is a very idiomatic language, I know I'll get some of the idioms wrong, so again feedback is welcome. Oh and initially I'm doing this on MacBook using TextMate as the editor. At some point I'm going to play with NetBeans and Eclipse as tools and so try out JRuby, not that I like a challenge of learning 17 new things at once!

Start at the beginning. Go on the end and then stop, said the Red Queen

So the beginning of a Rails app is the code generator, to create the application I fire up a terminal make sure I'm in the right directory and call

rails rblog

This gives the well known directory structure of

app
config
db
doc
lib
log
public
script
test
tmp
vendor

Most of the time I'll be in the app directory (that's where the models, controllers and views are), but I'll also use stuff from the db directory where the 'migrations' are stored, in the public directory where public the web files are and in config, where various setup files live.

Once the application has been created I can fire up another terminal (I usually have three open, one for my commands, one for the server and another to see the log file), change the the project directory and run the server with the command 'script/server'

This starts the server on port 3000, the server I'm using here is Mongrel, you can also start WEBrick. There's plenty of discussion on these servers out on the web so I won't go into the differences here.

Once the server is running you can point your browser at http://localhost:3000 and you should see something like:

RailsHomePage

I'm going to use MySql for the database and this needs to be configured. To do this I've edited config/database.yml to look like this:

development:
adapter: mysql
encoding: utf8
database: rblog_development
username: root
password:
socket: /tmp/mysql.sock

Adding similar entries for test and production databases. Once that's done I created the development database

mysqladmin -u root create rblog_development

Now that all the necessary structure is in place I can create the first controllers and models. What do I know about the blog? I know it's going to have users, users can have blogs and blogs will have entries and comments. There may be more things eventually, such as tags, categories, pingbacks etc, but for now that's enough. So not to get too far ahead of myself I decided to create scaffolding for users, blogs and blogentries.

For the users model I'm going to user a similar approach to that used in the Rails book, so the user will have an email address and password, the password will be stored as a hash will be salted. A user will have a name that can be displayed on comments or on a blog and users may also own blogs. For now I'm going to limit this to one blog per user, but in the future this may expand to multiple blogs.

Running

script/generate scaffold user email:string hashed_password:string name:string blog_id:integer

gives me what I want. Doing something similar for blogs and blogentries

script/generate scaffold blog title:string sub_title:string owner_id:integer admin:boolean
script/generate scaffold blog_entry title:string entry:text author_id:integer entry_added:datetime entry_last_edited:datetime

creates those models and their corresponding controllers and migrations.

Notice that as in my previous post I'm using singular names for the model components, so user, blog and blog_entry.

Now that's done it's then onto setting out some of the UI and writing some unit testing code.

Posted by kevin at 7:32 AM in Ruby

Monday, 22 September 2008

Learning Rails - Part 1

I've been looking at Ruby and Rails for a long time, when I say looking at here what I really mean is staring through the glass and wondering what the fuss was about. Now that I finally have a MacBook I decided to actually sit down and learn Rails and Ruby at the same time. This means that on my hour long commute to and from my current contract I'm writing web code, and much fun it is. The commute is split over two trains so each part is about 30 minutes which gives me a very fractured learning experience but I'm still getting something done.

I wanted to use the web app I'm working on (it's only a toy) as a learning tool. This means that a) I wanted to minimize the new concepts and b) not be led by the hand too much. Because of that I decided that I would initially not use REST based routing as I would need to understand more about REST and using the built in routing would hide the routing system from me. So taking my routes in hand I initially did things the 'hard' way (actually, it's not that hard)

I finally figured that I knew enough to then try the RESTian approach, so firing up my trusty console, and TextMate I tried adding a new controller and model to the application.

I ran a command, something like,

script/generate scaffold foo

then ran

rake db:migrate

pointed the browser at http://localhost:3000/foos and everything seemed good. I added a new foo, life was good. Then I tried to browse to http://localhost:3000/foo/1 and I get an error:

Unknown action
No action responded to 1

After much Googling and running of

rake routes

I couldn't find an answer.

Eventually after much re-reading of the routing chapter in The Book something must have lodged in my head and I decided to kill the web server and restart it, and suddenly the routes started working. The moral is "you do sometimes need to re-start the rails web server"!

The second issue was even more stupid. After fix the above problem, and getting my head more around the REST idea I decided I needed a bunch of controllers, so I duly run

script/generate scaffold bars

restart the server and immediately get strange errors along the lines of

undefined method `edit_bars_result_path' for #<ActionView::Base:0x255a508>

eh!

Rails experts will be laughing right now, or thinking 'been there, done that.' Rails adopts naming conventions, in this case models and controllers are singular. RESTian routing is based around the ideas of things and collections of things, the things are singular and the collections are plural. I tried to generated things that were already plural (bars), and the RAILs pluralization had no idea what to do with it, so the naming broke (at least that's what I think happened :) )

Posted by kevin at 4:03 PM in Ruby

Sunday, 4 May 2008

More Ubuntu Settings

I was going to call this entry "More Ubuntu Woes" and maybe I should have.

Ubuntu makes certain things that should be difficult, easy and some things that should be easy, difficult, like assigning keys to commands. I'm a keyboard jockey, I'm way happier using the keyboard than the mouse> I tell my self this is because the keyboard is quicker, but it's probably because I cut my teeth in the days before mouse, and and in Emacs where key chords are king!

This means I am lost without my keyboard shortcuts, in Windows such things as W+L to lock (where W is the Windows key). I use Windows a lot, and if I'm using Ubuntu I'd like the same keys to work. This should be easy, however it appears that having Compiz enabled, Compiz and Gnome clash!. Gnome has dialogs to set up keybindings, but you have to jump through hoops to get it to work.

First hoop is getting Ubuntu to recognise the Windows key (called the Super key in Linux) as a key modifier, like Control and Alt. To do this go to System..Preferences..Keyboard, select the Layouts tab and then Layout Options. From here select Alt/Win key behavior and then choose "Super is mapped to the Win-keys"

Once you've done this you can now edit the Gnome keyboard preferences. From System..Preferences..Keyboard Shortcuts, scroll down to Desktop. Here you can click on the "Show the panel run application dialogue", select this and hit WindowsKey + r on the keyboard. Do the same for Run a terminal, but select WindowsKey + t. You may think you can do the same thing for the Search, Home Folder and Lock screen commands (assign them to Windows + f, Windows + e and Windows +l respectively), however, those commands cannot be assigned from here and if you try, not only will the commands not work but you may have trouble re-assigning the keys elsewhere. Instead to assign these key you will need to you the Compiz Configuration Manager

Select System..Preferences..Advanced Desktop Effects Settings. In the dialog box select General and then Commands. I have my first three commands set to "beagle-search", "nautilus" and "gnome-screensaver-command --lock" respectively and the key bindings set to f, e and l. And this all works.

There's more here on this.

Now, if only I can get Ctrl+Esc to bring up the main menu!

Posted by kevin at 12:21 PM in General

Thursday, 1 May 2008

CruiseControl.Net

I'm working with CruiseControl.net this week. First time I've worked with the product and I'm finding a couple of issues (that are all my mistakes) but that aren't particularly well documented. So this is as much for my benefit as anything else.

Firstly, last night after editing the config file I couldn't get the build to run. Now, there are several config files. in c:\Program Files\CruiseControl.NET\server, the main one is the ccnet.config file, this is the default location for this file, that location can be changed, to do that you'd edit the ccservice.exe.config file.

The ccservice.exe.config file is re-read when the CCNet service is (re)started, as is the ccnet.config file. When you edit the ccnet.config file it appears that the service does re-read the file, however, if the file is invalid the service ignores it, and doesn't appear to log this fact anywhere. Re-starting the service will force a re-read of the config file and then log an error if the file is invalid.

I was changing a CCNet config file to do multiple checkouts, after a bit of trial and error the source control section of the file ended up looking like this

<sourcecontrol type="multi">
	<sourceControls  autoGetSource="true" applyLabel="true">
		<vsts autoGetSource="true" >
			<server>http://server:8080</server>
			<project>$/FOO/SharedUILibraries</project>
			<username>user</username>
			<password>user</password>
			<domain>nt</domain>
			<workingDirectory>
                               C:\...\FOO\SharedUILibraries
                        </workingDirectory>
			<cleanCopy>true</cleanCopy>
			<workspace>WS_MINE</workspace>
			<deleteWorkspace>true</deleteWorkspace>
		</vsts>
		<vsts autoGetSource="true" >
			<server>http://server:8080</server>
			<project>$/FOO/SharedEnterpriseLibrary</project>
			<username>user</username>
			<password>user</password>
			<domain>nt</domain>
                        <workingDirectory>
                            C:\...\SharedEnterpriseLibrary
                        </workingDirectory>
			<cleanCopy>true</cleanCopy>
			<workspace>WS_MINE</workspace>
			<deleteWorkspace>true</deleteWorkspace>
		</vsts>
		<vsts autoGetSource="true" >
			<server>http://server:8080</server>
			<project>$/FOO/WD</project>
			<username>user</username>
			<password>user</password>
			<domain>nt</domain>
			<workingDirectory>
                            C:\...\FOO\WD
                        </workingDirectory>
			<cleanCopy>true</cleanCopy>
			<workspace>WS_MINE</workspace>
			<deleteWorkspace>true</deleteWorkspace>
		</vsts>
	</sourceControls>
</sourcecontrol>
And this worked, however there was one gotcha.

Before getting this to a working stage I was getting a status in the CCNet dashboard of CheckingModifications, whatever I did I'd get this status, even forcing a build wouldn't change it. It turned out the reason for this was that I had put the wrong name in the project element. This meant that CCNet was trying to look for bits that didn't exist, and sat there spinning its wheels. Once corrected everything worked fine.

So if you get the CheckingModifications status, check that your source control settings are correct and that you can do a checkout

Posted by kevin at 7:09 AM in Net

Wednesday, 26 March 2008

LINQ Nasties

This was raised on an internal mailing list by Brock Allen, and as he isn't blogging much (not that I can comment) I thought I'd raise it here.

Look at this query:

NorthwindDataContext db = new NorthwindDataContext();
db.Log = Console.Out;

var supp = (from s in db.Suppliers
           select s).FirstOrDefault();

var prods = from p in supp.Products
           where p.UnitsInStock > 10
           select p;

foreach (var p in prods)
{
   Console.WriteLine(p.ProductName);
}

Looks pretty harmless, get a supplier, then get the products fromt that supplier where the UnitsInStock > 10.

Problem is if yuou run this, you see the following in SQLProfiler

exec sp_executesql N'SELECT TOP (1) [t0].[SupplierID],
[t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle],
[t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode],
[t0].[Country], [t0].[Phone], [t0].[Fax], [t0].[HomePage]
FROM [dbo].[Suppliers] AS [t0]
WHERE [t0].[SupplierID] = @p0',N'@p0 int',@p0=1

exec sp_executesql N'SELECT [t0].[ProductID], [t0].[ProductName],
[t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit],
[t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder],
[t0].[ReorderLevel], [t0].[Discontinued]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[SupplierID] = @p0',N'@p0 int',@p0=1

The first statement is executed when you call FirstOrDefault(), the second when you execute the foreach. Notice anything about the statements? They are almost exactly the same, except the second statement loses the TOP(1) part. This means that the where clause is happening on the client! Not a big deal you may think, unless of course the select returns 1000s of rows.

Fixing this is easy

var prods = from p in db.Products
           join s in db.Suppliers
           on p.SupplierID equals s.SupplierID
           where s.SupplierID == 2
           && p.UnitsInStock > 10
           select p;

which gives:

exec sp_executesql N'SELECT [t0].[ProductID], [t0].[ProductName],
[t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit],
[t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder],
[t0].[ReorderLevel], [t0].[Discontinued]
FROM [dbo].[Products] AS [t0]
INNER JOIN [dbo].[Suppliers] AS [t1] ON [t0].[SupplierID] = ([t1].[SupplierID])
WHERE ([t1].[SupplierID] = @p0) AND ([t0].[UnitsInStock] > @p1)',N'@p0
int,@p1 int',@p0=2,@p1=10

Which is probably what you want.

I like LINQ, especially LINQ to XML, but this reminds of the dark days of EJB Entity Beans. You really have to profile the generated code to understand exactly what LINQ is giving you, don't be seduced by the ease of use.

Update

Ian Griffith pointed this out:

"One subtlety with your LINQ Nasties post is that you kind of make it look like the solution is to use one query instead of two. In fact, the key is understanding which operations will evaluate the query and which won't."

And he's dead right, Ian's blogged about this here. Even if you don't read Ian's full post, read the "Know Your Tools" section at the end.

Posted by kevin at 2:28 PM in Net

Thursday, 20 March 2008

ASP.Net Page_XXX events

In ASP.Net the engine looks for various methods to call to handle events such as
public void Page_Load(object sender, EventArgs e) {}
I had always assumed that the framework searched for these methods based on their full signature, turns out this isn't the case. The ASP.Net MVC framework uses a
public void Page_Load() {}
method, and I was trolling through the code trying to find where this is called from, when I ended up inside the Page ProcessRequest method, i.e. the default ASP.net processing. Which meant there was no special processing for this version of Page_Load.

I quickly create a bog standard web app and added a no parameter Page_Load to it, and sure enough it fires!

Note that if you have the parameterised and no parameter Page_Load only the parameterised one is called.

Posted by kevin at 10:03 AM in Net

Good Things With MVC

I've just started playing with ASP.NET MVC (or Microsoft's Homage to Ruby on Rails as Tim Ewald labelled it!), it's good to see a community growing up around this.

Posted by kevin at 6:02 AM in Net

Upgrading SQL Server

As a developer I constantly use Visual Studio and SQL Server, and it turns out thatn when you install these, the install order is important. If you install SQL Server before VS200x then you get all the SQL tools such as the Management Studio and the Profiller. However, if you install VS200x and then install SQLServer the tools do not get installed. This has annoyed and frustrated me for years, then I discovered it wasn't just me, other people were having the same problem.

If only I'd read the warnings!

This week when I was going through the process again, having already installed VS200x I paid attention to what the SQL Server installation was telling me. When you install SQLServer it goes through a systems check to make sure you are able to install the software, things such as how much memory you have, whether you have IIS etc. One of the warnings I got was an "Edition Change Check (Warning)". Normally I ignore this as it's only a warning. But this time I took notice

The warning says

To change an existing instance of Microsoft SQL Server 2005 to a different edition of SQL Server 2005, you must run SQL Server 2005 Setup from the command prompt and include the SKUUPGRADE=1 parameter.
and this time I did take notice. I fired up a command prompt, flipped to the Servers directory and ran
Setup SKUUPGRADE=1
and joy of joys all the tools appear as part of the install.

Of course, the annoying thing is, why doesn't the installer do this. It's detected the problem, one little 'Do you want to upgrade?' checkbox wouldn't have hurt anybody!

Posted by kevin at 5:11 AM in Net

Sunday, 21 October 2007

Ubuntu Suspend

Suspend was was working in Feisty but when I updated to 7.10 (Gutsy) it stopped. When I resumed all I'd get a blank screen.

This post seems to have fixed things for me.

Having played with these settings it looks like I only need
POST_VIDEO=false
from the
/etc/defaults/acpi-support
file

.

Posted by kevin at 5:18 PM in General

Friday, 5 October 2007

Books I've Read Recently

Somebody was asking about books on an in internal DevelopMentor listserver.

This is a list of recent books that I've read (and these are just the ones within the last three months)

  • Revelation Space series by Alastair Reynolds. Hard Science Fiction. First two books are great, the third was slightly disappointing.
  • Harry Potter an the Deathly Hallows I'm sure you all know this one. It's unremittingly dark
  • Slaughterhouse5 by Vonnegut
  • Occupational Hazards by Rory Stewart. Required reading if you're interested in Iraq and what will happen there
  • Salmon Fishing in the Yemen. Because I'd run out of books on holiday, and yes, it is a novel, and it's actually quite good.
  • God is not Great by Christopher Hitchens. For all us non-believer's out there.
  • This Book Will Save Your Life. Another Novel. Get the doughnuts instead!
  • A Short History of Tractors in Ukranian by Maria Lewycka. Very funny. You'll like all the characters by the end
  • The Life and Times of the Thunderbolt Kid by Bill Bryson. This is laugh-out-loud funny. If you haven't read it, treat yourself and go and buy it. On holiday I read it, my wife read it and the kids read it.
And that was just on holiday Since then it's been

Posted by kevin at 3:10 PM in General

IgNobels

The IgNobels were awarded this week

I especially loved this one:

Literature - Glenda Browne of Blue Mountains, Australia, for her study of the word "the", and how it can flummox those trying to put things into alphabetical order.

Sounds like the sort of thing Douglas Adams or Terry Pratchet would write.

Posted by kevin at 12:34 PM in General