Sponsors

The Lounge

Wicked Cool Jobs

Current Bloggers

Partners

 

Wikis

  • You have not yet contributed to any pages.

Open Source Whining

Posted by Tim Barcz, Wednesday, July 28, 2010 (3,652 views)

Was working on a blog post talking about a problem I’ve found in Git (1.7.0.2) and I thought I would check to see if it’s been fixed in the most recent version.  After downloading and installing I reviewed the release notes where I’m quite shocked to read the following:

“…All hopes to the contrary, Git for Windows is backed by only a handful of developers, in spite of being downloaded almost one hundred thousand times. You can expect developers to be enthusiastic to fix others' issues in such a situation only for so long. In short: Do not expect other people to fix your issues for you.”

Basically, what I get from this is that the msysgit committers are a bunch of whiners. What they fail to see is that the people who would benefit from their VCS may not have the same skillset to work on the code.  This is something we’ve realized long ago with Rhino Mocks

Should more people help? Possibly. As someone active in open source technology I don’t know that I can be of much assistance to the Git team – I am someone who benefits greatly from their software (I am quite thankful for it) but don’t have the requisite knowledge in C/C++ to assist in any meaningful fashion.

Just a bit disappointed to see this type of whining in their release notes – certainly there are far better ways to say what they’re trying to say.  Doesn’t represent msysgit or the broader open source community well.

Discuss (18)

Best Error Dialog ever w/ Visual Studio

Posted by Derik Whittaker, Wednesday, July 28, 2010 (345 views)

Today I received the following error and thought it summed up my day perfectly.

image

 

Now the real question is what was I doing to receive this error…… I was trying to copy a single line (w/ 50 characters of text) to the clipboard…DOH

Till next time,

Filed under:
Discuss (3)

CodeBetter/Devlicio.us/LosTechies MSDN Ultimate Giveaways

Posted by Tuna Toksoz, Tuesday, July 27, 2010 (3,599 views)

UPDATE: I have added subscription donors/contributors who made this possible.
UPDATE: Our friends from
LosTechies also wanted to participate, and they donated a number of licenses (6 and counting). Thank you guys!

In an internal discussion we had, an interesting idea popped up. MVP bloggers we had at CodeBetter/Devlicio.us were generous enough to donate some of their MSDN subscriptions they were given as part of MVP program. Then the cool kids at LosTechies stepped in, and donated a number of licenses as well! Currently we have 13-16 licenses available, and this number may change depending on the demand and outside donations. The subscriptions are for one year.

We decided to give them away to successful/promising OSS projects that are in need of licenses. The rules are simple.

  1. The project has to be opensource
  2. The project has to be in need of MSDN license. We’ll trust your word in this.
  3. The selection will be based on our discretion, we’ll do our best on being fair.
  4. We may change the number of licenses available during the selection progress.

You can send me an email (tehlike (hat) gmail (hot) com) with title starting with [CDL/MSDN] (or [CD/MSDN]), or DM me on twitter (@tehlike) if you want to participate. You have to include

  1. Public URL for the project page
  2. Your name and your position in the project

It wouldn’t have been possible with the help of following fellow bloggers. Thanks to Codebetter Crew: Ben Hall, Ward Bell, James Kovacs. Devlicious Crew: Hadi Hariri, Christopher Bennage, Tim Barcz, Rob ReynoldsLostechies Crew: Eric Hexter, Jimmy Bogard, Keith Dahlby

Good luck!

Filed under: ,
Discuss (6)

How to detect the theme being used in WP7

Posted by Derik Whittaker, Tuesday, July 27, 2010 (162 views)

As the Windows Phone 7 have either a dark (black) or light (white) theme which can be applied it will become very important for you to know which theme the user enabled in order to determine your applications color schema, this is assuming you are using styles which are not built into the skinning on WP7.

Sadly detecting the current theme is a bit hackish as it requires you to take a look at a current loaded resource to determine the theme.  I would have hoped that this would be part of the built in SDK as I see this as a common need for many applications.

Here is how you determine which theme is being used.

Color themeColor = (Color)Application.Current.Resources["PhoneForegroundColor"];
        
if (themeColor.ToString() == "#FFFFFFFF")
{
    this.PageTitle.Text = "Dark ";       
}
else if (themeColor.ToString() == "#DE000000")
{
    this.PageTitle.Text = "Light ";    
}

As you can see the code to determine the theme is easy, but not clean in my opinion.

Till next time,

Filed under:
Discuss (0)

YouTrack for OSS Projects

Posted by Hadi Hariri, Monday, July 26, 2010 (260 views)

Quite some time ago, several OSS leads asked us about whether JetBrains could provide OSS license for YouTRACK. We’ve taken it one step further, and in collaboration with the great folks at CodeBetter and Devlicio.us, we are pleased to announce YouTRACK at CodeBetter. Having TeamCity running most of the OSS projects on there, it only made sense to offer the same facilities for issue tracking at the same location. And seeing that YouTRACK integrates with TeamCity, we can offer all the functionality the combination is capable of.

 

image

 

I’d like to thank Kyle Baley, James Kovacs and Bredan Tompkins for making this possible, as without their support this wouldn’t happen. Not only are they generous in hosting YouTRACK, but also ran the risk of providing me with the credentials to the server, and at one point it looked like it had all gone to hell. Luckily however all seems to be working great now.

What are the next steps?

If you are an OSS project lead and  would like to use YouTRACK for your issue tracking, please email teamcity@codebetter.com with your details and you’ll be up and running in no time. If you want to learn more about YouTRACK, please visit our web site.

Filed under:
Discuss (2)

The Future of .NET Open Source Software Delivery

Posted by Rob Reynolds, Monday, July 26, 2010 (5,931 views)

Imagine we are awhile into the future. How do you get open source releases down to your project so that you can use them? How do you get the products down to your computer so that you can use them? Is it easier or harder than the way we’ve always done it before?

The Past and Present

Before we can go there, let’s look at what we do now (the past is really the same for us here). Let’s say I want to use NHibernate. What do I do?  There are basically three paths we all follow in this process.

1. Never had product x before. If I don’t have a current version, I have to go out and look for it. So what do I do?

  • Open a browser
  • Find the site
  • Find the downloads
  • Find the particular download I want through the plethora of options that may be presented to me
  • Download it
  • Unzip it
  • Then put it into my project references folder somewhere so I can keep it in source control with my project

2. Use the current version without upgrade. If I have a current version, I may just copy it over and use it in my new project. Nevermind that it is two versions ago. I don’t want to take the time to upgrade because it could be a pain.

  • Open file explorer and find the project with the old version
  • Open file explorer and find the new project
  • Create the structure I need for the references folder
  • Copy the contents of the old project to the new project

