Posts [ 41 to 60 of 83 ]

Re: Multiple child models in a dynamic form

Hi, thanks for the tutorial!

I do have a question though, How would you do it to, for example, sum fields in an estimate, I'm guessing with observe_field, but I not sure how to implement it because of the ids of each child. Example, you have an estimate and this has many products (product name, unit cost, quantity, etc), that you can add dynamically to the estimate, just like your tutorial. So, my question is how would you do it to show the total(rjs?) of each product ( product_unit_cost x product_quantity = product_total) in the same row(just view) and also how to show the estimate's total ( product_1_total + product_2_total + ...).

Other question, when the user save the estimate, sometimes they left empty products(child) but they are saved in the db anyway, how can I do it to not save the empty childs?.

Re: Multiple child models in a dynamic form

johnT wrote:

So, my question is how would you do it to show the total(rjs?) of each product ( product_unit_cost x product_quantity = product_total) in the same row(just view) and also how to show the estimate's total ( product_1_total + product_2_total + ...).

This is actually a little complicated, and not too different from the post before yours. The problem is that, when adding an item the server doesn't get called, it is all done locally with Javascript. You could set up a complex javascript which counts all displayed records every time you add/remove a product but that also means you have to put the individual product price somewhere in the DOM, which you might not know if you're giving the option to add blank lines.

When it comes to "shopping cart" type solutions like this I prefer using Ajax. Simply call the server for each product that you add and use rails to calculate the items in your cart. Then you can use a simple rjs script to update the list. In the end, if your display uses calculations or other complicated stuff, this is probably a better idea.

johnT wrote:

Other question, when the user save the estimate, sometimes they left empty products(child) but they are saved in the db anyway, how can I do it to not save the empty childs?.

Re: Multiple child models in a dynamic form

Because I don't know much of rjs I ended up doing this(probably the worst thing to do) but it works for now while I learn ajax:

-first, I created a fake column in the items table, this because I didn't know how to save a record that is in a disabled text_field into the db. (If someone knows how to do it please tell me)-second, I set the real unit_total field as a hidden_field.

-third, at the end of the child partial I scanned the prefix for each field, because each item has a different ID, in my case 'estimate_items_attributes_0_unitcost', 'estimate_items_attributes_1_unitcost'....

Re: Multiple child models in a dynamic form

The tutorial is brilliant...

But I'm having problems using this as I move to a non-scaffolded project. I think there's something blindingly obvious to a real Rails programmer that I've missed out or forgotten to do. Signatures of the problem? When I use "form_for" the model at the root, I don't get an "ID" in the generated form or the response hash and I have to manually add a "url => {:action => 'update' }" because "(model)_path" is undefined. That missing ID means that every edited model instance is doubled. Amazingly, the *children"/"tasks" equivalent *do* get IDs and get updated rather than duplicated.

I couldn't see the "(model)_path" defined in any scaffolding. But something in a scaffolded project makes it spring into existence... What have I missed? My guess is that I need to define some method name to make it work.

I'm using ruby 1.8.7 patch level 72 on Mac. Rails 2.3.2. gem 1.3.3. I can run the github/alloy/complex-model-examples code, so I'm pretty sure that my base installation is OK.

--

SOLVED:

I needed to change config/routes.rb. I had explicit map.connect routes for new, create, edit, etc.

I needed to have an additional map.(model) route and now the path helpers work.

That wasn't really obvious for someone justing moving from scaffolding to "real" Rails.

This example assumes you have a text field with id "total_sum" that can hold the result price, you can use a div or whatever too if you prefer. If you do you will have to use .innerHTML instead of .value.

All that said, I personally would still sooner do this through ajax/rjs simply because it gives the end user less of a chance to mess with your inputs. I'd especially guard against letting the form determine price information that is saved to the database, as forms can be manipulated by a savvy user or even circumvented completely.

Re: Multiple child models in a dynamic form

JezC wrote:

SOLVED - at least partially.

I needed to change resources.rb. I had explicit map.connect routes for new, create, edit, etc. I needed to have an additional map.page route and now the path helpers work. That wasn't really obvious for someone justing moving from scaffolding to "real" Rails.

Did you mean routes.rb? The (object)_path you mention is indeed defined there, and if you're not using the correct syntax may not be available. The traditional way to define a route in rails is as follows:

map.connect '/:controller/:action/:id'

This simply connects a potential path to a controller and action without giving you any additional url helper.

Rails' default url helpers (e.g. (object)_path or edit_(object)_path) are automatically generated when you add a resource to your routes. A resource is another name for a controller and model that operate in a predictable (RESTful) way. For instance, say I have a blogs controller and model, I can define the route like this:

map.resources :blogs

