development

Too Many Interfaces

While writing some code at work the other day, I noticed something, that I had meant to blog about earlier.

I work in a .NET development shop, coding C#. One of the latest kicks we’re on at work is IOC and Dependency Injection, we use it everywhere. It’s almost a crime if you actually create an instance of an object using the ‘new’ keyword. One of the side effects of this is we have interfaces for just about everything. There are a couple things I don’t like about this.

When I think of interfaces, I generally think of the something along the lines of IDisposable, IView, INotifyPropertyChange, IDraggable, etc. These interfaces are something you implement if you need certain functionality, and they can be used by multiple classes in your projects. When you start creating interfaces for every class in your project so that you can use a service locator or some other means to create the concrete instance of the class, you end up with interfaces named IUpdateAddressView, IContractService, ILinearScheduleRepository, etc. You’re not going to have any class except for LinearScheduleRepository implementing the ILinearScheduleRepository interface, it’s specifically made for that class, so that you can write code like this

var repository = ServiceLocator.Create<ILinearScheduleRepository>();

It adds complexity and it also makes navigating to code a pain in the arse, unless you have a tool like Resharper at your disposal. If you don’t and you right click on a method or property and chose to go to the definition, you end up in the Interface, not the class that implements that interface method or property.

My other gripe with this is you end up feeling like you’re coding in C/C++, where the interfaces are the equivalent of header files. You can no longer add a new method or property to a class, you must first go to the interface for that class and add your method or property there, then you can go to the class and implement it. It’s a pain to always have to remember to do that, since that’s not something you would generally have to do in C#. I don’t really like having to code for some tool that we’re using. Another place we do this is having to occasionally mark a method as virtual, so that our Mocking tool doesn’t call it when recording your expectations. There’s no other reason for that method to be virtual, but we have to do it if we want to Mock a test (which is something else I’m really not a fan of, but I will save that for another post).

I can see some benefit in IOC and Dependency Injection, I guess it’s just a case of the usual going overboard on the latest buzzword/development craze that we tend to do at my work. Maybe one of these days we’ll go the “let’s try and do a nice simple, non complex” implementation, the kind of thing I enjoy, but I doubt it. I can already sense that our next project will be Silverlight with Prism, Entity Framework, and some Fluent and maybe automapper thrown in just for fun.
|

Getting Distinct Objects Using LINQ

If you try to get distinct objects using LINQ you have two choices. You can use the overload to Distinct, which takes an IComparer<> that you write, where you override Equals() and GetHashCode() or you can do a grouping and select the first object of each group. For example, at my work I work with a lot of Title objects. If I have some duplicates in my list I can’t just use Distinct(), because it will think every object is different, it doesn’t know how to determine what’s equal and what isn’t. Instead I would want to compare the Title Ids to check if they are different. You can do that like so

var distinctTitles = (from t in TitleList select t.Title).GroupBy(x => x.TitleId).Select(g => g.First());
|

LINQ and Collections

When we first upgraded to the .NET 3.5 framework, the one feature I wasn’t the biggest fan of was LINQ. My main reason for the dislike is the way the syntax stands out from everything else around it. It reminded me of when I was a COBOL developer, and the code would have inline DB2 or IMS logic, which stood out from everything else. It may be powerful, but it just doesn’t look or feel right.

Well, over time I got over it. We have used LINQ a lot in this Silverlight project I am working on. The main use is for getting a distinct list of items, or to quickly filter or sort. It works great for this. The other day I found an even greater use.

Let’s say you have an object that looks like this:

public class TitleRight
{
    public Guid ID { get; set; }

    public List<Territory> Territories { get; set; }

    public List<Language> Languages { get; set; }
}

Now, let’s say you have a list of TitleRight objects, and you want to find the ones in the list that have a certain TerritoryID and a certain LanguageID. In the past, one way you would accomplish this would be to iterate through the list of TitleRights, and for each one, you would then iterate through the list of Territory and Language, and try to match on the ID.

Now, in .NET 3.5, with the help of LINQ and Lambda expressions, you can do the following

var query = from tr in TitleRights
            where tr.Territories.Find(t => t.Id == territoryId) != null &&
                  tr.Languages.Find(l => l.Id == languageId) != null
            select tr;

So, what is this code doing? It uses the List<T>.Find() method to search the list for a match, returning NULL if nothing is found. It took a little trial and error for us to figure this out, but in the end I think it truly shows the power of LINQ. This accomplished in 4 lines of code, something that would normally take probably 2 - 3 times as many.
|

Tech Books I'm Currently Reading

The iPhone Developer’s Cookbook

33463358

I have a couple ideas for iPhone applications, nothing big, quick hit applications that would be available for free, so I picked up this book to point me in the right direction. I also have plans for a big iPhone application, that the people I’ve mentioned it to think is a great idea, but it’s one of those things that would take a team of developers, some venture capital, and some big company buy in, not something I think I can pull off at the moment, but maybe I can patent the idea Happy

Silverlight 2 Unleashed

31942746

The application I am currently working on at work is a Silverlight web application. Silverlight 2 was recently released out of beta, so there are finally books showing up that are no longer referencing the beta build. I purchased this book to bring into our war room as a reference. I like the Unleashed books, and this one seems to cover a wide variety of subjects related to Silverlight 2, so hopefully it’s of use to the team.
|

Using the Netflix API