3. Upgrade. If I find a bug or I decide it’s time to upgrade to a newer version, how do I get it? Repeat the process of #1 (Never had product x before) and getting the latest version.

Problems with the Present Method of Delivery

It's slow. How long did it take me to get all of that? Yeah, now multiply times every library I want to use.

Too many decisions. I have to make way to many decisions to get the right product and right version downloaded and referenced into my project.

Dependencies may be hard to manage. I may be using projects that depend on the same libraries. In the example above I am using Castle in my project. That got upgraded as well when I got the latest version of NHibernate. Now I may have to test the changes to that. What if the latest version of Castle Windsor I am using is not compatible with the latest version of NHibernate? I won’t see that issue necessarily until I try to run my code. I can try binding redirects, but there is no guarantee that that will work. So now I have a problem. I have to figure out what version of Castle Windsor to use so that I can use the latest version of NHibernate. And this is where dependency management is fully placed on me as a developer. I can now decide to move forward or just continue to use the old version.

Too easy to just continue using the same version you have. It's way too easy to keep using the version you first downloaded and never learning about all of the awesomeness that comes with more current versions of the product.
 
Unfortunately for a lot of people, what I just mentioned with projects that have dependencies on the same things as other projects is the biggest barrier to using OSS (Open Source Software). So let’s talk about the future.

The Future

So now that we have looked at how we currently do it, how will it be in the future?

Open source developers will publish their latest releases to a central repository (possibly in addition to other methods of offering releases).  Then everyone can get their latest releases and develop from there.

Same three scenarios.

1. Never had product x before. Here’s the process.

  • Know what I’m looking for and confirm the name at the central repository
  • open a command line
  • type something to the effect of nu install nhibernate

And I’m done. It’s all brought to me and sitting in my references folder of my project.

2. Use the current version without upgrade. This is still an option. Same as in the present described above.

3. Upgrade. Here’s the process.

  • open a command line
  • type something to the effect of gem update
  • type something to the effect of nu install nhibernate

What Issues Does the Future Method of Delivery Address?

Speed. The process is amazingly streamlined. We are talking seconds as compared to minutes of time to get something. I can now concentrate on what I want to do instead of spending all the time I was on just getting the packages I needed.

The decision tree is reduced. How many decisions did I have to make to get what I needed in the present scenario? How about the future scenario? Greatly reduced.  Less choices to get what I want actually gets me to a decision faster.

I immediately see the dependency changes. All of the dependencies that are required come along nicely with NHibernate. I can immediately see that it downgraded my versions of Castle Core and Dynamic Proxy2. So now I know immediately that I have a problem between Castle Windsor and NHibernate using different versions. It doesn’t solve my problems on this, but it brings it to the surface. So now I can try something like the aforementioned binding redirects.

The process of upgrade became easier than use the current. Another thing you may have noticed. It actually becomes easier to upgrade to the latest version as compared to #2 (Use the current version). That will move people to upgrade, because people will choose the easiest path to get them on their way. And when everyone using the latest version, everyone wins.

The Future Is Now

Oh yeah, the future? It’s now. http://groups.google.com/group/nu-net

Related Posts

Before you comment about “cluttering” the ruby community, please be sure to read this (we’re with you on this):  http://devlicio.us/blogs/rob_reynolds/archive/2010/07/19/gems-for-net-community-response.aspx

Gems - Package Management for .NET 

How To – Gems & .NET & How To – Gems & .NET - Dependencies (References)

Walkthrough - Create Gems Even Easier With a Conventional Build (UppercuT)!

Discuss (11)

Dynamically Changing Resources in a ListBox using Binding and Converters

Posted by Derik Whittaker, Saturday, July 24, 2010 (2,323 views)

While working on an application targeted towards WP7 I wanted to have the application change style resource which was attached to a border element based on a value (aka a status) in my view model.  After searching around for a bit I was not able to come up w/ a complete end to end solution, only bits and pieces.  In order to help the next poor newbie I thought I would post my solution (btw, there may be a MUCH better solution than this out there).

In this sample I simply created a test application based off of the Item List Template which comes out of the box with a few minor changes.

 

Setting up the XAML

image

 

The important item to pay attention to above is the highlighted line.  This is the line which will change the border brush via the converter based on the value in the ‘Color’ property in my view model. 

Changes to the View model

image

The code above is the property I added which will allow us to trigger the border brush to determine what style to use

 

Creating the Converter

image

 

The above is a pretty standard converter which uses the IValueConverter interface.  The Part in here it pay attention to is how I am grabbing the brush resources out of the App.xaml file (there may be a better way to do this, but i could not find this).  What this code does is basically determines which loaded resource to return based on the value passed into the converter

 

Registering the Converter

image

Once you create your converter class (see above) you do need to register it in your app.xaml class.  Do do this simply follow the logic above.

 

Creating the Brush Resources

image

The code above will create the various resources needed to allow us to change the color of our item in XAML

Populating the ‘live data’

 

 

 

 

image

The default template for the Item List project has all the data hard wired in the MainViewModel class.  I simply added the above logic to populate the color properties.

 

After you put all the above together you get….

image

Notice how the little colors next to each item change, this is our doing :) Now of course this is a simple example, but it does go to prove how you can accomplish this.

Till next time,

Filed under: ,
Discuss (7)

Semi final release – Windsor 2.5 beta 2 (now with Silverlight support)

Posted by Krzysztof Koźmic, Wednesday, July 21, 2010 (428 views)