This should immediately give me the blogs_path, edit_blog_path and new_blog_path url helpers.

Re: Multiple child models in a dynamic form

This was fantastic! One hiccup that I encountered (due to my ignorance of how the various components work together) was how the name of the partial is used, and how changing the name of the partial will break the code (w/out making a minor change).

The locals hash seems to do the job of syncing up the partial with everything else, and so far I've got no issues (and can rename my partials to my heart's content). I figured I would post for anyone else who might be facing a similar situation, though I suspect my newness to RoR is a major factor . I'm 99% certain that I'm missing something super-clever, so feel free and share any insights you might have. I'm next going to be digging into extending this across a shared-table inheritance set of models, and we'll see how DRY we can keep things.

Re: Multiple child models in a dynamic form

Hi Victor,

You're right, render :partial call does apply some Rails magic to the local variables. When you use the :locals hash, as you found out already, you can define local variables for the view. However there is a "special" local variable which you can assign through :object. This one will automatically assume the name of the partial itself.

And there's an even more magical way to handle the first case, in which we're sending a Project object to the project partial. When object and partial share the same name you can do this:

<%= render :partial => @project %>

This will assume you want the partial named _project.html.erb and pass it the local variable project (containing @project), so it has the same result as the top example above.

@ST-303:

Apologies for the late reply, I missed your question when you first posted it. Yes you can add visual effects to the helper, but it's slightly more complicated than normal because, similar to the record ids, we'll need to find a way to address the new partial which has an unpredictable (client-generated) unique ID. Here's one way to do it..

# First let's find the new div. We'll look for all ".task" class divs and select the lastest one: page << "new_task_element = $$('div.task').last();" # Then we simply apply the Scriptaculous Effect to that element: page << "Effect.SlideDown( new_task_element );" end endend

You just have to be careful there are no other elements with class "task" in your view. Another thing to keep in mind is that a lot of "appear" effects don't work properly if you don't hide the div by default, so in the _task partial we'll have to add style="display: hidden;" as follows:

Re: Multiple child models in a dynamic form

Dagnan, does that mean you want to be able to insert items in the middle? Or is it alright to have new items appear at the bottom first? If the latter is ok, it's actually not terribly hard probably.

First I would make the tasks (items) act_as_list, and give them an extra position integer column. Next I'd put the tasks in the form in a list (UL) tag and add a hidden field called "position" to the _task form partial. Now you can make the UL a sortable_element and use the onChange action to loop through the tasks ($$('.task') for instance) and assign them a number based on their order in the dom, replacing the value of the hidden position field.

Then when you submit the position should be saved to the database automatically.

Re: Multiple child models in a dynamic form

Actually I've managed to realise it today.

I didn't implement the act_as_list plugin however :sI use two buttons near each item to move up and move down the item... A bit long, because I had to do all the event handlers and verifications in jQuery, but it works.

I still have a problem though. When the form is submit, or when I want to edit a project, tasks are not in the 'position' order, but as they were entered in the DB.

Re: Multiple child models in a dynamic form

My motto tends to be: if it works, it works That said I wasn't aware the child_index affects sorting at all, and it might mess up your actual resource index numbers. Unfortunately I don't have time to try it out right now, but you may want to check your database stays consistent if you submit like this.

I think the "proper" way to do it is to add an order option to the parent object's association, then the child objects should sort on their own. So in this case in the project model:

Re: Multiple child models in a dynamic form

Re: Multiple child models in a dynamic form

Hello, great tutorial.

I've been tinkering with this but what ever I do I can't seem to get the javascript link working properly. Everything up to that point works perfectly.

The new text fields of the new atritbute never shows up. ( I know "attribute" but it's all over my code now I'll fix it tomorrow. ) I'm guessing the "task" in the example code refers to the div and not an instance of Task. Am I correct in this?

Re: Multiple child models in a dynamic form

amrypma wrote:

I've been tinkering with this but what ever I do I can't seem to get the javascript link working properly. Everything up to that point works perfectly.

The new text fields of the new atritbute never shows up. ( I know "attribute" but it's all over my code now I'll fix it tomorrow. ) I'm guessing the "task" in the example code refers to the div and not an instance of Task. Am I correct in this?

Hi Auke,

You're right! $('tasks') refers to the container div (<div id='tasks'>) in the new view (new.html.erb)

...

I just spent 10 minutes writing about how it all looks good and then I finally noticed it. I think the problem is with this line:

I think this $('atribute') needs to be plural, so $('atributes'), same as in the old page.insert_html line under it that you commented out.

By the way, you might already have it but if you're using javascript/ajax for your apps, the Firebug addon for Firefox is a god sent. It has a javascript console that actually tells you what's going wrong instead of some obtuse "script error" message like IE has