Unity and Visual Studio .gitignore

If you’re using Unity and Visual Studio with a version control system like I am, beware your ignore/exclude file! When I first started my project I decided to simply combine the Unity ignore template and the Visual Studio ignore template. This is a big mistake! The Visual Studio ignore includes a *.meta, which is a very important file in Unity! Here is my resulting gitignore for Unity Visual Studio repositories:


## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/

# Visual Studio 2015 cache/options directory
.vs/

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# ### Unity ignores ###
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/Assets/AssetStoreTools*

# Autogenerated VS/MD solution and project files
ExportedObj/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd

# Unity3D generated meta files
*.pidb.meta

# Unity3D Generated File On Crash Reports
sysinfo.txt

AngularJS POST to .NET MonoRail Backend

Short post: if you’re trying to use AngularJS to $http.post() to a .NET MonoRail backend, you’ll find that there is nothing in Request.Form, or anywhere in the Request object.

I still have refactoring to do, but the quick solution is something like below. Note the headers object and transformRequest method. This needs refactored into a friendly service, but you get the idea for now.

$http({
    method: 'POST',
    url: '/YourUrl.rails',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    transformRequest: function(data) {
        var postData = [];
        for (var prop in data)
            postData.push(encodeURIComponent(prop) + "=" + encodeURIComponent(data[prop]));
        return postData.join("&");
    },
    data: myPostData,
}).success(function (data, status) {
    console.log("success");
    console.log(data);
}).error(GLOBAL.YOUR_ERROR_HANDLER);

Redmine Version 3 onto Raspberry Pi 2

This is going to be much less detailed than my post to install version 1.x of Redmine. This is a much more intense process, but I’ve done all the work for you. It’s possible I made a small error or two, but it should be pretty easy to work through if I did. I’ve done most of the work getting past all the really hard errors in the process.

This also assumes you’ve already done the regular Redmine install, though it’s not required.

Following along with http://www.redmine.org/projects/redmine/wiki/RedmineUpgrade but filling in the gaps to get it working on the Pi 2.
unzip redmine 3 to /usr/share/redmine3/ ensuring it doesn’t create a root directory inside there. (I extracted as redmine-3.0.1 and then renamed the folder)
sudo chmod 777 -R redmine3
sudo chown pi:pi -R redmine3
Now if you try the bundle install command, it won’t work. Why? Because the Pi has too low of a version of Bundler. Soooo, we have to uninstall it from apt-get, install a “fake” package, and then install the updated version straight through ruby.
sudo apt-get update
sudo dpkg -r –force-depends “bundler”
Download my fake bundler package here.
sudo dpkg -i bundler_1.9.4_all.deb
Now inside the redmine3 directory
sudo gem install bundler –version ‘1.9.4’
sudo apt-get install ruby1.9.1-dev
sudo gem install json -v ‘1.8.2’
sudo apt-get install libmysql-ruby
sudo apt-get install libmysqlclient-dev
sudo gem install mysql2 -v ‘0.3.18’
cp /etc/redmine/default/database.yml /usr/share/redmine3/config/database.yml
sudo chmod 777 config/database.yml
sudo chown pi:pi config/database.yml
nano config/database.yml and change mysql to mysql2
bundle install –without development test rmagick
This should now actually work since we did the pre-reqs, and it is going to take awhile. 10+ minutes on the Pi 2.
bundle exec rake generate_secret_token
bundle exec rake db:migrate RAILS_ENV=production
bundle exec rake tmp:cache:clear tmp:sessions:clear RAILS_ENV=production
sudo /etc/init.d/apache2 reload
sudo /etc/init.d/apache2 restart
sudo rm /var/www/redmine
sudo ln -s /usr/share/redmine3/public /var/www/redmine
Now try to surf to it. Ooops! Doesn’t work! Why? We need an upgrade to mod_passenger, and we have to build this sucker from source! Hold on to your boostraps…
https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#tarball_generic_install
(I used this tarball, which may differ from the latest when you read this.)
sudo su
mkdir /opt/passenger
cd /opt/passenger
tar xzvf /location-to/passenger-x.x.x.tar.gz
cd /opt/passenger/passenger-x.x.x
./bin/passenger-install-apache2-module
This will guide you through a process that will probably fail, but it will tell you what you need to do to make it work. Best work I’ve ever seen in an open source project! For me, I needed to:
apt-get install libcurl4-openssl-dev
apt-get install libssl-dev
apt-get install apache2-threaded-dev
apt-get install libapr1-dev
apt-get install libaprutil1-dev
Which I combined into one apt-get install libcurl4-openssl-dev libssl-dev apache2-threaded-dev libapr1-dev libaprutil1-dev
Let apt-get do its thing and then run the passenger installer again: ./bin/passenger-install-apache2-module
It will be happy and take a VERY long time to compile.
When it’s done, it will tell you modify your apache config with the following lines:
LoadModule passenger_module /opt/passenger/passenger-5.0.6/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /opt/passenger/passenger-5.0.6
PassengerDefaultRuby /usr/bin/ruby1.9.1
</IfModule>
I’ll show you how and where now.
nano /etc/apache2/mods-available/passenger.load
If you already had a version of mod_passenger installed, then this will already contain a mod_passenger line. Comment it out with a # and replace it with LoadModule passenger_module /opt/passenger/passenger-5.0.6/buildout/apache2/mod_passenger.so
nano /etc/apache2/mods-available/passenger.conf
Again, you may need to comment out the existing mod_passenger details and replace it with
<IfModule mod_passenger.c>
PassengerRoot /opt/passenger/passenger-5.0.6
PassengerDefaultRuby /usr/bin/ruby1.9.1
</IfModule>
sudo /etc/init.d/apache2 reload
sudo /etc/init.d/apache2 restart
Surf to your redmine URL and you’re done!