A bit later than expected (ah, work) I published beta 2 of Windsor 2.5 today. The release has the following changes as compared to beta 1.

  • Silverlight version (for Silverlight 3 and Silverlight 4) is now included in the package.
  • Synchronize Facility is now included in the package (.NET only)
  • The following code changes and fixes were made (incl. one breaking change)

    - added support for selecting components based on custom attributes and their properties. See Component.HasAttribute<T>() methods

    - added WithService.DefaultInterface() to fluent API. It matches Foo to IFoo, SuperFooExtended to IFoo and IFooExtended etc. If you know how DefaultConvention works in StructureMap, this is pretty similar

    - added support for CastleComponentAttribute in fluent API. Also added helper filter method Component.IsCastleComponent

    - added ability to specify interceptors selector as a service, not just as instance

    - added ability to specify proxy hook in fluent API

    - indexers on IKernel are now obsolete.

    - added WithAppConfig() method to logging facility to point to logging configuration in AppDomain's config file (web.config or app.config)

    - BREAKING CHANGE: Restructured lifecycle concerns - introduced ICommissionConcern and IDecommissionConcern and favors them over old enum driven style.

    - Fixed how contextual arguments are handled. Null is no longer considered a valid value (That would cause an exception later on, now it's ignored).

    - Changed method DeferredStart on StartableFacility. It now does not take a bool parameter. A DeferredTryStart() method was introduced instead.

     

This is probably the last pre-release for 2.5 and if no critical issues are found, we’ll release final release in 2, 3 weeks. Go grab the bits, see if it works for you and if it does not report back. I’m also looking for people who want to contribute sample applications for the final release. Ping me if you’d like to contribute to that.

Filed under: ,
Discuss (3)

Writing plug-ins for ReSharper: Part 2 of N

Posted by Hadi Hariri, Tuesday, July 20, 2010 (719 views)

[Finally I’ve managed to get the second part of the post on plug-ins. Sorry for the delay to everyone who was waiting. Appreciate your patience.  And now I’ll resume my holidays!]

In the previous part of this series, we saw the basics of how to create a plug-in for ReSharper, install it and run it. We created a context action that would allow us to mark a public method as virtual (where applicable). However, this was done as an explicit action by the user, as such, you didn’t get any kind of hint or suggestion to do this. What we want to do now is make this a hint, so that highlighting appears under methods that could be made virtual. In this part we are going to expand on the same plug-in and convert it into a QuickFix.

What is a QuickFix?

Have you seen the little squiggly lines that appear in Visual Studio?

image

They usually indicate a Suggestion (field can be made read-only), Warning (possible null reference) or Error. ReSharper analyzes and can detect potential issues in the code (similar to what static checker of Code Contracts does). These are known as Highlights and they are related to QuickFixes in that usually a highlight has an QuickFix associated to it, which invokes a context action. This is usually done by placing the cursor on top of the highlighting and press Alt+Enter

image

 

Highlighting Daemons

In the gutter of the Visual Studio editor (right-side), ReSharper displays a series of warnings, errors and hints, which indicate potential issues on a specific file. These issues are detected by background processes known as Daemons. Since what we are looking for is for ReSharper to warn us of existing methods that could be made virtual, what we need to do is somehow hook into these daemons.

image

 

Step by Step Guide

The Daemons in ReSharper use the Visitor pattern to use act on elements, be it code, files, etc. The first step is to implement an IDaemonStage interface, which hold metadata about our daemon stage at at the same time acts as a factory for the actual process we are implementing.

[DaemonStage(StagesBefore = new[]  { typeof(LanguageSpecificDaemonStage) })]
 public class MakeMethodVirtualDaemonStage: IDaemonStage
 {
     public IDaemonStageProcess CreateProcess(IDaemonProcess process, DaemonProcessKind processKind)
     {
         return new MakeMethodVirtualDaemonStageProcess(process);
     }

     public ErrorStripeRequest NeedsErrorStripe(IProjectFile projectFile)
     {
         return ErrorStripeRequest.STRIPE_AND_ERRORS;
     }
 }

There are two main methods to implement. The CreateProcess is what creates the actual process for us and the NeedsErrorStrip which indicates whether this daemon uses the gutter to display strips. The DaemonProcessKind parameter passed into the first method helps us discriminate on when this process should be executed, i.e. only during checking of visible (current) document, during solution wide analysis, etc.

The next step is to implement the process via the IDaemonStageProcess interface:

  public class MakeMethodVirtualDaemonStageProcess : IDaemonStageProcess
  {
      readonly IDaemonProcess _process;


      public MakeMethodVirtualDaemonStageProcess(IDaemonProcess process)
      {
          _process = process;
          
      }

      public void Execute(Action<DaemonStageResult> commiter)
      {
          if (_process.InterruptFlag)
          {
              return;
          }


          var file = _process.ProjectFile.GetPsiFile(CSharpLanguageService.CSHARP) as ICSharpFile;

          if (file != null)
          {
              var highlights = new List<HighlightingInfo>();

              var processor = new RecursiveElementProcessor<IMethodDeclaration>(declaration =>
              {

                  var accessRights = declaration.GetAccessRights();

                  if (accessRights == AccessRights.PUBLIC && !declaration.IsStatic && !declaration.IsVirtual &&
                      !declaration.IsOverride)
                  {
                      var docRange = declaration.GetNameDocumentRange();

                      highlights.Add(new HighlightingInfo(docRange, new MakeMethodVirtualSuggestion(declaration)));
                  }
              });

              file.ProcessDescendants(processor);
              
              commiter(new DaemonStageResult(highlights));
          }

      }

      
  }

The main meat of this class is in the Execute method. We first check to make sure that we’ve not received an interruption (Interrupt Flag raised) due to some external action. Next step is to get access to the current file (remember that we are visiting the entire visible document, not just a specific method). Having the file, we can now create a RecusiveElementProcessor* to perform a tree walk of the AST and perform the specific action on each element. The action to perform is declared as the lambda expression. Since we’re interested in the method declaration, the type is IMethodDeclaration (there are many others). If we look at the expression, we can see that it’s pretty much the same as that of Part 1, the only difference is that we add the results to the highlighting variable.

The HighlightingInfo class has a parameter which can be a Suggestion, Warning or Error, as explained previously. Since in our case we need a suggestion, we pass in the MakeMethodVirtualSuggestion:

[StaticSeverityHighlighting(Severity.SUGGESTION)]
 public class MakeMethodVirtualSuggestion : CSharpHighlightingBase, IHighlighting
 {
     public ICSharpTypeMemberDeclaration Declaration { get; private set; }

     public MakeMethodVirtualSuggestion(ICSharpTypeMemberDeclaration memberDeclaration)
     {
         Declaration = memberDeclaration;
     }

     public string ToolTip
     {
         get { return "Method could be marked as virtual"; }
     }

     public string ErrorStripeToolTip
     {
         get { return ToolTip; }

     }

     public override bool IsValid()
     {
         return Declaration.IsValid();
     }

     public int NavigationOffsetPatch
     {
         get { return 0; }
     }
 }

This class is pretty simple. The main property to define is the ToolTip, which is the text that will show when we hover of the highlighting. The ErrorStripeToolTip is what’s displayed in the right-hand side gutter. Finally the Attribute StaticSeverityHighlighting is to indicate what type of tip it is (Warning, Error, etc.).

 

[*Note: In this case, the operation we want to perform is very simple. If we want a more complex scenario where we need to do some processing before and after each element is visited or have a more fine-grained control, we can implement the IRecurisveElementProcessor. I’ll cover this in another post]. 

 

To recap, right now we would have everything place to display highlighting when a method that could be made virtual is encountered. The only remaining part is to now be able to apply a QuickFix. This is in many ways similar to the ContextAction we saw in Part 1:

[QuickFix]
public class MakeMethodVirtualQuickFix : BulbItemImpl, IQuickFix
{
    readonly MakeMethodVirtualSuggestion _highlighter;

    // Takes as parameter the Highlighter the quickfix refers to
    public MakeMethodVirtualQuickFix(MakeMethodVirtualSuggestion highlighter)
    {
        _highlighter = highlighter;
    }

    // In the transaction we make the necessary changes to the code
    protected override Action<ITextControl> ExecuteTransaction(ISolution solution, IProgressIndicator progress)
    {
        _highlighter.Declaration.SetVirtual(true);

        return null;
    }

    // Text that appears in the context menu
    public override string Text
    {
        get { return "Make Method Virtual"; }
    }

    // Indicates when the option is available
    public bool IsAvailable(IUserDataHolder cache)
    {
        return _highlighter.IsValid();
    }
}

The MakeMethodVirtualQuickFix needs to implement the IBulbItem and IQuickFix interfaces. For ease of implementation we can inherit from BulbItemImpl. The constructor should take as parameter always the actual highlighting that has given way to invoking the QuickFix, in our case the MakeMethodVirtualSuggestion. Similar to the ContextAction we implemented in Part 1, the actual fix itself is pretty trivial. All we need to do is make the method virtual. How do we get access to the method? The easiest way is via the Declaration property of the highlighting passed in (this is a property we added before). The only thing left is to call the SetVirtual method on it. Since we are in the ExecuteTransaction method, ReSharper makes sure that any change made is executed as a whole.

The rest of the properties are trivial. Text returns the text of the QuickFix (what appears in the menu), and IsAvailable indicates when the QuickFix is available, which in our case is whenever the highlighting is valid.

 

The End Result

Once we compile the plug-in and place it in the corresponding Plugins folder under ReSharper\Bin, we’re done. Here’s the end result:

image

and invoking Alt+Enter on the highlighting gives us:

 

image

 

Summary

Extending ReSharper to create highlightings and quick fixes is pretty simple once you understand how all the pieces fall into place. Most of the code will usually be the same and what will vary will be the actual element processing to be performed and the corresponding QuickFix. As mentioned previously (in the Note), for complex scenarios, we can have more control over the tree walk and that’s something we’ll examine in a future post.

I’ve placed the code up on my github account so feel free to download it, play with it and ping me if you have any comments or questions. The code is updated to work with ReSharper 5.1

Filed under: ,
Discuss (1)

How To – UppercuT and Gems

Posted by Rob Reynolds, Tuesday, July 20, 2010 (743 views)

In a previous post I mentioned how I was going to show you how UppercuT (UC) has the ability to make gems stupid simple to create and publish. You ask if gems can get any easier and to that I answer, “Why YES, they can!” How about just filling out the information for the gemspec, running a build and having a nice, shiny new gem ready for publishing?

Rock The Gems

Basically you want to get the latest release of UppercuT. You can download it or grab the source and compile.

There are already instructions out there for how to get UC in your project, so I’m not going to concentrate on that.

Once you upgrade (or add and get everything else set up), you want to have this gems folder at your top level (just under trunk or branch name).

gems folder at the top level

In that gems folder you are going to find a file named something like the file below. Rename that file to your new gemname.gemspec.

Note: Once you have a gemspec file in a gems folder, your build server NOW needs to also have ruby and gems installed.

Open that file in your favorite text editor and fill in the details. Here’s a good post on how to do that.

Rename the file to gemname.gemspec Open in a text editor and edit the gemspec according to your needs

Then just for having the gems folder with a gemspec in it, UC will automatically try to build the gem for you (the code in your code_drop/projectname folder is brought over to code_drop/gems/lib folder).

code_drop/gems 

Gem gets built with the correct version

Removing All of the Other Output After the Gem is Built

Once we are good with what we are getting back for the gem, we can start cleaning up. So we go into our build.custom (don’t have one? create it right next to the build folder) folder and create a file named gemsBuild.post.step.

build.custom/gemsbuild.post.step

Let’s open the file and insert this:

<?xml version="1.0" encoding="utf-8"?>
<project name="CUSTOM POST GEMSBUILD" default="go">
  <!-- Project UppercuT - http://projectuppercut.org -->
  <property name="build.config.settings" value="__NONE__" overwrite="false" />
  <include buildfile="${build.config.settings}" if="${file::exists(build.config.settings)}" />
  <property name="dirs.current" value="${directory::get-parent-directory(project::get-buildfile-path())}" />
  <property name="path.to.toplevel" value=".." />
  <property name="folder.code_drop" value="code_drop" overwrite="false" />
  <property name="dirs.drop" value="${dirs.current}\${path.to.toplevel}\${folder.code_drop}" overwrite="false" />
  <property name="folder.gems" value="gems" overwrite="false" />
  
  <target name="go" depends="run_tasks" />
  
  <target name="run_tasks">
    <delete>
      <fileset basedir="${dirs.drop}/${folder.gems}" >
        <exclude name="*.gem" />
        <include name="**/*" />
      </fileset>
    </delete>
  </target>
  
</project>

Note: Don’t like NAnt? You can also use Ruby or PowerShell instead of NAnt to write your custom extensions.

Now when we run our build again, we have a nice clean folder.

All clean - just the built gem. Nice...

 

What If I Want to Change What Goes Into my Gem?

Interested in influencing what goes INTO your gem in the first place? That’s a pretty good thing to be concerned with so that you don’t have all of your referenced assemblies sitting in there. Read about how to set up dependencies. Then you will create a file next to gemsbuild.post.step named gemsPrepare.post.step.

build.custom/gemsPrepare.post.step

In that file, you will insert something similar to the following (roundhouse file):

<copy todir="${dirs.drop}\${folder.gems}\lib">
  <fileset basedir="${dirs.drop}\${folder.gems}\lib\MSBuild">
    <include name="**/*.*" />
  </fileset>
</copy>

<copy todir="${dirs.drop}\${folder.gems}\lib">
  <fileset basedir="${dirs.drop}\${folder.gems}\lib\NAnt">
    <include name="**/*.*" />
  </fileset>
</copy>

<delete>
  <fileset basedir="${dirs.drop}\${folder.gems}\lib" >
    <include name="ConsoleApp/**" />
    <include name="MSBuild/**" />
    <include name="NAnt/**" />
  </fileset>
</delete>

Learn More

With this knowledge, you shall build. Interested in more UppercuT? Check out the ChuckNorris framework and join the group.

 

Related Posts

Before you comment about “cluttering” the ruby community, please be sure to read this (we’re with you on this):  http://devlicio.us/blogs/rob_reynolds/archive/2010/07/19/gems-for-net-community-response.aspx

Gems - Package Management for .NET 

How To – Gems & .NET & How To – Gems & .NET - Dependencies (References)

The Future is Now!

Discuss (3)

Gems For .NET – Community Response

Posted by Rob Reynolds, Monday, July 19, 2010 (986 views)

There has been a lot of response in the community about this gems idea we’ve been talking about. I even had the opportunity to sit down with Nick Quaranto, the guy behind Rubygems.org, over coffee Sunday and talk about where we think we are going and what it will take to get there.

One of the biggest things that everyone wants to see carrying this idea forward is that we migrate off of Rubygems.org and have our own gem server. And we all agree this is a great idea. There are just two things that really keep that from happening at the current moment. The devil is in the details and when we are ready to move off to our own server, it’s real money at that point (to do it right).

Right now we are embracing the idea of “one community,” and we are certainly not the first non-ruby community to use RubyGems.org. Long term a different host for the .net gems will be both necessary and beneficial. As we move off, we’ll be able to even expand some of the things we can do as far as checking gems as they are published to make sure they meet certain constraints. 

If you are concerned about getting started versus later migrating – the process will be well thought out and seamless for the user experience of getting your gems and pushing them. The user experience is still going to be rock solid, and the same concept of gem install gemname is going to be there no matter what happens.

And for you gem owners – we’ll be working closely with Nick to ensure that the process is still rockstar.

The more community involvement there is from you and others like you, the faster we move to our own servers. And as far as when, well that all depends on you.

Filed under: ,
Discuss (12)

My Objective Today is to Make You Think

Posted by Jak Charlton, Monday, July 19, 2010 (1,042 views)

 

"Maybe There is a Better Way"

I recently presented at DeveloperDeveloperDeveloper in Sydney, and although my talk was Stuff About CQRS, I opened with the slide 

My Object Today Is to Make You Think ... 'Maybe There is a Better Way'

(slides here)

The real focus of this was around how normal people think, and how unlike normal people we developers really are. My role in development is all about enabling better communication, because fundamentally I believe the real value a developer brings to a project is not technical, but is in the way they interact with the team, and more importantly with the normal people they are actually creating software for.

Obviously some of this has roots in DDD, the Ubiquitous Language is obviously an attempt to traverse this chasm that seems to exist between us.

Then I touched on user interfaces, and how they are so rarely designed the way people think - normal people think about their objectives and goals, not in terms of data like we developers do. Inductive UIs are focused on tasks, unlike the traditional data driven UIs that we tend to throw at users - users and people don't think in grids and columns and rows, they think "I want to change my address", not "open my customer record, edit the three fields under address and save to the database" - only a sadist or a developer would think that way.

And finally I touched on things like NoSQL databases, which neatly solve a communication problem - they stop us thinking about How to store information and let us focus on What we are storing and Why.

And lastly I tried to show the link between CQRS and these business problems - how it made you focus on the language, on tasks and objectives and how it let you detach the How from the What and Why.

But most importantly, what I was trying to do in that presentation was to throw some non-mainstream ideas out into the audience, to spark discussion and debate, and to get people to think - Maybe There is a Better Way  

If only a few of those in the audience went away and Googled some of the ideas I was talking about, it will be another step towards moving development away from it's heavy focus on technology and technological solutions - and towards a people and business driven focus, where technology is an artifact, not the deciding factor.

 

 

Filed under: , , ,
Discuss (3)

Caliburn.Micro Soup to Nuts Pt. 3 – All About Actions

Posted by Rob Eisenberg, Saturday, July 17, 2010 (2,056 views)

We briefly introduced actions in Pt. 1, but there is so much more to know. To begin our investigation, we’ll take our simple “Hello” example and see what it looks like when we explicitly create the actions rather than use conventions. Here’s the Xaml:

 

<UserControl x:Class="Caliburn.Micro.Hello.ShellView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:cal="http://www.caliburnproject.org">
    <StackPanel>
        <TextBox x:Name="Name" />
        <Button Content="Click Me">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cal:ActionMessage MethodName="SayHello" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </StackPanel>
</UserControl>

 

As you can see, the Actions feature leverages System.Windows.Interactivity for it’s trigger mechanism. This means that you can use anything that inherits from System.Windows.Interactivity.TriggerBase to trigger the sending of an ActionMessage.*  Perhaps the most common trigger is an EventTrigger, but you can create almost any kind of trigger imaginable or leverage some common triggers already created by the community.  ActionMessage is, of coarse, the Caliburn.Micro-specific part of this markup. It indicates that when the trigger occurs, we should send a message of “SayHello.”  So, why do I use the language “send a message” instead of “execute a method” when describing this functionality? That’s the interesting and powerful part.  ActionMessage bubbles through the Visual Tree searching for a target instance that can handle it. If a target is found, but does not have a “SayHello” method, the framework will continue to bubble until it finds one, throwing an exception if no “handler” is found.** This bubbling nature of ActionMessage comes in handy in a number of interesting scenarios, Master/Details being a key use case. Another important feature to note is Action guards. When a handler is found for the “SayHello” message, it will check to see if that class also has either a property or a method named “CanSayHello.” If you have a guard property and your class implements INotifyPropertyChanged, then the framework will observe changes in that property and re-evaluate the guard accordingly. We’ll discuss method guards in further detail below.

Now you’re probably wondering how to specify the target of an ActionMessage. Looking at the markup above, there’s no visible indication of what that target will be. So, where does that come from? Since we used a Model-First approach, when Caliburn.Micro (hereafter CM) created the view and bound it to the ViewModel using the ViewModelBinder, it set this up for us. Anything that goes through the ViewModelBinder will have its action target set automatically. But, you can set it yourself as well, using the attached property Action.Target. Setting this property positions an ActionMessage “handler” in the Visual Tree attached to the node on with you declare the property. It also sets the DataContext to the same value, since you often want these two things to be the same. However, you can vary the Action.Target from the DataContext if you like. Simply use the Action.TargetWithoutContext attached property instead. One nice thing about Action.Target is that you can set it to a System.String and CM will use that string to resolve an instance from the IoC container using the provided value as its key. This gives you a nice way of doing View-First MVVM if you so desire. If you want Action.Target set and you want Action/Binding Conventions applied as well, you can use the Bind.Model attached property in the same way.

Let’s see how we would apply this to achieve MVVM using a View-First technique (gasp!) Here’s how we would change our bootstrapper:

 

public class MefBootstrapper : Bootstrapper
{
    //same as before

    protected override void DisplayRootView()
    {
        Application.Current.RootVisual = new ShellView();
    }

    //same as before
}

 

Because we are using View-First, we’ve inherited from the non-generic Bootstrapper. The MEF configuration is the same as seen previously, so I have left that out for brevity’s sake. The only other thing that is changed is how the view gets created. In this scenario, we simply override DisplayRootView, instantiate the view ourselves and set it as the RootVisual (or call Show in the case of WPF). Next, we’ll slightly alter how we are exporting our ShellViewModel, by adding an explicitly named contract:

 

[Export("Shell", typeof(IShell))]
public class ShellViewModel : PropertyChangedBase, IShell
{
    //same as before
}

 

Finally, we will alter our view to pull in the VM and perform all bindings:

 

<UserControl x:Class="Caliburn.Micro.ViewFirst.ShellView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:cal="http://www.caliburnproject.org"
             cal:Bind.Model="Shell">
    <StackPanel>
        <TextBox x:Name="Name" />
        <Button x:Name="SayHello"
                Content="Click Me" />
    </StackPanel>
</UserControl>

 

Notice the use of the Bind.Model attached property. This resolves our VM by key from the IoC container, sets the Action.Target and DataContext and applies all conventions. I thought it would be nice to show how View-First development is fully supported with CM, but mainly I want to make clear the various ways that you can set targets for actions and the implications of using each technique. Here’s a summary of the available attached properties:

  • Action.Target – Sets both the Action.Target property and the DataContext property to the specified instance. String values are used to resolve an instance from the IoC container.
  • Action.TargetWithoutContext – Sets only the Action.Target property to the specified instance. String values are used to resolve an instance from the IoC container.
  • Bind.Model – View-First - Set’s the Action.Target and DataContext properties to the specified instance. Applies conventions to the view. String values are used to resolve an instance from the IoC container.
  • View.Model – ViewModel-First – Locates the view for the specified VM instance and injects it at the content site. Sets the VM to the Action.Target and the DataContext. Applies conventions to the view.

 

Now, let’s take a look at another interesting aspect of ActionMessage: Parameters. To see this in action, let’s switch back to our original ViewModel-First bootstrapper, etc. and begin by changing our ShellViewModel to look like this:

 

using System.ComponentModel.Composition;
using System.Windows;

[Export(typeof(IShell))]
public class ShellViewModel : IShell
{
    public bool CanSayHello(string name)
    {
        return !string.IsNullOrWhiteSpace(name);
    }

    public void SayHello(string name)
    {
        MessageBox.Show(string.Format("Hello {0}!", name));
    }
}

 

There are a few things to note here. First, we are now working with a completely POCO class; no INPC goop here. Second, we have added an input parameter to our SayHello method. Finally, we changed our CanSayHello property into a method with the same inputs as the action, but with a bool return type. Now, let’s have a look at the Xaml:

 

<UserControl x:Class="Caliburn.Micro.HelloParameters.ShellView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:cal="http://www.caliburnproject.org">
    <StackPanel>
        <TextBox x:Name="Name" />
        <Button Content="Click Me">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cal:ActionMessage MethodName="SayHello">
                        <cal:Parameter Value="{Binding ElementName=Name, Path=Text}" />
                    </cal:ActionMessage>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </StackPanel>
</UserControl>

 

Our markup now has one modification: We declared the parameter as part of the ActionMessage using an ElementName Binding. You can have any number of parameters you desire. Value is a DependencyProperty, so all the standard binding capabilities apply to parameters. Did I mention you can do all this in Blend?

 

ActionsInBlend

 

One thing that is nice about this is that every time the value of a parameter changes, we’ll call the guard method associated with the action(CanSayHello in this case) and use its result to update the UI that the ActionMessage is attached to. Go ahead and run the application. You’ll see that it behaves the same as in previous examples.

In addition to literal values and Binding Expressions, there are a number of helpful “special” values that you can use with parameters. These allow you a convenient way to access common contextual information:

  • $eventArgs – Passes the Trigger’s EventArgs or input parameter to your Action. Note: This will be null for guard methods since the trigger hasn’t actually occurred.
  • $dataContext – Passes the DataContext of the element that the ActionMessage is attached to. This is very useful in Master/Detail scenarios where the ActionMessage may bubble to a parent VM but needs to carry with it the child instance to be acted upon.
  • $source – The actual FrameworkElement that triggered the ActionMessage to be sent.

You must start the variable with a “$” but the name is treated in a case-insensitive way by CM.

 

Word to the Wise

Parameters are a convenience feature. They are very powerful and can help you out of some tricky spots, but they can be easily abused. Personally, I only use parameters in the simplest scenarios. One place where they have worked nicely for me is in login forms. Another scenario, as mentioned previously is Master/Detail operations.

 

Now, do you want to see something truly wicked? Change your Xaml back to this:

 

<UserControl x:Class="Caliburn.Micro.HelloParameters.ShellView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <TextBox x:Name="Name" />
        <Button x:Name="SayHello" 
                Content="Click Me" />
    </StackPanel>
</UserControl>

 

Running the application will confirm for you that CM’s conventions even understand ActionMessage parameters. We’ll discuss conventions a lot more in the future, but you should be happy to know that these conventions are case-insensitive and can even detect the before-mentioned “special” values.

 

Now, lets look at a simple Master/Detail scenario that demonstrates ActionMessage bubbling, but let’s do it with a shorthand syntax that is designed to be more developer friendly. We’ll start by adding a simple new class named Model:

 

using System;

public class Model
{
    public Guid Id { get; set; }
}

 

And then we’ll change our ShellViewModel to this:

 

using System;
using System.ComponentModel.Composition;

[Export(typeof(IShell))]
public class ShellViewModel : IShell
{
    public BindableCollection<Model> Items { get; private set; }

    public ShellViewModel()
    {
        Items = new BindableCollection<Model>{
            new Model { Id = Guid.NewGuid() },
            new Model { Id = Guid.NewGuid() },
            new Model { Id = Guid.NewGuid() },
            new Model { Id = Guid.NewGuid() }
        };
    }

    public void Add()
    {
        Items.Add(new Model { Id = Guid.NewGuid() });
    }

    public void Remove(Model child)
    {
        Items.Remove(child);
    }
}

 

Now our shell has a collection of Model instances along with the ability to add or remove from the collection. Notice that the Remove method takes a single parameter of type Model. Now, let’s update the ShellView:

 

<UserControl x:Class="Caliburn.Micro.BubblingAction.ShellView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:cal="http://www.caliburnproject.org">
    <StackPanel>
        <ItemsControl x:Name="Items">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Button Content="Remove"
                                cal:Message.Attach="Remove($dataContext)" />
                        <TextBlock Text="{Binding Id}" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <Button Content="Add"
                cal:Message.Attach="Add" />
    </StackPanel>
</UserControl>

 

The first thing to notice is that we are using a more Xaml-developer-friendly mechanism for declaring our ActionMessages. The Message.Attach property is backed by a simple parser which takes its textual input and transforms it into the full Interaction.Trigger/ActionMessage that you’ve seen previously. If you work primarily in the Xaml editor and not in the designer, you’re going to like Message.Attach. Notice that neither Message.Attach declarations specify which event should send the message. If you leave off the event, the parser will use the ConventionManager to determine the default event to use for the trigger. In the case of Button, it’s Click. You can always be explicit of coarse. Here’s what the full syntax for our Remove message would look like if we were declaring everything:

 

<Button Content="Remove"
        cal:Message.Attach="[Event Click] = [Action Remove($dataContext)]" />

 

Suppose we were to re-write our parameterized SayHello action with the Message.Attach syntax. It would look like this:

 

<Button Content="Click Me"
        cal:Message.Attach="[Event Click] = [Action SayHello(Name.Text)]" />

 

But we could also leverage some smart defaults of the parser and do it like this:

 

<Button Content="Click Me"
        cal:Message.Attach="SayHello(Name)" />

 

You can specify literals as parameters as well and even declare multiple actions by separating them with a semicolon:

 

<Button Content="Let's Talk"
        cal:Message.Attach="[Event MouseEnter] = [Action Talk('Hello', Name.Text)];
                            [Event MouseLeave] = [Action Talk('Goodbye', Name.Text)]" />

 

WARNING: Those developers who ask me to expand this functionality into a full-blown expression parser will be taken out back and…dealt with. Message.Attach is not about cramming code into Xaml. It’s purpose is to provide a streamlined syntax for declaring when/what messages to send to the ViewModel. Please don’t abuse this.

 

If you haven’t already, run the application. Any doubts you had will hopefully be put to rest when you see that the message bubbling works as advertised :) Something else I would like to point out is that CM automatically performs type-conversion on parameters. So, for example, you can pump TextBox.Text into a System.Double parameter without any fear of a casting issue.

