Archive for the ‘Computers’ Category
December 6th, 2011
Ran into a simple problem today while I was speccing a new controller in our project. We generate some signed cookies for devices which check into our system and then we use those cookies to identify these devices when they return. Unfortunately the ActionController.TestRequest @request instance variable you get when using rspec-rails has the cookies collection as a basic hash and no cookies= method defined. This means that attempting to invoke permanent or signed on a hash results in a runtime error and you can't just assign the cookies collection to a valid ActionDispatch::Cookies::CookieJar instance.
You can get around this by going around the missing attribute setter and changing the instance variable directly.
#./specs/controllers/some_controller_spec.rb
# a new device is created here...
⋮
@request.instance_variable_set(:@cookies, ActionDispatch::Cookies::CookieJar.build(@request))
# the token is what we use to identify the device on subsequent requests
# so our specs need to be able to create it when necessary
@request.cookies.permanent.signed[:token] = [device.device_id, device.secret]
⋮
# remainder of spec omitted
If you're doing stuff with the regular cookies hash you will need to merge! your cookies hash with the @request.cookies hash before building and assigning the full blown ActionDispatch::Cookies::CookieJar instance.
Reference: How to test cookies.permanent.signed in Rails 3
December 2nd, 2011
There is surprisingly little up to date information about ActionView::Helpers::FormBuilder. That's because mostly it hasn't changed. I'm always afraid of documentation going back to 2008 when we're talking about Rails because 99% of the time its just not quite going to work.
A little bit of background: we're using Twitter's Bootstrap in our project. There's a bit of ceremony around each field such that you need to do a .clearfix div, then a label, then a .input div and finally the input. I want to eliminate all those keystrokes so I can just do:
#./app/views/c2dm/new.html.haml
form_for @message, :url => {:action => 'create'} do |f|
%fieldset
= f.text_field :registration_id
= f.text_field :collapse_key
= f.text_area :message
.actions
%input.btn.primary{:type=>"submit"}
Here's the no-nonsense way of achieving this by adding a new class to your app/helpers/application_helper.rb (don't forget to restart your Rails server when you do this):
#./app/helpers/application_helper
⋮
# add these lines after the ApplicationHelper module
class BootstrapFormBuilder < ActionView::Helpers::FormBuilder
helpers = field_helpers +
%w{date_select datetime_select time_select} +
%w{collection_select select country_select time_zone_select} -
%w{hidden_field label fields_for} # Don't decorate these
helpers.each do |name|
define_method(name) do |field, *args|
options_index = ActionView::Helpers::FormBuilder.instance_method(name.to_sym).parameters.index([:opt,:options])
if options_index.nil?
options = args.last.is_a?(Hash) ? args.pop : {} # pretty sure this shouldn't happen
else
options = args[options_index - 1] # -1 to account for the method name argument
end
label = label(field, options[:label], :class => options[:label_class])
@template.content_tag(:div, :class => 'clearfix') do
@template.concat(label)
@template.concat(@template.content_tag(:div, :class => 'input') { @template.concat(super(field, *args)) })
end
end
end
end
ActionView::Base.default_form_builder = BootstrapFormBuilder
# you can also register this in ./config/application in the config block
# but I was not having a lot of success going that way
# which is why I moved it to the ./app/helpers/application_helper.rb file
Ideally you'd add this somewhere outside of application_helper.rb and load it properly.
What I referenced:
advanced rails studio: custom form builder
Form Builders in Rails
Working With and Around FormBuilder
Updated: 12/21/2011 for handling methods where options isn't the last param.
November 2nd, 2011
I have a schedule.json file that I want to dump to the browser for testing purposes.
This took entirely too long for me to sort out through trial and error, but here it is:
#/app/controllers/some_controller.rb
def schedule
render :file => "#{Rails.root}/app/assets/resources/analytics/schedule.json",
:content_type => 'application/json',
:layout => false
end
October 30th, 2011
When attempting to refactor in VS2010 a message box will appear with the message "Could not prepare files for refactoring".
This is a mildly aggravating bug that I had found a solution for a couple years ago and then promptly forgot. Since moving all my development to virtual machines on my Macs though it has resurfaced - mo' VS installations, mo' problems.
In this case I had a project that is using the Microsoft Web Deployment project. When I went to load our solution up for the first time of course that project type was missing so I searched for it and the first link that comes up is the beta released in April 2010. So I installed that. Whoops.
What you really want is the "Visual Studio® 2010 Web Deployment Projects - RTW" whatever the fuck RTW means [I know its release to web, but seriously, stop will the nonse release acronyms]. You can find it here:
http://www.microsoft.com/download/en/details.aspx?id=24509
You'll need to uninstall the beta if you have it installed before installing the final version.
September 3rd, 2011
I guess the title is a little misleading because there is seldom any fun to be had with the .NET Framework.
But if you've got a Linq to SQL *.dbml and the tool is generating those swell ExtensionDataObject properties preventing you from easily serializing your model classes to JSON and you don't want to make shadow classes (::gasp:: yes I know the .NET Fx loves ceremony, I however do not) then you can use a custom JavaScriptConverter to ignore those properties. When you have control of a class you can put a NonSerialized attribute on properties but that becomes substantially more difficult when a tool is responsible for generating the class file and cheerfully overwrites any changes you may make if you even open the file to glance at its contents. Yes shitty *.dbml tool in Visual Studio, I'm looking at you.
So let's say you have this simple helper class:
// JsonSerializationUtility.cs
public static class JsonSerializationUtility
{
public static string ToJson(this object obj, string wrapper = null)
{
var json = new JavaScriptSerializer().Serialize(obj);
if (!string.IsNullOrEmpty(wrapper))
json = "{ \"" + wrapper + "\": " + json + " }";
return json;
}
public static T Deserialize<T>(string json)
{
var jss = new JavaScriptSerializer();
jss.RegisterConverters(new [] { new ExtensionDataObjectConverter() });
var result = jss.Deserialize<T>(json);
return result;
}
}
... then you'll need this handy ExtensionDataObjectConverter class!
// ExtensionDataObjectConverter.cs
public class ExtensionDataObjectConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get
{
return new ReadOnlyCollection<Type>(new [] { typeof(ExtensionDataObject) });
}
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
return null;
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
return null;
}
}