Install Redmine onto Raspberry Pi 2 (this is the tutorial you want!)

(UPDATE: I needed Redmine >=3.0 for a plugin, so I ended up re-doing this for version 3 of Redmine, which is a more complicated process. I wrote instructions for Redmine version 3 onto the Raspberry Pi 2, but they’re not quite as detailed as the ones here. But if you’re able to follow these instructions, you should be able to follow along for 3.0. It’s just a bit more complex because you have to build packages.)

(COMMENTS: I suggest you take a look below at the comments to this post if you run into anything unexpected, like an error. There is a lot of feedback for various issues some folks ran into.)

After scouring the internet, I’ve created the go-to tutorial for installing Redmine onto the Raspberry Pi 2 without assuming you are a Linux guru and without pages and pages of steps. This assumes you have a Raspberry Pi 2 and a freshly imaged SD card that has never booted. If you’ve already booted, that’s fine, you should be able to pick up around step 12 (I would recommend an SD image backup first!).

I’m using Raspbian 2015-02-16 in this tutorial. Yes, this is 27 steps, but it holds your hand and it zips by. Plus, the first half is initial Pi setup and backup.

  1. Before even booting your Pi, download Adafruit Pi Finder. This is a cross-platform utility that allows you to get started with your Pi without having to hook it to a TV and use a keyboard. It will discover it, tell you the IP, and get you connected without any display or keyboard attached to the Pi. Just make sure it’s connected via wire to your network.
  2. I suggest you image your SD card with Win32DiskImager.
  3. Insert your SD card, plug in the wired ethernet cable, and finally plug in the power supply. Let it go to town booting and doing it’s first time thing. Note that you don’t need it hooked to a screen or keyboard, you just need to let it run for a minute or two until the activity light dies down.
  4. Open PiBootstrap.exe.
  5. Click Find my Pi
  6. It will take a minute or two to search your network–be patient.
  7. If you have more than one Pi, you will need to make sure you edit the correct one, but I expect in most cases you will just have the one. Enter the SSH credentials you want to use and a hostname. I chose piredmine for my hostname. For this install, leave “Install the WebIDE?” unchecked.
  8. Click “Bootstrap!”
  9. The tool will connect, an SSH Terminal window will open, and go to town downloading and installing stuff. Let it run.
  10. Run sudo raspi-config and expand the filesystem to fill the SD card.
  11. Optional: Shutdown, eject your SD card from the Pi, and make a backup on your regular machine using the same Win32DiskImager utility. This way, if things go wrong, you can rollback to this point easily. Put it back in your Pi when it’s done.

    Otherwise: Reboot.
  12. Now to actually install stuff!
  13. (At this point, it may be easier to sudo su to become root rather than prefix all your commands with sudo. It’s up to you, though!)
  14. Execute sudo apt-get install apache2 mysql-server and wait. You’ll be prompted to enter a password for the MySQL root user. Remember to make it secure. Wait some more.
  15. Next execute sudo apt-get install redmine redmine-mysql and wait. You’ll be prompted about configuring the redmine/instances/default package with a lengthy text blurb advising you to select Yes. Select Yes, then select mysql. Now enter the MySQL root user password from earlier. For the next password prompt, you can leave it blank for a random password or enter whatever you like. This one shouldn’t ever be important for you to know because you know the root password. I left mine blank for random.
  16. You’ll see a message that “This may take awhile.” It is not kidding. Go do something else for 5 or 10 minutes.
    “This may take a while.” Yes, yes it will.

    It will give you false hope that it is done, but it’s not. Keep waiting.

  17. Finally it’s done, and we are nearly so. Execute one last install: sudo apt-get install libapache2-mod-passenger  This one will be quick. A little configuration and we’ll be good to go.
  18. Execute: sudo ln -s /usr/share/redmine/public /var/www/redmine  This will make your URL “http://youservername/redmine”
  19. sudo chown -R www-data:www-data /var/www/redmine
  20. sudo su  (need to become root for this next one)
  21. echo "RailsBaseURI /redmine" > /etc/apache2/sites-available/redmine.conf [Thanks Daniel]
  22. exit (to exit root)
  23. sudo a2ensite redmine
  24. sudo /etc/init.d/apache2 reload
  25. sudo /etc/init.d/apache2 restart
  26. Done! Surf to http://piredmine.local/redmine and wait for the initial loading process (this is a one-time wait). The default Redmine login is admin / admin
  27. You may need to make additional changes to your apache configuration if you’re running on a domain name, or to use plugins, but this was the hard part. Pat yourself on the back and eat some chocolate.