So, we’ve discussed using Interaction.Triggers with ActionMessage, including the use of Parameters with literals, element bindings*** and special values. We’ve discussed the various ways to set the action target depending on your needs/architectural style: Action.Target, Action.TargetWithoutContext, Bind.Model or View.Model. We also saw an example of the bubbling nature of ActionMessage and demoed it using the streamlined Message.Attach syntax. All along the way we’ve looked at various examples of conventions in action too. Now, there’s one final killer feature of ActionMessage we haven’t discussed yet…Coroutines. But, that will have to wait until next time.

 

*Currently, the full version of Caliburn is not based on System.Windows.Interactivity. Caliburn’s trigger mechanism was around long before Blend’s.  You may notice a shocking similarity in the markup. That said, Caliburn v2.0 will be migrated to use the Blend model in the near future.

**Actually, if no handler is found, before an exception is thrown, the framework will check the current DataContext to see if it has the requested method. This seamed like a reasonable fallback behavior.

***One important detail about ElementName Bindings that I didn’t mention…It doesn’t work with WP7 currently. Due to the fact that WP7 is based on a version of Silverlight 3 which had an incomplete implementation of DependencyObject/DependencyProperty, the infrastructure is not present to make this work in any sort of sane way. However, parameter literals and special values still work as described along with all the rest of the ActionMessage features.

