Thursday, 29 October 2009

Trick found in find(:all)

What happens if you want to search on an class but by an associated class - so I have a class of printers which are a type of organisation. Organisations have names, printers don't (or rather they do, but they have a name by virtue of being a type of organisation). How do I search on their name?

@printers = Printer.find(:all, :include=>:organisation,
:order=>"organisations.name",
:conditions=>['`organisations`.`name` like ?' , "%#{params[:search]}%"]).paginate( :page => params[:page], :order => 'name')


is how.
Couple of things to note - the :include calls in the associated class - and note the back-ticks (not single quotes) around the field - and also note that it is split in two.
Works like a dream.

jQuery awsome find

Just about forever I have had a real problem with jQuery inserting elements into the DOM, and then getting events bound to the new inserted items.
It seems (a) I am not alone and (b) this is the archetypal newbie question.
Yes there is a FAQ on this. And guess who didn't read it?
the answer is instead of
$("#link").click(function(){
// whatever
})


You do
$("#link").live("click", function(){
// whatever
})

This is going to change how I do jQuery forever. And I am embarrassed to say that I never knew it. Ho hum.

PS.
Another trick
Getting the text of a the selected value of a pulldown:

$('#categories').find(':selected').text()


Wednesday, 21 October 2009

collection_select

This guy saved me from tearing out (what's left of) my hair.
Thank you.

Tuesday, 20 October 2009

Haven't given up

Just been working on another project.
Complex forms - you have to love them.
Had a problem with having a form updating more than one model - in this case it has to update an address as well.
Devil's own business getting the drop down menu to work - and then found Ryan Bates' comment - I want to marry him ...

Here is the partial to be rendered
<% new_or_existing = address.new_record? ? 'new' : 'existing' %>
<% prefix = "organisation[#{new_or_existing}_address_attributes][]" %>
<% fields_for prefix, address do |address_form| %>

<%= address_form.error_messages %>


<%= address_form.label :address_1 %> <%= address_form.text_field :address_1 %>



<%= address_form.label :address_2 %> <%= address_form.text_field :address_2 %>



<%= address_form.label :address_3 %> <%= address_form.text_field :address_3 %>



<%= address_form.label :town_city %> <%= address_form.text_field :town_city %>



<%= address_form.label :county_state %> <%= address_form.text_field :county_state %>



<%= address_form.label :postcode_zip %> <%= address_form.text_field :postcode_zip %>



<%= address_form.label :country %> <%= address_form.text_field :country %>



<%= address_form.label :live %> <%= address_form.select :live, [['No', false], ['Yes', true]]%>


<% if new_or_existing == 'new' %>


<%=address_form.label :address_type_id %> <%= address_form.collection_select(:address_type_id, AddressType.find_all_by_live(true), :id, :name, {:index=>""}) %>


<% end %>
<% end %>


Then the model is as follows:
def new_address_attributes=(address_attributes)
#handles the address edit form in the edit view
address_attributes.each do |attributes|
addresses.build(attributes)
end
end

def existing_address_attributes=(address_attributes)
addresses.reject(&:new_record?).each do |address|
attributes = address_attributes[address.id.to_s]
if attributes
address.attributes = attributes
else
addresses.delete(address)
end
end
end

def save_addresses
addresses.each do |address|
address.save(false)
end
end


And there is a callback to save the address in the case of an update

after_update :save_addresses

Getting the address_type collection to work was an absolute bugger - it kept rejecting the
organisation[new_address_attributes][]
saying it wasn't allowed. That was when I found Ryan's comment about using the same fields_for thingy and yay - it all works.

Wednesday, 23 September 2009

Holy crap that was a mind-f**k

nested forms - you have to love 'em.
Nesting with has_many was not too much of a problem. Follow the railscast and it all seems to work just fine - yes it was fiddly, but in the end it comes good.
Nesting with has_one - a total mind fuck.
With has_many you can use association.build to build all the objects you want and then use yr bog-standard controller to handle it for you with the update.
But has_one has a real gotcha. If you try and create two objects - which you may have to to get round the nil problem when using the form_for thingy, then if you try and use association_build, it updates both of them - immediately orphaning one of them as you can only have one associated object. And then all manner of horribleness starts.
After a long, long, long time screwing around with this - came up with the following:
def client_attributes=(client_attributes)
#this little beaut Returns the associated object. nil is returned if none is found (ie on new).
cl = client(force_reload = false)
if cl == nil
build_client(client_attributes)
else
client_attributes.each do |key, value|
unless key == 'id'
cl["#{key}"] = client_attributes["#{key}"]
end
end
client=(cl)
end
end

It is the normal virtual attribute you use to pick it up from the form, and then whack a method in the model. But you have to handle two different situations - one when it is a new build, in which case you won't have an existing client object - so you can go ahead and build it, and the other time when you do.
Then I have manually gone through the new attributes - and leaving aside the id, taken the new values by hand into a temp object (cl), given it the new values from the hash you pass over, and then save it to the child object (client).
Then when that gets handed over to the controller for the normal update, everything is in the right place and there is peace and brotherly love the world over.

Friday, 18 September 2009

redgreen and autoSPEC

Ahhh - the command is autospec, not autotest (RTFM).
Had a problem getting redgreen to work - but commenting out the
require redgreen/autotest inside of ~/.autotest seems to have done the trick

Thursday, 17 September 2009

Rspec

Have put off the day long enough. Got a simple new class to build (address class). Going to build it using rspec from the ground up - not use scaffold etc.
Wish me luck.