The project I am currently working on makes use of the Netflix API to retrieve information about titles and displays the box art. It took me a while to get it working, mainly because I was trying to do too much. I figured I’d share this information, in case you also are going about using the API in the wrong way. There are two ways to use the API. First, you use it to make simple calls to their RESTful web services. Second, you are making a front-end of some sort that signs in as the user and lets them manipulate their queue, browse the library, or watch on demand streams. For our application I needed to go the first route, but was coding it the second way, which was overkill, and was causing me major problems. To perform a simple Title search, or to do a daily download of their entire index, you don’t need to sign in as a Netflix user, you just need to authenticate using Open Authentication with your consumer key and consumer secret (which you will need to apply for on their developer site).

Some kind developer was nice enough to write a simple class to help you with this. You can view the code to his implementation, OAuthBase, here. Add this class to your application, and then it’s as simple as the following code to perform a title search.


private void Search()
{
    var url = new Uri(“http://api.netflix.com/catalog/titles?term=” + titleName);

    var consumerKey = ConfigurationSettings.AppSettings[“ConsumerKey”];
    var consumerSecret = ConfigurationSettings.AppSettings[“ConsumerSecret”];

    string normalizedUrl;
    string normalizedRequestParameters;

    var oauth = new OauthBase();

    var signature = oauth.GenerateSignature(
        url, consumerKey, consumerSecret,
        null, null, “GET”, oauth.GenerateTimeStamp(), oauth.GenerateNonce(),
        out normalizedUrl, out normalizedRequestParameters);

    var finalUri = normalizedUrl + “?” + normalizedRequestParameters + “&oauth_signature=” +
        oauth.UrlEncode(signature);

    // Call the service to perform the title search
    var xmlDocument = new XmlDocument();
    xmlDocument.Load(finalUri);
}


Believe me, this is so much simpler than what I started out doing. I was following their examples and I was connecting to their site through my application, bringing up a Netflix login screen, having to add my application to a trusted application list, etc. I wasted a couple days development before I realized that was only needed if I wanted to let users interact with Netflix, not just do a title search.
|

VSTS 2008 Power Tools

If there is one category of software developed by Microsoft that I have never been a fan of, it’s the source control applications. Visual Source Safe was just awful, and their newer one, Team System, isn’t all that much better.

When I first started at Turner, we were using Source Safe on my team. From there we moved over to Star Team, which actually made Source Safe look good. We eventually left Star Team for CVS, which rocked. I like CVS because it is simple to use, and it just works. My favorite feature is using an application like Tortoise CVS, which allows you to do all of your source control from within Windows Explorer. We moved to Subversion from CVS, which is a better version of CVS, so I liked it even more. Once I loaded Tortoise SVN I could use it from Windows Explorer too.

When I started on this Agile project, we moved over to Team System. It’s pretty much like Source Safe, but has some extra features. The main reason we moved over was for its SCRUM and shelving capabilities, two features we never use. It integrates with Visual Studio, but it isn’t the greatest integration. If you have multiple machines you work on, it screws up its whole ‘workspace’ concept. Worst of all, to edit a file you had to fire up Visual Studio and go into the Team Explorer interface and check it out for edit. This sucks when you want to make a simple configuration change. This is where CVS and SVN rocked, you just opened the file in whatever editor you like and edit it. Since it monitors the directory, it picks up the change. Right-click on the file and choose Check-In. It’s that simple.

Well, you can finally do this with Team System, if you go and download their VSTS 2008 Power Tools. The shell integration isn’t installed by default, you have to do a custom install to enable it. After a log-out-log-in you now have VSTS capabilities from within Explorer.
|

NHibernate Class Level Filtering

While this information is available in the NHibernate documentation, it’s easy to overlook. If you have a filter you apply to all of your queries through a ‘Where’ clause in NHibernate, you can place that ‘Where’ clause in your HBM file at the class level.

For example, we don’t delete data where I work, we need it for historical reporting and for searching. Instead of deleting we usually have an active indicator. What this causes is all of our queries always have “WHERE ACTIVE_IND = ‘Y’” tacked onto the end. Instead of doing that we can just place this in our HBM and it will automatically be applied to any query.

<class name=”className” table=”tableName” where=”ACTIVE_IND = ‘Y’”>
...
</class>

I want to thank my co-worker Kevin Brill for pointing this out.

|

Quick Mac Dev Tip - Enable Apache

I have a couple co-workers that have recently joined the Mac community. I figure I can pass along any development tips, programs I use, gotchas, and general tips that I’ve come across along the way.

My first tip is how to enable Apache Web Server on your Mac, so you can do some web development.

The great thing about the Mac is Apple has actually included a lot of development tools by default or on the installation DVD. Apache Web Server is already installed on your Mac, you just need to enable it, which is pretty simple.

Start up the Mac System Preferences. You can either do this by going to the Apple Menu and choosing System Preferences, or you can click on the System Preferences icon in your dock, if you have it there.

Go to the Sharing section, under Internet & Network, and click the checkbox next to Web Sharing. That’s pretty much all there is to it. If all went well, you can open your web browser and browse to http://localhost/, you should see the Apache Web Server start page. You even have your own personal web page located at http://localhost/~username, you can use iWeb to publish to this.

The other thing you need to know is where the actual directory on your drive is that’s mapped to localhost. Double click on your hard drive and open the Library folder. Navigate to the WebServer directory and then to the Documents directory, this is where the web site resides.

To access your personal web page you go to /Users/username/Sites.

One last thing you need to know, in case you are doing something like PHP development, or any other type of development that requires you to make a change to the Apache configuration file. This file resides in /etc/httpd. You need to be root user to edit this file, the best way to do this is to open the Terminal and type the following

cd /etc/httpd

Since your Mac is based on Free BSD, a Unix system, you have all of the great Unix editors built in. An easy one to use for editing the Apache config file is Pico, but you also have access to Vi and Emacs. To start Pico as root to edit the config file type the following

sudo pico httpd.conf

Type in your root password and you are now able to make your needed changes.
|

Mac Development with Objective-C

With the recent release of the iPhone SDK I know a couple developers who have purchased a Mac and are thinking of doing some iPhone/Mac software development. Now, most of these developers are from a purely Microsoft development background, from the early days of Win32 and COM development, perhaps some VBScript, and now .NET development. They don’t have a background in a low level language, such as C. Objective-C has been around since the 80’s, it’s basically a very thin OO layer on top of C. If you know C you should have no problem learning Objective-C. I learned C back when I was going to university for my Engineering degree. I think it’s a good thing to learn a low level language such as C or Assembler, as it helps you later on when you are learning a lot of the higher level languages, such as Java or C#. I myself have been playing around with Objective-C, mainly for writing a couple little programs I use on my Mac, but I would like to try an iPhone App if I could think of one to develop.

Here are a couple good resources I’ve found for helping learn Objective-C.

The first place to start would be the Apple Developer Connection. It has good tutorials on Objective-C, Cocoa development, iPhone development, and using XCode, the Apple IDE.

There are a couple blogs I follow which are pretty good: Cocoa Is My Girlfriend, Mac Developer Tips, and iPhone Developer Tips.

There are also a couple books I recommend. These books mainly pertain to XCode, but you learn Mac development at the same time. Both of these books have taught me a lot.

Cocoa Programming For Mac Os X (Third Edition): Aaron Hillegass. Make sure you get the third edition, as this one is geared toward XCode 3, which is the newest release. I have the second edition also, and while you can probably follow along, the changes between XCode 2 and XCode 3 are pretty big, so you will have trouble following along with the code samples.

26778177

XCode 3 Unleashed. The great thing about this book is it walks you through developing an application from start to finish using XCode and the other tools provided by Apple for UI design, unit testing, and performance testing.

28187225

I will agree with a co worker of mine that the barrier of entry for a developer on the Mac platform is a bit higher than that of a developer on the Windows platform, but in a way I think that works to the Macs advantage. You don’t have every point-and-click coder out there creating crap applications for the Mac, a Mac developer has to be a bit more knowledgeable.
|

Run VM From External Drive

If you install the software I spoke of in an earlier post: “Read/Write to NTFS on external drive with Mac”, you will be able to run a virtual machine from your external drive. You need to have write access to the NTFS drive to run the VM. You may think that running a virtual machine from an external drive would have bad performance, but it’s actually just as responsive as if the files were on your machine. The only times I’ve seen operations take an extended amount of time is when you perform a Suspend, or when you take a snapshot of the machine. The great part about running the VM from the external drive is it lets you keep the space on your laptop/desktop. My MacBook has a 60 GB HD, and my average virtual machine is weighing in at 30 GB, which is a huge chunk of space to give up.
|

Read/Write to NTFS on external drive with Mac

If you work with both a Windows machine and a Mac, and you want to hook up a portable drive to both, you will need to format the drive in a format that both Windows and Mac can read. Since FAT 32 really sucks, your best bet is formatting the drive using NTFS. A Mac can read an NTFS partition, but can’t write to it. You may also run into issues trying to read from an external/portable drive that’s formatted in NTFS.

I ran into this today when I used VMWare Converter to convert my work computer into a virtual machine. The resulting VMWare image was around 20GB, not exactly the size file our network folks would like me trying to copy across the network. The easiest way to move such large files is to copy the files to a portable drive. I formatted my portable drive in NTFS and copied the files onto it. When I hooked the external drive to my MacBook I received a read error. To fix this I did the following.

Install MacFUSE. This allows your Mac to use any FUSE (File System in Userspace). Once you download the disc image and install the package, you should download and install the NTFS-3g FUSE. You will need to reboot after the install, (something I haven’t had to do since my Windows days); but after the reboot you should hopefully now encounter no more issues.
|

Extension Methods

Since we are using Silverlight on this new project I am working on, we are doing our development in .NET 3.5. One of the new features in .NET 3.5 is Extension Methods. When I first saw this I figured it was a nice feature, but I didn’t know when I would use it. Today I wrote a couple. I figure there’s probably a couple reasons you would create an Extension Method: (a) You see you are performing the same coding routine in multiple places, and it would be nice if you could replace it with less code, and (b) there’s a method you always wished was on one of the built in .NET types -- something like String.ToUpperCase() or something along those lines. The Extension Methods I wrote today fell into the first category. We have a lot of places in our code where we check if an object is null before progressing.

if (contract == null)
    return;

I wrote a simple IsNull Extension Method that can be applied to any object as long as a reference to my Extension Method namespace is in the using directives.

public static bool IsNull(this object source)
{
    return source == null;
}

It’s very simple, and only saves a little typing, but it looks nicer to have the following

if (contract.IsNull())
    return;

We also tend to have a lot of code that checks if a List is not null and also isn’t empty

if (titleIds == null || titleIds.Count == 0)
    return;

For this I created an IsNullOrEmpty Extension Method

public static bool IsNullOrEmpty<T>(this List<T> source)
{
    return ((source == null) || (source.Count == 0));
}

This way you can write the code as

if (titleIds.IsNullOrEmpty())
    return;

These are the only Extension Methods I’ve written so far, but I can think of another one that would be useful and would fall into the second category of why you would write Extension Methods. Let’s say the Generic List of Integer TitleIds I had in the previous example had a couple duplicates, it would be nice to be able to say

titleIds.RemoveDuplicates();

|

Visual Studio Error: "Some of the properties associated with the solution could not be read."

Something happened when I created the Visual Studio .NET 2008 Solution for my Executive View project and checked it into Team System. After it was checked in, I, and the other developer, would receive the following error when opening the solution: “Some of the properties associated with the solution could not be read.”

It took a little digging, but once I looked at the solution file in Notepad++, I saw that there was a duplicate GlobalSection(TeamFoundationVersionControl) = preSolution section. It’s the section that contains all of the parameters prefixed with Scc*. If you delete the duplicate selection it will fix the error.
|

Starting New Project At Work

A few months back I was involved in developing a prototype of an Executive View application, using WPF technology. I wasn’t the biggest fan of the project, mainly due to us using Tangerine, a pre-developed application from Infragistics. While it did help us get the prototype out the door in a timely fashion, I didn’t want us to go the route of just building on top of that application. Luckily we didn’t go that route. It was decided we could use Tangerine as a reference application, which is what I was pulling for from the beginning.

This week will mark the first iteration of The Executive View development. We are doing it in .NET 3.5, with a Silverlight front end. It will be a nice diversion from the project I was working on, which will be nice. I’m not the biggest fan of Silverlight development, mainly because here I am trying to get out of Microsoft development all together, and I’m going to be learning a totally new development environment. At the same time I guess it is pretty cool to be developing using the newest, cutting-edge technology. We’ll see how it goes.
|

Perfect work at home setup - a Mac, VPN, VMWare Fusion

Occasionally I work from home. I used to bring home my work laptop and VPN into work off of it, but we got new machines, and I opted for a desktop. I just like having a desktop for development. It's more powerful, and is cheaper to upgrade.

Since I got a desktop I started working from home a different way. I installed the Cisco VPN software on my Mac, and I also installed Microsoft Remote Desktop Connection. This way I could remote into my machine at work and just work off that machine. There would be an occasional flicker of the screen while it's refreshing, but all-in-all it worked well.

Since I occasionally have to work in Visual Studio .NET 2005, and other times in Visual Studio .NET 2008, I decided to just have those environments running as virtual machines. That way when we go to VS.NET 2008 full time, I won't need to perform an uninstall, I can just delete that virtual machine and start using the VS.NET 2008 virtual machine exclusively. It also helps in the future if my machine gets borked, I can just revert to an earlier snapshot of the VM.

Since I am running off a virtual machine I've found it difficult to work from home using my previous technique. Remoting into a machine, then running a VM on that machine is pretty painful in the lag that occurs.

I decided a better option would be to just get VMWare Fusion for the Mac, and load the virtual machine directly onto my Mac and run it from here. Since I am VPN'd into the company network the VM connects to the domain with no problem (except I have to remember to have my machine at work off the network or I will get an error because of the duplicate machine names on the network). I ordered a copy and just tried it out and it works great. I will try to work some this weekend on the WPF project, and if all goes well, I may just start bringing my Mac to work and working off of it. My goal is to only use Windows for development and Outlook, all other stuff I can just do from my Mac.
|

WPF - Thoughts on first week of use

I've been doing development on our prototype application since the beginning of this week and thought I would give my thoughts I what I think of WPF.

Pros:

It's pretty easy to do things using WPF compared to doing the similar thing in traditional .NET WinForms development. Now, I don't know if this is a case of WPF being a great framework, or WinForms being a bad one; but I'll still consider this a Pro.

Cons:

The tools. Even though WPF has been out a while, the tools used for development still aren't up to snuff. I perform a majority of my XAML development using Expression Blend March 2008 CTP, and all of the C# coding using Visual Studio .NET 2008. In a way this sucks, because, even though Expression Blend is made for doing WPF development, there's no intellisense to be found. Also, it doesn't integrate with a source control system, like Team System, which we use. So I will modify a XAML file and go to save it, then find it's read-only and needs to be checked out. VSTS doesn't have a stand-alone client, I have to fire up Visual Studio to check out the file.

The prototype we are developing is modeled on Infragistics Tangerine example application. This sucks because we're shoe-horning our code into all this existing code. I actually scrapped all the code on the window I am modifying, and also scrapped using their overly complicated XamDataGrid for the built in and easily customizable WPF ListView. Hopefully once we get through with this prototype next week and they show it to the steering committee, and the buy off on it, we can scrap the whole Tangerine application and begin fresh. It's hard to learn a new technology when all you're doing is adding code to an existing application.

Overall I like WPF. I'm not exactly enjoying doing the current development we're doing with it, but it is a nice change of pace.
|

WPF

One of the upcoming features of the application we are working on is called the online experience. We want to provide the higher ups, the directors and managers, with an easy, intuitive look into what's going on at the moment and in the future, in our company. One thing my managers are fans of, which I'm happy about, is eye candy. I don't mean having lots of bling for no reason. But, from working on a Mac, you come to like the eye candy that makes the operating system and it's applications a pleasure to use. I suggested we look into using WPF (Windows Presentation Foundation). I've been pretty impressed with some of the demo applications I've seen, and hopefully we have waited long enough since it's introduction that a lot of the bugs have been ironed out. One thing I really like is this gives us a chance to have a business application that doesn't necessarily have to follow the usual boring business application look-and-feel. It does get boring sometimes working on an application that's just filled with grids displaying information, will be a welcome change to introduce something new.
|

WCF: Underlying connection closed

If you use WCF you may encounter an error with the following text: 'The underlying connection was closed: The connection was closed unexpectedly.' This has to rank up there as one of the most useless error messages you may receive as a developer. It's sort of a catch-all error message. We encountered it twice today, and the only thing in common between our two issues is it was looking like a serialization issue.

I spent about 4 hours or so trying to figure out why one of my classes was having trouble serializing. It finally came down to one of the fields being of type System.Type. Apparently you can't serialize a type of System.Type, because it's an abstract class that inherits from an internal System.RuntimeType class. Now, wouldn't that be a good error message, 'Unable to serialize type: System.Type', instead of the message above that gave no indication as to what was wrong?

The second instance of a team member receiving this error was their serialized object containing more items than is specified in the maxItemsInObjectGraph. Again, wouldn't it be nice to receive an error message, 'Unable to serialize: number of items exceed maxItemsInObjectGraph.'?

If you receive this catch-all error, you should look into anything which can cause a serialization issue.
|

Ruby on Rails Project - To Do List #4

Well, I sure do let a lot of time go by between these posts. For a simple Rails project that will take around an hour or so to code, it's taken over a month to write the posts about it.

When I last left off we had a browser interface that would display a list of Projects, and if you clicked on one of those Projects you would be presented with a page displaying a list of Tasks associated with that Project. This is a great start to a Project Tracking application, but it's missing a big piece...an interface for allowing the user to enter the Projects and Tasks through the web browser. Everything we've added so far has happened from the command line. So, that is what I'll cover this time, adding a user interface for entering this information.

The page used for displaying the Projects is located at /app/views/projects/index.rhtml. The code is pretty simple


<h1>Projects</h1>
<ul>
    <% @projects.each do |project| %>
        <li><%= link_to project.name, :action => 'details', :id => project.id %></li>
    <% end %>
</ul>


We'll add the ability to add new Project to this same page, it will be at the top of the page. The existing projects will be listed below it.

First thing we'll do is update index.rhtml with the following code


<!-- Form for adding a new Project -->
<% form_tag :action => :new do %>
    Project Name: <%= text_field :project, :name %>
    <%= submit_tag 'Add new project' %>
<% end %>


This provides us with a text box and a button wrapped in a form that will submit to the 'new' method in the Project controller. The form should look like this if you view it in the browser at http://localhost:3000/projects/

project_from

Now we need to add the 'new' method to the Project Controller. This is located in /app/controller/projects_controller.rb. Add the following code


def new
  @newproject = params[:project]
  Project.new(@newproject).save
  redirect_to :action => :index
end


This code is pretty simple. When the user submits a new Project name, it comes over in the params object as a hash, with ':project' as the hash name, and ':name' as a key with the value the key corresponds to as the value they entered. Then we call the Save method and redirect back to index, which will redisplay the page with the new Project showing in the list.

This works great, you can add new Projects all day long, but there is an issue. We should have some sort of validation. We should validate that the user actually enters a value before clicking the button to create a project. We should also make sure the Project name they enter is unique. In most instances this would require a lot of coding on the developers part, but not in Rails. This is all taken care of. There are some pre-built validations, we'll use the validates_presence_of and validates_uniqueness_of validations, to check that the value has a length greater than 0 and also that the value is not already present in the database. We just need to add the validation calls to the Project model. The model is located at /app/models/project.rb, update it to look like this


class Project < ActiveRecord::Base
  has_many :tasks

  validates_presence_of :name
  validates_uniqueness_of :name
end


Now if you try to add a blank Project or one with a name already taken, nothing happens. Once we actually work on a layout to make this site presentable we can display error messages, but for the time being not having it save bad data is good enough.

Now we have to repeat the steps above to all the user the ability to add new Tasks to the project. Update the form that displays the tasks, which is located in /app/views/projects/details.rhtml. Add the following code after the <h1> tags


<% form_tag :action => :addtask, :id => @project.id do %>
    Task Name: <%= text_field :task, :name %><br />
    Due Date: <%= date_select('range', 'due_date', : order => [:month, :day, :year]) %><br />
    <%= submit_tag 'Add new task' %>
<% end %>


This gives us a form that looks like this

task_form

Next we add the 'addtask' method to the Project Controller, which will create a new instance of a Task with the information entered by the user, find the Project that the task is going to be associated with, and adds the task to the tasks array of the Project, then it saves the project.


def addtask
  #create task
  @task = Task.new(params[:task])
  @task.is_complete = false

  #add to project
  @project = Project.find_by_id(params[:id])
  @project.tasks << @task
  @project.save

  redirect_to :action => 'details', :id => params[:id]
end


Add the following to the Task model, and you are done.


validates_presence_of :name


We'll allow duplicate task names, but the task does need a name entered.

That's all for this time. Next time we will allow updating and deleting of tasks. Also, we'll need to show overdue tasks.
|

Ruby on Rails Project - To Do List #3

In step two of my PC Task project I created my models for Projects and Tasks. In step three I will move on to the Controllers and Views.

We'll start off with the Projects Controller. Just like we used a script to generate our Model, we can do the same thing with our Controller. The syntax for creating a Controller is

$ ruby script/generate controller controller_name

So, to create our Projects Controller type the following

$ ruby script/generate controller Projects index

You should receive something similar to the following

exists app/controllers/
exists app/helpers/
create app/views/projects
exists test/functional/
create app/controllers/projects_controller.rb
create test/functional/projects_controller_test.rb
create app/helpers/projects_helpers.rb
create app/views/projects/index.rhtml

So, you'll probably notice I added an extra argument on to the end of that command, 'index'. The default name for the file that is accessed when a user visits your site is the index page, so adding this extra argument just created the index.rhtml page for us. If you leave it off, you can always create it later yourself.

Before I move on, I never did define what Model, View, Controller really meant. Here's a couple quick definitions.

Model - handles data and business logic
Controller - handles user interface and application logic
View - handles GUI objects and presentation logic

In a web application the chain of events is

a. Web browser sends a request for a page to the controller.
b. Controller gets the data it needs from the model.
c. Controller renders the page then sends it to the view.
d. View displays the page in the browser.

OK, if you were to start the application, using the following command

$ ruby script/server

and you open a browser and navigate to http://localhost:3000/projects, you should see a page that has the following displayed

Capture2

Now, we need to decide what we want to display in the View, so we can code for this in the Controller. I think at the moment we can just display a list of all the Projects.

Now, before I go any further I want to do a quick introduction to a feature of Rails called Scaffolding. Scaffolding is a tool that can quickly create a view for you that you can use to interact with your model. The view that's created lists all the data in the table and creates an interface for performing your CRUD operations. Scaffolding used to be the selling point of Rails, back when it was the new kid on the block. It's a fun little feature, but I think most developers forgo it for creating their own Controller and View. Scaffolding is very easy. Open the projects controller ($ mate app/controller/projects_controller.rb) and modify the file to look like the following

class ProjectsController < ApplicationController
  scaffold :project
end

Now, save the file and refresh the page in your browser that points to http://localhost:3000/projects. Your web page should now look like this

Capture1

I had created a Test Project in step #2, so it is showing here. As you can see, it has all of the CRUD operations on the screen. This is a cool feature, something I would love sometimes at work in .NET WinForms (I think something similar to this is available in ASP.NET 2008, which is a pretty good clone of Rails, way to innovate again Microsoft), but it's not the route we will take. Instead we will go "our own route".

Modify the Controller file to look like the following

class ProjectsController < ApplicationController
  def index
    @projects = Project.find(:all)
  end
end

Here we define an index action and the find(:all) returns all records in the Projects table. If you refresh the page in your browser you are back to this page

Capture2

We haven't defined any code in our view (index.rhtml), so nothing is displayed yet. We now need to update the View to show a list of Projects. Open the index.rhtml file and update it like so

<h1>Projects</h1>
<ul>
  <% @projects.each do |project| %>
    <li><%= link_to project.name, :action => 'details', :id => project.id %></li>
  <% end %>
</ul>

What all is this doing? @project is an instance variable, he was defined in the Controller. The line with @projects.each do |project| is basically looping through the items stored in @projects, which is the result of the find(:all) command, and storing the current item in project, which is then used when writing out the list. The link_to command is an HTML helper that wraps the item in anchor tags. If you view the page in the browser now you should see the following

Capture3

Not as cool and exciting as what was created by Scaffolding, but it's a start. If you click on the link you will receive an error. This is because we defined an action called 'details' that we haven't defined yet. Let's do that now. Add the following to the Projects Controller.

def details
  @project = Project.find_by_id(params[:id])
  @tasks = @project.tasks
end

This uses the project.id that is passed as id in the parameters and gets the tasks related to that project. Now we need to create a details.rhtml page. Create one in the same directory as index.rhtml and add the following code

<h1><%= @project.name %></h1>
<ol>
<% @tasks.each do |task| %>
<li><%= task.name %> <%= task.due_date %> <%= task.is_complete %></li>
<% end %>
</ol>

Now, if you click on the link on index.html you should see a page similar to the following

Capture4

Not the prettiest page in the world, but it will do for now.

We now have a Controller that will gather the information about the Projects and the associated Tasks, and will display that information in our index and details View.

In step 4 I will add more of the CRUD functionality.
|

Ruby on Rails Project - To Do List # 2

It's been a month since I made the first post for this personal project. What can I say, it was the holidays, and I had other stuff on my mind. I'm still interested in learning Ruby and Rails, so I'm not abandoning the project. Here's part two.

My To-Do List web application is going to start off pretty simple. The first thing I need to do is consider the entities that are needed. To begin I will just have a Project entity and a Task entity. A Project can contain one or more Tasks. A Project will have one attribute, a Name. A Task will have a couple attributes: Name, Due Date, Project ID and an Is Complete flag.

Just like Rails provided us with scripts to generate our directory structure, it also provides us with a script to generate our Model. Remember, Rails is based on the MVC (Model, View, Controller) Design Pattern. The Model creation syntax is

$ ruby script/generate model model_name

Now we create our two Models

$ ruby script/generate model Project
$ ruby script/generate model Task

Here's an example of the output you should receive

exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/project.rb
create test/unit/project_test.rb
create test/fixtures/projects.yml
create db/migrate
create db/migrate/001_create_projects.rb

As you can see, it not only generates our Model, but also the Test files for running our Unit Tests and files for migrating our database changes. This is one thing I enjoy about Rails, you don't have to use a tool to create your database tables and the columns in those tables, you can use the files that are generated. I recommend doing this, since Rails will automatically create Unique ID fields for you.

So, now that we have the Model created, we will add the code to the migrate file to create the columns we need.

If you look at the file 001_create_projects.rb in TextMate, you should see the following

class CreateProjects < ActiveRecord::Migration
  def self.up
    create_table :projects do |t|
    end
  end

  def self.down
    drop_table :projects
  end
end

If we performed a migration with this, it would create a projects table for us, and it would have a Unique ID field, but nothing else. We can modify it to add the fields we need, which is just a Name.

class CreateProjects < ActiveRecord::Migration
  def self.up
    create_table :projects do |t|
      t.column :name, :string
    end
  end

  def self.down
    drop_table :projects
  end
end

The code for 002_create_tasks.rb is

class CreateTasks < ActiveRecord::Migration
  def self.up
    create_table :tasks do |t|
      t.column :name, :string
      t.column :due_date, :datetime
      t.column :project_id, :integer, :null => false
      t.column :is_complete, :boolean
    end
  end

  def self.down
    drop_table :tasks
  end
end

We can now use Rake to apply these changes to the database. You should receive output similar to this

$ rake db:migrate
(in /Users/punkcoder/Development/Ruby/pctask)
== CreateProjects: migrating ==================================
-- create_table(:projects)
  -> 0.0257s
== CreateProjects: migrated (0.0259s) ===========================

== CreateTasks: migrating ==================================
-- create_table(:tasks)
  -> 0.0034s
== CreateTasks: migrated (0.0036s) ===========================

If you go look at the database you should see the tables with the columns. Now we can define the relationships between the tables. Ours is actually pretty simple: a Project has_many Tasks. So, how do we define the relationship? We do it in the Model. Go to app/models/project.rb, it should look like this

class Project < ActiveRecord::Base
end

(Oh yeah, really quick, you notice the < in the syntax above, well, Ruby is an Object Oriented language, and this syntax means Project inherits from ActiveRecord.)

So, to say that Project has many Tasks you pretty much state it

class Project < ActiveRecord::Base
  
has_many :tasks
end

This is a two way relationship, so we also edit app/models/task.rb to say that a Task belongs to a Project

class Task < ActiveRecord::Base
  belongs_to :project
end

Cool, now that we have that set up we can actually test this. Rails has an interactive development environment in the console which we can use. Type the following

script/console

You should see

Loading development environment.
>>

So, the first thing we will do is create a new Project. Rails has created the method we need to do this, it's the 'new' method. To create a new Project type the following

>> project = Project.new(:name => 'Test Project')

You should get the response

=> #<Project:0x24b614c @new_record=true, @attributes={"name"=>"Test Project"}>

We have created a Project named "Test Project". If you go look in the database you won't see anything, because we haven't called Save, instead it's just in memory at the moment. It has been created though, so you can inspect it

>> project.name
=> "Test Project"
>> project.new_record?
=> true
>> project.id
=> nil

Since it hasn't been saved in the database a Unique ID hasn't been assigned. Now, here's the cool part. Remember how we defined that a Project has many Tasks in our Model? Well, if you type the following, you get a nice surprise

>> project.tasks
=> [ ]

That's right, we never added a tasks field to the database, but we set up a relationship, and here it shows an empty array waiting for some tasks.

Now we can save it. Again, just like the 'new' there's also a 'save' method we can call.

>> project.save
=> true
>> project.id
=> 1

Now we have a Unique ID.

Now we can create a task, much like we created a project

>> task = Task.new(:name => 'Test Task 1', :due_date => Time.now, :is_complete => false)

We can't save the task yet, if you call Save you get an error

>> task.save
ActiveRecord::StatementInvalid: MySql::Error: #23000Column 'project_id' cannot be null.

We set the constraint on the project_id field that said it couldn't be null. To save the Task it needs to belong to the Project we created. We can add it using the << operand

>> project.tasks << task

Now you can call task.save and project.save

If you call project.tasks it will list all the tasks. You can access the attributes on the task like this

>> project.tasks[0].name
=> "Test Task 1"

Rails creates methods to allow you to find items in the database for creating an instance of an object. An example of this is

>> test_project = Project.find_by_name('Test Project')

now you can perform the same inspection as before

>> test_project.tasks[0].due_date
==> Sun Jan 13 22:34:17 -0500 2008

Rails actually creates a find for every column, so you can do something like the following

>> test_task = Task.find_by_project_id(1)
>> test_task.name
=> "Test Task 1"

Well, that's enough for now. I'll try not to take another month before writing up Part 3.
|

Ruby on Rails Project - To Do List # 1 (Reprint)

When I lost the files on my backup drive I lost my original blog files, which also meant the history of posts on my site. This is a reprint of part 1 of my Ruby To Do List project, since I am about to post part 2.

Originally posted on Dec 11, 2007...Good thing I'm not this slow at doing development at work Happy

>>

I am finally getting around to starting the personal Ruby on Rails project I wanted to work on, as a way to learn Rails development better. You can only learn so much from a book, real world experience helps a lot.

My plan is to build a simple To Do List application, I'll call it "PC-Task", just to add my Punk Coder touch. I am going to document each step of the process.

The first step is going to be pretty simple, it's just getting everything set up, creating the directory structure and getting the database created.

I am using the install of Ruby and Rails that came pre-installed on Leopard, Mac OS X.

These are: ruby 1.8.6 and rails 1.2.3

I am also using MySQL for my database.

Ruby on Rails has a directory structure which will be created with the following command

$ rails project_name

So, the first thing I will do is create this directory structure

$ rails pctask --database=mysql

Adding the --database=mysql switch will configure the application to use MySQL, saving you a step in editing the file.

I'm not going to list all of the files that get created, but here's what the directory structure looks like

$ cd pctask
$ ls -p

README
app/
config/
doc/
log/
script/
tmp/
Rakefile
components/
db/
lib/
public/
test/
vendor/

The bulk of where we work is in the application directory (app/), which contains the controllers, helpers, models and view directories.

Another important directory is the script/ directory. You will use this a lot in your development. One important thing in there is the server which our application will run on. We will use Mongrel, which listens on port 3000. You start Mongrel with the following command.

$ script/server

Once it's started you can open a browser window and go to http://localhost:3000/. This will bring up a default Welcome to Rails page with some Rails info.

The next thing to do will be to set up the database. I know the geeky thing is to do all your MySQL administration from the command line, but I am going to use a graphical environment called 'CocoaMySQL', a free tool you can find on the web.

I create a couple new databases named 'pctask_development', 'pctask_test' and 'pctask_production', at localhost using the root user. Now that the databases are created, we need to configure the application to connect to it. This is done in the database.yml file located in the config directory. If you open this in TextMate (my editor of choice), you should see a section that looks like this:

$ mate config/database.yml

development:
adapter: mysql
database: pctask_development
username: root
password:
host: localhost

This style of markup is YAML (YAML Ain't Markup Language), which is why it has the .yml extension. It's easy to read and something you use often in Rails development.

Since we used the --database=mysql switch at the beginning the adapter parameter is already filled out for us. Actually, we shouldn't have to make any changes, unless you've changed the default blank password for root user on localhost. If so, fill it out.

Now we can test the database connection. To do this, we will perform a database migration using the rake command. Type the following:

$ rake db:migrate

You should get output similar to the following if all worked well:

(in /Users/punkcoder/Development/Ruby/pctask)

If you receive an error, check to make sure your database is running. You can do this from the command line with the following command:

$ ps -ax | grep mysql

You should receive a couple lines of output showing you the mysql processes that are running. If nothing is running start MySQL

$ sudo /usr/local/mysql/bin/safe_mysqld

If MySQL is running and you receive an error, check the info in database.yml again.

That's all for now. We have the foundation set up to start development.
|

WCF Message Size Limit

My first technology post of 2008!

We ran into an interesting problem at work that I thought I would detail, in case others run into this problem. A little background on our project. Our application is used for the entry and management of contracts. These are entertainment contracts, which can pertain to 1 or more titles. These titles can have multiple rights and restrictions. A lot of contracts are pretty simple, but some can get complex, containing a large amount of data. In our testing we ran into one of these kinds of contracts. It was for a long running show, so it contained all the episodes ever aired, which was around 460 episodes. Now, add to that a couple rights that pertain to each episode and a couple restrictions, plus we attached a copy of the real contract in PDF form, which was around 860k in size. When we tried to save the contract it bombed quickly not giving any indication of what occurred. When we looked at the Request Message in Fiddler we saw that it was a little over 4MB in size and it looked fine, so no red flags there. We checked the trace logs and it didn't provide us with any answers, just an error message saying the server connection closed unexpectedly. We also looked at the app.config and the web.config settings to check if all the maxMessageLengths and maxBuffers were set to their maximum, along with high timeouts. All of this looked fine. Searching the web provided us with no answers, so we did some testing. We created a new contract that contained no rights or restrictions and we attached one instance of the PDF. This saved fine. We then attached 2 PDFs, then 3PDFs, and it finally failed once we hit 4 PDFs. This caught our attention because the size of the message we saw in Fiddler before was around 4MB and now this contract with 4 PDFs was around that size too. Still, 4MB seemed small, since all of the maxLengths in the config files are Int32, meaning their maximum value is 2GB. Now that we had this info I did a search and found a couple interesting things. MSMQ has a maximum message size of 4MB. This was interesting, but we weren't using MSMQ, so I looked elsewhere. That's when I ran into ASP.NET having a limit of 4MB for files being transmitted. This is apparently a safety feature to prevent DOS attacks. While we aren't using ASP.NET we are using WCF services with wsHTTP, so I figured it was worth a shot. I went into the web.config and added the following line in the System.Web section

<httpRuntime maxRequestLength="32678"/>

This set the max length of a Request to 32MB.

Once this was added we ran the same test we had before and the contract saved with no issues. We researched this issue over the course of a couple days and were fearing the worst. We thought we may have to re-architect the entire way we passed around data. In the end we were glad to see it was 1 line that fixed everything.
|

Almost launch time

Tomorrow is our final build, barring any major bugs that need to be fixed, before our soft launch to a few customers next week. It's amazing how this agile development has produced a very usable application. We've spent the past couple iterations doing a lot of front end work. The back end and services seem to be working well, we haven't had to touch any of the code in a while. We've learned a lot about agile development along the way. We've gotten better at many aspects so it doesn't seem as overwhelming as it sometimes felt. We still have a lot of development to do, this is just us getting it in front of the users so they can start banging on it, giving us feedback.
|