How To – Gems And .NET – Dependencies (References)

Posted by Rob Reynolds, Saturday, July 17, 2010 (858 views)

In my last post I didn’t mention dependencies.  Dependencies are their own animal. They require a couple more things to be in place. Let’s talk about those things.

In the .NET world, the dependency for compiled bits is usually an exact version of a reference.

Let me explain. So for example, you have a reference to log4net, and you don’t ILMerge it into your assembly. You now have a dependency that the DLL needs to be there and a particular version (outside of redirecting the bindings).  So what I’m getting at is that you require an exact version of a particular DLL. And what you really need is an exact name, version, culture, and public key token of a DLL.  But let’s keep things simple. It’s really the version and the name when culture is neutral (and the key shouldn’t change in the same version). So just the name and version.

Adding a Reference as a Dependency

For each reference you have to a library, you find out what version it is (assembly version) and then add that as a dependency. You can do that by cracking open reflector and taking a look at the actual assembly version.

The assembly version

Don’t use the properties. Neither file version or product version are going to be accurate here:

 Properties of log4net.dll - file and product verions

There is nothing out there that says that assembly, file and informational (also known as product) versions have to be the same. .NET relies on the assembly version for referencing. It makes sense that we should as well. Here’s a better example where things are different:

Castle File Version 1.2.0.6623 Castle Assembly Version 1.2.0.0

