I'm working on some code today that saves records to a database. For my rspec tests I want to redirect the "save" to a stub. And I want to take the data that would have been saved and stow it somewhere else. Well, I had plenty of problems with this so I'm here to share the real solution.
The first issue that I ran into: return values on stubs must match the type of the return value in your live code. Duh. But I'm coming from the static typed world, so this one slipped by me. I had a method that was returning the number of new records created (0 or 1). Simple. But the stub was just pushing the input into an array:
saved_rows = []
proc.stub(:save) do |arg0|
puts 'redirecting save'
saved_rows << arg0
end
Which meant that the return value (that was going to 'real' code) was a big array. No bueno. Ok, fixing that was a huge aha moment. Just add a '0' on the line after @saved_rows << arg0. Much cursing about this one -- the object worked find from irb but failed when I did the test.
Next up: storing the row in an array outside of the stub. I couldn't find any samples of this, so it was trial and error. In the code above, it certainly looks like it'd work. But it doesn't. I assume saved_rows is getting created in two places. The solution: use an @instance variable:
@saved_rows = []
proc.stub(:
save ) do |arg0|
puts "
redirecting save "
@saved_rows << arg0
0
end
Bada-bing. Now I have a save method that is storing the new data in a place where I can get to it (and test it).
Related Rspec doc:
https://www.relishapp.com/rspec/rspec-mocks/docs/method-stubs/stub-with-substitute-implementation
Coding, Mostly
19 January 2012
25 November 2011
sometimes hard conventions suck (rendering partials in RoR)
I spent an hour today on this one:
render :partial => "short_list", :collection => @items
which was in an ajax call. I was doing it with 'render :inline' but partials seemed like a much better idea. Well, that wasn't such a great idea. I kept getting ActionView::MissingTemplate errors. Tried about 15 things, read three or four blog posts, several SO questions. Then I noticed one that had an underscore in front of the file name. Odd. So I go read the docs and sure enough.
Even if you specifically say:
partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partialsSo I had some code that said:
render :partial => "short_list", :collection => @items
which was in an ajax call. I was doing it with 'render :inline' but partials seemed like a much better idea. Well, that wasn't such a great idea. I kept getting ActionView::MissingTemplate errors. Tried about 15 things, read three or four blog posts, several SO questions. Then I noticed one that had an underscore in front of the file name. Odd. So I go read the docs and sure enough.
Even if you specifically say:
render :partial => "item/short_list", :collection => @items
it will not find your partial because it doesn't start with an underscore. Even though there is only one view in that directory.
That, that is stupid. Conventions are fine when you want to just sorta let the app wire things up. But when you specifically say "do it this way" the convention should not get in your way.
The odd thing about Ruby is that it is much more of an RTFM language than C# -- because there's no compiler to tell you "hey, you did that wrong" and the autocomplete is usually just not there.
That, that is stupid. Conventions are fine when you want to just sorta let the app wire things up. But when you specifically say "do it this way" the convention should not get in your way.
The odd thing about Ruby is that it is much more of an RTFM language than C# -- because there's no compiler to tell you "hey, you did that wrong" and the autocomplete is usually just not there.
15 November 2011
More Rubymine Impressions
OK here's another couple of things I love about this IDE. For the sake of typing, RM means RubyMine.
- Local History: you get a diff-able view of all the saves that you have made to a file. If you're using a DVCS that's 3 different views of the changes that you've made to a file. Wild. I love this because I've often thought of adding a "commit on every successful build" sort of thing to Visual Studio so that I have a step by step recreation of what I did with a file. That way if you think 'huh, that was working 20 minutes ago' you'd be able to backtrack. With RubyMine, no need.
- Parentheses: Seems like such a small thing, but it makes my life easier. When I type '(' into RM it gives me a closing paren for free. But if I miss that for whatever reason and then type the closing paren anyway, RM figures it out and just overwrites the closing paren that I typed. I'm waiting for this to trip me up, but it hasn't happened yet so so far it's awesome.
- Find is fast fast fast: So far I've got about 200 files in my app. Not many really. But when I do a Shift Ctrl F and search for a string in the files it is nearly instantaneous. It is possible that that's because the files are on an SSD. Still it seems faster than Visual Studio.
Labels:
ruby,
ruby-on-rails,
rubymine
09 November 2011
ROR + RubyMine impressions (from a .NET Dev)
Playing with RubyMine and ROR today. I'm actually hoping to build something real with this in the next few days. Well, a few days might be optimistic. I'm a .NET dev and I remember people saying that MVC was really just Microsoft-ROR. Didn't know much about it at the time but I'm starting to see it.
Here are some impressions of RubyMine and ROR, in no particular order.
Here are some impressions of RubyMine and ROR, in no particular order.
- What a deal: I got RubyMine for $35. A steal. Part of the 'Winter is coming' sale. Someone's been watching too much Game of Thrones eh?
- Autocompletey magic: Love the auto complete in RubyMine so far. I've never seen Visual Studio pick up on `<` as well as RubyMine does. Gives me every option that I could ever want to put next to a less than.
- Ruby is: I don't know yet. Still deciding.
- VCS: RubyMine's source control integration is effortless. Makes me wonder why MS hasn't made a decent plug in for SVN by now. If a $35 product can pull it off but a $5k+ product is 'missing' that, well what's the deal?
- Console: wait so I can interact with my model directly from the command line? http://guides.rubyonrails.org/getting_started.html Section 6.6 (no anchor there?!). OK that's pretty cool.
- Wizard-ish things: `rails generate model ...` makes Rails stronger in code generation than Visual Studio? Weird. I expected a lot of 'type this text into a new text file'. Instead there's a generator that takes care of that for me. The generator also builds functional tests and unit tests? Testing as the norm instead of a 'like-ta-have'. Huh.
- Associations are built into the routing (nested resource). Interesting.
- ASP.NET MVC = C# on Rails? Yeah I can see it. Wonder what web language used <%= %> first.
- Speed speed speed: this one keeps coming back to me as I read the getting started guide. Something that would take me half an hour in C# MVC would take maybe 4 mins in ROR. Most of that time is in the database. And I'm not including the migration time for a database that is in a new environment (e.g Beta) in the .NET world -- what version is the db in now and what version should it be migrated to? In C# MVC: don't know and don't know (usually). In ROR: known and known. Versioning and migration are built in over here in the ROR world. This I like.
Labels:
ruby,
ruby-on-rails,
rubymine
12 June 2011
Thinking of an ideal logging framework
First, let me say that logging is important. It's one of the Martian Principles: #13 Log Everything. Disk space is so cheap anymore that having weeks worth of detailed logs shouldn't be any big deal, provided you aren't taking a noticeable performance hit.
Today I'm working with the Enterprise Library Logging framework and finding it lacking. It certainly does all-that-and-a-bag-of-chips. But it's got some issues that have really tedious workarounds:
I did look at ELMAH. It looks good, but it breaks the MP#13 because it's only logging the errors.
So, the ideal laundry list for a logging solution:
Today I'm working with the Enterprise Library Logging framework and finding it lacking. It certainly does all-that-and-a-bag-of-chips. But it's got some issues that have really tedious workarounds:
- Changing logging configuration on the fly without restarting your web app isn't easy. You have to add some custom code to make Enterprise Library look for a config file that isn't web.config. Small workaround, but every app needs it. I hear that EL 5.0 Optional Update 1 has a fix for this. Note the version number there: EL is up to version 5 and just now it's thinking of a standalone config.
- Changing the EL.config as part of your deployment is wow a lot of work. I found this post by Oleg Sych that explains how to do it. It isn't trivial. Getting the rest of my team to agree to that amount of work to get Prod/Testing/Debug configuration of EL.config working? Hah, forget it. It requires hand-editing of the csproj file. Not good.
I did look at ELMAH. It looks good, but it breaks the MP#13 because it's only logging the errors.
So, the ideal laundry list for a logging solution:
- Simple simple simple to add to an existing app.
- Configure the logging level on the fly without restarting the app.
- Write to a local (in the app directory) no-footprint database.
- Multiple handling of certain classes of entries (errors get an email, verbose entries don't)
- Easy to configure for production deploy via a script or .config transform (preferably second option)
We had a similar setup at the last job (but it wrote to the Windows event log, yech). I don't really want to roll my own here. We were using log4net, but I recall a lot of configuration pain around it. Not sure why, but the guy who was working on it was bright enough that I don't think he was the issue. Plus, I think the on-the-fly config was something we had to do on our own.
Will update if I can find anything that satisfies all these conditions.
30 March 2011
Buying a house in a depreciating market
TLDR: This calculator is surprisingly accurate for a first time buyer: NYT Rent vs Buy Calculator
First time homebuyer here. Been ready - nearly - to buy for a few years now but the combination of "WTF is with the housing market" and a shaky economy has left me thinking it's a bad idea. Granted, this was sort of a vague feeling of unease -- not a decision I looked at super closely.
Here it is a few years later and the economy is getting better. Slowly. In fact so slowly that it looks unlikely that we'll get back to full employment before the next recession. Nevertheless, my career is doing fine and demand for my skill set is strong. I feel that now might finally be time to buy.
However, I really want to be objective as possible about it. This is money we're talking about here and it's a good idea to keep your money and emotions far apart.
To that end, I decided to do some math.
First, house payments are partially interest payments and partially principal payments. So that's some money that goes to the bank and some that goes to you. Then there's PMI, house insurance and property taxes.
Here's the big negative: depreciation. In my market, we're looking at almost $17,000 per year for depreciation according to Case Schiller values.
You may say: "But what about the emotional satisfaction of owning a home?" Sure. Then there's the weekends spent re-caulking the bathtub and kitchen sink. Houses can be a spare time sink. I surely love my spare time. Allows me to write more in my blog (can't you tell?!). I consider the emotional benefit of owning a home to be offset by the emotional cost of having less time to watch Jersey Shore. That's a joke.
In the benefits column, we have: tax savings, principal payments and... well that's it. Not paying rent anymore? Sure, but you're paying the ITI in PITI so that washes out quickly.
Now for the math: the total "not going in my pocket" costs per year are the sum of: PMI, Homeowner Insurance, Property Taxes, Depreciation and Interest -- I'll call these Costs. The "going in my pocket" amount is the sum of tax savings and principal payments -- I'll call these Credits. For me, buying a $225k property at 5.25% with 3% down means my total outlay (Costs minus Credits) would be about $8k. Well that's much much less than I'm paying in rent ($9.5k / year for an apartment that certainly isn't the same as a decent house). OK so buying a house looks like a no-brainer: I'm coming out about $100 a month ahead.
Wait, not so fast. That's in a static (not appreciating or depreciating) market. Factor in depreciation as it stands currently (about 7%) and my total outlay per year bumps up to $23k. Granted, a huge chunk of that is solely depreciation. But why pay depreciation unless you're already in a house? This is the same reason people walk away from mortgages. Depreciation is just moving the goal line -- the goal line of you owning your house outright.
It seems unlikely that the market will depreciate for years though. When would be the optimal time to buy? When the total outlay per month is the same as the rent on a similar house. The way I calculate it, that's when depreciation is heading toward positive territory but still negative -- above -4% to be exact. If you're comfortable living in a smaller apt instead of a larger house, that number moves to -2%.
Play around with this Buy vs Rent calculator on the NYT website and you'll see that when the market is depreciating still it will take you about 20 years for buying to be better than renting. Yikes.
In the meantime -- while I'm looking for the market to improve enough that I won't be underwater on the house in a year, evaporating my down payment -- I think I'll hang around the foreclosure market and see if anything pops.
First time homebuyer here. Been ready - nearly - to buy for a few years now but the combination of "WTF is with the housing market" and a shaky economy has left me thinking it's a bad idea. Granted, this was sort of a vague feeling of unease -- not a decision I looked at super closely.
Here it is a few years later and the economy is getting better. Slowly. In fact so slowly that it looks unlikely that we'll get back to full employment before the next recession. Nevertheless, my career is doing fine and demand for my skill set is strong. I feel that now might finally be time to buy.
However, I really want to be objective as possible about it. This is money we're talking about here and it's a good idea to keep your money and emotions far apart.
To that end, I decided to do some math.
First, house payments are partially interest payments and partially principal payments. So that's some money that goes to the bank and some that goes to you. Then there's PMI, house insurance and property taxes.
Here's the big negative: depreciation. In my market, we're looking at almost $17,000 per year for depreciation according to Case Schiller values.
You may say: "But what about the emotional satisfaction of owning a home?" Sure. Then there's the weekends spent re-caulking the bathtub and kitchen sink. Houses can be a spare time sink. I surely love my spare time. Allows me to write more in my blog (can't you tell?!). I consider the emotional benefit of owning a home to be offset by the emotional cost of having less time to watch Jersey Shore. That's a joke.
In the benefits column, we have: tax savings, principal payments and... well that's it. Not paying rent anymore? Sure, but you're paying the ITI in PITI so that washes out quickly.
Now for the math: the total "not going in my pocket" costs per year are the sum of: PMI, Homeowner Insurance, Property Taxes, Depreciation and Interest -- I'll call these Costs. The "going in my pocket" amount is the sum of tax savings and principal payments -- I'll call these Credits. For me, buying a $225k property at 5.25% with 3% down means my total outlay (Costs minus Credits) would be about $8k. Well that's much much less than I'm paying in rent ($9.5k / year for an apartment that certainly isn't the same as a decent house). OK so buying a house looks like a no-brainer: I'm coming out about $100 a month ahead.
Wait, not so fast. That's in a static (not appreciating or depreciating) market. Factor in depreciation as it stands currently (about 7%) and my total outlay per year bumps up to $23k. Granted, a huge chunk of that is solely depreciation. But why pay depreciation unless you're already in a house? This is the same reason people walk away from mortgages. Depreciation is just moving the goal line -- the goal line of you owning your house outright.
It seems unlikely that the market will depreciate for years though. When would be the optimal time to buy? When the total outlay per month is the same as the rent on a similar house. The way I calculate it, that's when depreciation is heading toward positive territory but still negative -- above -4% to be exact. If you're comfortable living in a smaller apt instead of a larger house, that number moves to -2%.
Play around with this Buy vs Rent calculator on the NYT website and you'll see that when the market is depreciating still it will take you about 20 years for buying to be better than renting. Yikes.
In the meantime -- while I'm looking for the market to improve enough that I won't be underwater on the house in a year, evaporating my down payment -- I think I'll hang around the foreclosure market and see if anything pops.
02 May 2009
Why you need Fiddler if you're publishing web sites
I'm publishing a new web site today (this is my new project that's using Silverlight, SQLite, LINQ via DbLinq and WCF). Well I tried to publish it on Monday but ran into a snag with the service I used to talk to the database. I thought it was a url problem, so I spent maybe an hour or two messing around with web.config and the service references in my Silverlight project. I've learned a couple of valuable lessons here.
Changing service references around can be a real hassle. There's two solutions to this. First, you can just have two references to the service in your Silverlight project, just changing the using statement at the top of your files to the one you want. However this might mean changing your code in more than one place, which will get old. Second, you can use a ServiceHostFactory (I read about this here):
public class MySiteHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
// Specify the exact URL of your web service
Uri webServiceAddress = new Uri(ConfigurationManager.AppSettings["ServiceUri_MySite"]);
ServiceHost webServiceHost = new ServiceHost(serviceType, webServiceAddress);
return webServiceHost;
}
}
And then add a key/value pair to your web.config. I did try this approach and it worked, but still didn't get to the root of my problem.
Get your policies straight. When you're deployed you'll probably want to lock down who can access your service. But in the meantime, open that policy right up. You'll need two files, clientaccesspolicy.xml and crossdomain.xml.
clientaccesspolicy.xml:
Use Fiddler and add this to your web.config: <serviceDebug includeExceptionDetailInFaults="true" />. Using these two I found the issue in 10 minutes. Keep in mind that I was running the Silverlight app locally but I was pointing to the remote server. Turned out I was missing a dll (System.Data.SQLite). So I added it from my local dblinq directory. Still got the NotFound error. What?? Back to Fiddler. Go to the line that has the error (a 500 in my case) then Inspectors, TextView in the bottom pane. "The located assembly's manifest definition does not match the assembly reference": ah hah, wrong dll. Uploaded the correct one and away we went. All done.
Update: seetha asked what you need to do to get SQLite running on discountasp.net. The answer: not much. It's all about the trust level that your host let's you run .net apps under. Discountasp.net lets you run at Full Trust so there's no tweaking needed to get it going. Just make sure your app can find the .s3db file regardless of directory structure (I put mine in App_Data) and make sure you have the right version of your SQLite dll in your bin.
Changing service references around can be a real hassle. There's two solutions to this. First, you can just have two references to the service in your Silverlight project, just changing the using statement at the top of your files to the one you want. However this might mean changing your code in more than one place, which will get old. Second, you can use a ServiceHostFactory (I read about this here):
public class MySiteHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
// Specify the exact URL of your web service
Uri webServiceAddress = new Uri(ConfigurationManager.AppSettings["ServiceUri_MySite"]);
ServiceHost webServiceHost = new ServiceHost(serviceType, webServiceAddress);
return webServiceHost;
}
}
And then add a key/value pair to your web.config. I did try this approach and it worked, but still didn't get to the root of my problem.
Get your policies straight. When you're deployed you'll probably want to lock down who can access your service. But in the meantime, open that policy right up. You'll need two files, clientaccesspolicy.xml and crossdomain.xml.
clientaccesspolicy.xml:
And crossdomain.xml:<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*" >
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
NotFound can mean a lot of things. I kept getting a NotFound error out of my service. This was where I spent most of my time. Publishing the service? No prob. Opening up cross domain access? No prob. NotFound? What the heck does that mean. I could browse to the service. I could build a proxy using svcutil.exe. I was running my Silverlight app locally so I knew everything else was running right. So what the heck was going on? Well, a lot of messing around went by and still I didn't get anywhere until I did this:<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>
Use Fiddler and add this to your web.config: <serviceDebug includeExceptionDetailInFaults="true" />
Update: seetha asked what you need to do to get SQLite running on discountasp.net. The answer: not much. It's all about the trust level that your host let's you run .net apps under. Discountasp.net lets you run at Full Trust so there's no tweaking needed to get it going. Just make sure your app can find the .s3db file regardless of directory structure (I put mine in App_Data) and make sure you have the right version of your SQLite dll in your bin.
Subscribe to:
Posts (Atom)