Rails, managing history of model updates - ruby-on-rails

I'm not sure what's the best approach in my situation, I would like an opinion.
My situation is:
I have a "Ticket" model, having several fields of many kinds: text, numerical and associations. Tickets support comments through the acts_as_commentable gem.
The tickets are generated by users, who can comment and modify their own tickets.
Because the fields of a ticket can change over time I would like to allow my users to modify several of them. What I need though is to keep a commented history of all the changes, so that at any moment they can see in a ticket what, why and when was changed, in the comment, timestamp and list of changes that they can see together with the comment.
I was thinking to solve this by generating a "TicketUpdate" model, have the TicketUpdates generated in the Comments form (using fields_for and accepts_nested_attributes_for).
Basically the user could select in a drop down list (i.e. a select tag) the field they want to change, changing the value of the drop down would trigger an event to show an appropriate input field (input for the text and numeric fields, select for the associations) with the old value pre-populated
I could intercept the TicketUpdates in the "comment/create" controller performing the updates.
This approach would look nice and sweet to the user, but I don't see how to implement in a neat or DRY way.
Because ticket has many fields and they are mixed decimals and associations, I would have to implement specific logic for each field, both in the view and in the controller.
I'm not sure if there's maybe a better approach, or there's actually any gem or trick to get this done easily.
anyone got anything to recommend me here?
I'm using rails 3.2.8.

Related

How do I create a fields_for a potentially unlimited number of children objects?

I'm making an application that involves booking appointments for users. I have a User model and an AvailableDate model. The user has_many availble_dates and the AvailableDate belongs_to user.
I want to present a form for the user so that they can mark a couple of dates in a calendar and each of the dates they mark will become an AvailableDate object tied to that user.
At the moment my solution is to do all the work that a form_for helper would normally do manually. This involves a lot of javascript and is generally just getting far too messy.
I can't figure out how I should make a form_for tag work when I need to create potentially infinitely many dates. In theory a user could keep marking off dates in the future as available. If I knew how many dates I needed to create for a user, I could do user.available_dates.build, N times. But this doesn't work here.
Can anyone help? It like this problem should be pretty common. Am I designing my application wrong?
One technique is to render the fields for your association once, outside the form.
When the user performs whatever interaction that should create a new set of inputs you use javascript to clone the initial set of fields and insert them into the form. The one thing you need to do is change the name of these inputs so that they are unique. Usually people use the current time in milliseconds for this unique identifier.
Been there & have found several resources to help: Tutorial & Cocoon
The bottom line is you need to ensure child_index is unique for each field. The tutorial I use has child_index: Time.now.to_i to create a truly unique id, consequently allowing you to add as many fields as you want
The best way to do this:
Render fields_for as a partial (passing your form builder object)
When you want to add new field, create ajax_field action
Make ajax_field view have its own form_builder
Both your original & ajax_field forms will call the partial
On front-end, you can use JS to GET new form action & append field to page
I can give you code if you want

Retrieving field params field in rails

I have been trying to analyze this problem very closely but I am still yet to find a good way to approach it. (Hope my explanation is good enough)
So I have three models [user, status and milestone]
the status model belongs to the user model
The milestone model belongs to status model and also to the user model through the status model
Okay so I want to tie each milestone to a model by doing something like (milestone.build_status, this is pretty easy from the CLI, I have tested and tried it, and it works as expected.)
So the big issue I am having is on the web page. I am displaying all the statuses (I have already handled cases when the user enter a status) to user with a corresponding text field where they can enter their milestone, well when I do I post I can only get the params of the text field that was supplied (duh! isnt that obvious).
My question would be what are some possible approaches that I can use to figure which particular status that the user entered the milestone for.
I think you may be looking for Active Record Nested Attributes
This will allow your forms for your object of the User model to also accept input for its associated Status and/or Milestone objects for creating and updating each associated records all in one transaction.

A few intermediate Rails3 Questions

I'm building an app called "CourseWork to dig into rails/develop my skills and I have a question about how to structure it. Users have a resource called "CourseGrading" that is able to create categories and belongs to "Course". Each "category" should have a name, a percentage out of 100 and a course_id. I need to add these percentages together and alert users if the total isn't 100 while still saving.
Then the user's generated "categories" should populate an enum_string specific to that user in a resource called "CourseAssignment" which has a name, description, category and finalgrade.
Can anyone give hints or resources for how best to accomplish this? Thanks
You probably want to take a look at Active Record Callbacks. These will allow you to insert some code to be run when creating/validating/updating/deleting models.
You should probably make use of the ActiveRecord validations.
Check out this guide that explains how to write your own custom validator. Your custom validator would run when the form gets submitted, and in it, you would grab the percentage params and do your check. If it's not what you expect, you can just add an error to the form and the validation process will just kick the user back to the form page and display the error.

Before save action... split input field

I have two models and controllers:
Snippets, and Tags.
There is a belongs_to relationship, with tags belonging to snippets. This works well, I have a text field which creates a new tag associated with the snippet when the user submits a snippet.
I want to be able to have a text field which, when submitted to a function (in the model) would split the text on commas (e.g. split(",")).
However, I'm having a little trouble with it.
My though process was, def a function on the Snippet model that splits the input then loops the array of the split, creating a new Tag associated with the Snippet at save time.
Sounds easy enough, but with the RoR magic it's just not happening for me :)
Can someone shed some light / link to a document or something - would be grand!!
Using rails3 with ruby 1.9.2 - normally PHP dev but giving this ruby a go. Magic.
There is a Railscast that explains how to use a virtual attribute in your model to convert submitted "tag_names" into associated models.
It also shows how to do a has_many :through association (called "Taggings") so that tags can belong to many snippets. In your setup, a tag can only belong to one snippet, so you would likely be creating many duplicate tags, when in fact they're the same tag, just associated to different snippets.
If you prefer reading to screencasts, you can check out the transcribed ASCIIcasts.

RESTful way to do degradable Multiple Models in a Form in Rails

So far, I've not been able to find a solution that is able to allow a form to interact with two models that have a one-to-many relationship. Say for example, a customer has many items.
Currently, I've implemented solutions using Javascript that enables users to add/remove rows to the item list. Let's keep it simple, we're creating new records here.
In improving this to be degradable, I've instead created a 'Add Item' button that commits a different value, so that in my create action, I'm able to capture the new attributes and add a new Item to the customer object.
However, since item is new and has no id, I have no way of removing a particular item. I've thought of using indexes and added post buttons/links to remove, but this sort of makes everything messy and I can't use my partial for collections. So I feel like it's a hack; is there a better alternative?
You want to use accepts_nested_attributes_for. The Railscasts episode henrikloevborg mentions covers a method of doing this kind of thing that's been obsoleted by accepts_nested_attributes_for.
You can do it without accepts_nested_attributes_for. Which might be necessary if you don't want to upgrade to Rails 2.3.
In your javascript to remove an item, you should add a hidden field to the form called _delete with the value of true. Then in your controller. Ignore any new records with the _delete field, and destroy any existing ones.
All that's built in to accept_nested_attributes_for
Play around with the code in the complex-forms-exmample github repository. It's essentially the code from Railscast #75 updated to use the newer feature, accepts_nested_attributes_for.
You will notice that it doesn't use RJS to accomplish the dynamic addition/removal of records. Also compared to what you've been doing it creates on submit, not during a remote call. The automatic addition/deletion of items is handled using content_for tags to create a template stored in a javascript function and the Prototype library to modify a hidden field, which accepts_nested_attributes_for uses to destroy objects you want to remove.

Resources