So what would I put in my gemspec? If your reference was to log4net version 1.2.10.0, then you need to assign a dependency to that exact version. Done like so:

spec.add_dependency('log4net','= 1.2.10.0')

I believe you add each referenced dependency to it’s own line.

Gem Exists?

Now to the sanity check. Before you even add it as a dependency, you want to ensure that the gem exists.

Go to http://rubygems.org and in the top right there is a search box. Search for your reference there.

Search box on RubyGems.org

So let’s search for log4net to be sure it’s there.

Search results for log4net

Sweet! I can move on to my next reference because the right version of the gem exists.

Keep in mind that the name of the gem may not be the one you are looking for and/or the name may be slightly different. For example. I have a gem for UppercuT. The gem is named uppercutbuild because there was already a gem named uppercut.

Gem Doesn’t Exist?

Now if it’s not there, you can add it. When the actual authors want to start managing the gem, you can just add them as owners so they can push their own gems.

To check the owners of a gem you type:

gem owner gemname

Gem owners for log4net

To add someone, according to the gem docs, you issue this command (all on one line):

gem owner gemname --add users.confirmed.email.address.for.ruby.gems@wherever.com

And that’s it.

You see how I am listed as the owner of the log4net gems? I am not really the developer, when I created the gem, I tied it as closely as I could to the apache project and the committers. When those guys are ready to own the gem, I have the specs for both 1.2.9 and 1.2.10 (both are commonly referred to without the last version octet) and I can just add them as owners.

 

