Friday 30 October 2009

save! and save, update_attributes and update_attributes!

This little bugger ate an hour or so of my day. Had a model with validation on a telephone number field which it should fail if someone puts in letters etc.
For some reason I had changed the update to update_attributes! rather than leaving it as update_attributes (teach you to fiddle with things).
save!/update_attributes!/create! throws an error - and unless you have some way of catching it you will end up with
ActiveRecord::RecordInvalid (Validation failed: Name can't be blank, Name has already been taken, Main number only digits, ., +. (, ), allowed):

instead of the scaffold-like

Let that be a lesson

Thursday 29 October 2009

406 Not Acceptable error on jQuery ajaxSubmit

Doh.
Remember to add format.js to the response block - otherwise it falls over ...

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.