References:

Redmine Install Guide that insists on using experimentals respositories
A “write-up” that works if you have guru level knowledge and a few pre-reqs already installed
Installing Redmine Backlogs on Debian
(Backlogs is a plugin — I’ve never used it)

Inkscape Laser Engraver Bug

If you’ve tried to use the modified Inkscape laser engraver plugin mentioned in this blog post about building an engraver, you may have run into an error trying to do the export. It’s something like “AttributeError: ‘module’ object has no attribute ‘unittouu’” or “unittouu not part of inkex module“. Here’s the fix.

The bug is on line 3080 of laserengraver.py and broke due to an Inkscape change. Old line:

doc_height = inkex.unittouu(self.document.getroot().get('height'))

New line:

doc_height = self.unittouu(self.document.getroot().xpath('@height', namespaces=inkex.NSS)[0])

Be sure to have the exact same number of spaces/tabs on this line. In Python, whitespace is important, so you can’t mix and match spaces and tabs, and all code blocks must have the same whitespace alignment.

Problem solved!

SQL PSA: Never reference OUTER JOIN-ed tables in your WHERE clause

Never reference OUTER JOIN-ed tables in your WHERE clause. The exception is when you want to test if your outer join expression matched any rows at all; i.e.,  checking to see if the outer table’s primary key column is NULL.  Otherwise, put any criteria on your outer tables within the join expression itself.

Full details: http://weblogs.sqlteam.com/jeffs/archive/2007/05/14/criteria-on-outer-joined-tables.aspx

HTML5 Localstorage

If you haven’t heard, HTML5 Localstorage allows us web developers to store data within the client’s browser. This is different than cookies which are transmitted with every request to the server. Localstorage allows us to put data into the browser’s storage once and not have to transmit it back and forth.

Using local storage is super easy. It acts just like a hashtable and is accessed through a global JS variable called “localStorage”.

1
2
var foo = localStorage.getItem("bar");
localStorage.setItem("bar", foo);

Boom, you’ve retrieved an item and set an item! If an item doesn’t exist, it will just return null, not an exception like some hashtable implementations.

I’ve been using this to storage and retrieve Kendo Grid filters and sorts between page views. That’s for another blog post, though…

Could not load file or assembly … HRESULT: 0x80070057 (E_INVALIDARG)

Wow, this error just cost me 40 minutes of my life. I was forced to hard-reset my computer and when it rebooted, trying to load my primary IIS dev site gave this error. It names a specific DLL, but that’s a red-herring. The specific DLL is irrelevant. In my case, it was a 3rd party DLL that worked fine when I switched IIS to a different site, so I knew it wasn’t the problem.

Searching reveals this thread on the MSDN social site. It says to delete the contents of “Temporary ASP.NET Files” folders. There are several locations if you want to be really thorough. Note that the last one is the one I had missed and was causing me grief:

C:\Users\<UserName>\AppData\Local\Temp\Temporary ASP.NET Files
C:\Windows\Microsoft.NET\Framework\v2.0.50727
C:\Windows\Microsoft.NET\Framework\v4.0.30319
C:\Windows\Microsoft.NET\Framework64\v2.0.50727
C:\Windows\Microsoft.NET\Framework64\v4.0.30319

The Framework64 v4 directory is where my culprit files were located. I’m running Windows 8.1 64 bit and Visual Studio 2012.

tl;dr: delete your .NET temp file directories, and don’t forget Framework64!

GitExtensions Date Column Setting

By default, Git Extensions for Windows will display the commit timestamp as just the number of hours or days prior to now. If you’re like me, you find this sort of information worthless. Telling me something happened 37 days ago is not useful information. Telling me it happened September 15, 2013 at 2:37 pm is much more my style.

To change this setting, select “GitEx Browse” from the Windows Explorer right-click context menu, then Settings -> Settings. Finally, navigate to and uncheck this box:

Git Extensions relative date setting
Git Extensions relative date setting

Ahhh, so much better now!