Related Posts

Before you comment about “cluttering” the ruby community, please be sure to read this (we’re with you on this):  http://devlicio.us/blogs/rob_reynolds/archive/2010/07/19/gems-for-net-community-response.aspx

Gems - Package Management for .NET & How To – Gems & .NET

Walkthrough - Create Gems Even Easier With a Conventional Build (UppercuT)!

The Future is Now!

Discuss (3)

How To - Gems And .NET

Posted by Rob Reynolds, Friday, July 16, 2010 (1,584 views)

In my last post I showed gems being used for .NET. Now let’s talk about How.  Most of this stuff I’ve learned over the past two days, so if I have a mistake here or you have a better idea, please don’t hesitate to offer a better solution.

The GemSpec

The Gem::Specification reference is your friend.

In order to create a gem, you need to define a gem specification, commonly
called a “gemspec”.

A gemspec consists of several attributes. Some of these are required;
most of them are optional.

From here you learn what is required and what will just get you there.

Setup

1. Create a folder named gems in your top level source directory.

2. In that folder we are going to put our gemspec and version files. This is where we will store the files in source control (and one of them may become autogenerated).

3. We will bring our gems folder to our compiled source folder after we build. Then we can add in the compiled output.

GemSpec for .NET

1. Create a file named project.gemspec. In our example it is roundhouse.gemspec. This is the most important file for this entire process.

First two files

2. Open the gemspec in your favorite notepad editor. Copy the below in and change it for you needs.

version = File.read(File.expand_path("../VERSION",__FILE__)).strip

Gem::Specification.new do |spec|
  spec.platform    = Gem::Platform::RUBY
  spec.name        = 'roundhouse'
  spec.version     = version
  spec.files = Dir['lib/**/*']

  spec.summary     = 'RoundhousE - Professional Database Change and Versioning Management'
  spec.description = 'RoundhousE is a Professional Database Change and Versioning Management tool'
  
  spec.authors           = ['Rob "FerventCoder" Reynolds','Pascal Mestdach','Jochen Jonckheere','Dru Sellers']
  spec.email             = 'chucknorrisframework@googlegroups.com'
  spec.homepage          = 'http://projectroundhouse.org'
  spec.rubyforge_project = 'roundhouse'
end

3. Just about everything with tick marks above you will edit to suit your needs. spec.name and spec.rubyforge_project (and the gemspec file name) should all match and not be an already existing project name on RubyForge.

4. If you are a singular author, instead of spec.authors, replace it with

spec.author = 'somebody'

You can also set up description for multiple lines.

spec.description = <<-EOF
   Rake is a Make-like program implemented in Ruby. Tasks and
   dependencies are specified in standard Ruby syntax.
 EOF

Dependencies On Other Libraries

What we call references. You have a dependency on them existing for your library to run. See this post.

VERSION file

This file is stupid simple. It’s a version number. I believe you can put whatever you want in here. Use the Assembly Version number here and stick with the .NET 4 octets of numbers (like 0.0.0.0) for version.

1. Create a file named VERSION.

2. Open it in your favorite editor and put the version you want here.

VERSION with 0.5.0.242 as contents of file

Libraries

1. Create a folder called lib.

adding in lib folder

2. Copy YOUR compiled DLLs into here. Your references (or dependencies) should not go here. See How To: Gems and .NET - Dependencies.

 Put your dlls in lib folder

Documentation

Create a docs folder. In that folder goes your documentation. This could be release notes, a ReadMe, actual documentation. This area is open. Just make sure you add the docs folder to the specification.

spec.files = Dir['lib/**/*'] + Dir['docs/**/*']

 

Executables

If you want to give someone the ability to run an executable from the command line after installing your application with gems, and you use .NET, this is how you do it.

1. Create a folder named bin as a subdirectory next to the gemspec.

2. Put your executable (and dependencies) into the bin directory.

create a bin directory stand alone executable in bin

3. Create your shim file (it’s named what you would type at the command line). I’ve called mine rh. The one above allows ruby to be able to actually execute the Windows executable. Let’s open it and see what it looks like. This, we learned from an answer to a post on stack overflow.  This shim also goes in source control

result = system(File.dirname(__FILE__) + "/rh.exe " + ARGV.join(' '))
exit 1 unless result

4. Don’t forget that space at the end of your executable name.

5. Open your gemspec. We need to make sure we have spec.executables filled out and our new directory added to our Files.

version = File.read(File.expand_path("../VERSION",__FILE__)).strip

Gem::Specification.new do |spec|
  spec.platform    = Gem::Platform::RUBY
  spec.name        = 'roundhouse'
  spec.version     = version
  spec.files = Dir['lib/**/*'] + Dir['docs/**/*'] + Dir['bin/**/*']
  spec.bindir = 'bin'
  spec.executables << 'rh'

  spec.summary     = 'RoundhousE - Professional Database Change and Versioning Management'
  spec.description = 'RoundhousE is a Professional Database Change and Versioning Management tool'
  
  spec.authors           = ['Rob "FerventCoder" Reynolds','Pascal Mestdach','Jochen Jonckheere','Dru Sellers']
  spec.email             = 'chucknorrisframework@googlegroups.com'
  spec.homepage          = 'http://projectroundhouse.org'
  spec.rubyforge_project = 'roundhouse'
end

Build And Push

You must already have Ruby (1.8.6 or better) and RubyGems installed and/or updated to at least 1.3.7 (gem update –system). You will want to use a RubyInstaller version of Ruby under the Ruby on Windows section.

1. Open a command line and type

gem build project

2. If there are no issues, you should have a gem for upload.

roundhouse-0.5.0.242.gem

roundhouse-0.5.0.242.gem

3. Create an account with RubyGems.org.

4. Ensure your project name isn’t already taken by searching for it. If it is you will need to rename your gemspec file, spec.name, and spec.rubyforge_project to a name that is not taken.

5. Type the following command:

gem push project_someversionnumbers.gem

gem push roundhouse

6. Let it finish. Head out to rubygems.org and look at your shiny, new gem!

 sweet!

7. Test it.

gem install project 

gem uninstall project

 

FollowUp

In my next post, I’ll show you how to make it stupid simple. UppercuT will support this feature natively so all you have to do is have a directory called gems (at the top level of your source) with the gemspec. During the build, it will create the VERSION file and copy your output the the lib folder (custom step for bin folder will be necessary). Then it will execute a step that builds the gem. All for the price of “build”. That’s coming up in the next blog post. In the meantime, feel free to ask any questions you have. Stay tuned…

 

Related Posts

Before you comment about “cluttering” the ruby community, please be sure to read this (we’re with you on this):  http://devlicio.us/blogs/rob_reynolds/archive/2010/07/19/gems-for-net-community-response.aspx

Gems - Package Management for .NET & How To – Gems & .NET - Dependencies (References)

Walkthrough - Create Gems Even Easier With a Conventional Build (UppercuT)!

The Future is Now!

Discuss (11)
More Posts Next page »
CodeBetter.Com