Rails 3.1 Dependent / Cascading Dropdowns - ruby-on-rails

I am getting to grips with Rails 3.1, and I am hoping that someone can point me in the direction of a Gem that will allow me to use dependent selects on a form (or indicate how this is best done in Rails 3.1). I have come across the chained_selects plugin, but that seems to rely on prototype, so it is not ideal in 3.1.
The simplest example of this is car makes/models:
I have 3 models: vehicleMake, vehicleModel and vehicleTrim. I also have assignment tables vehicleMake_vehicleModel and vehicleModel_vehicleTrim, which specify what models are appropriate for each make etc.
I have a vehicle model which I am trying to populate with a make, model and trim. The vehicle model belongs_to vehicleMake, vehicleModel and vehicleTrim.
How can I ensure that the dropdown for model only shows models for the make that is selected (and thus for trim)? As a second point, how can I validate this in my vehicle model?
Thanks!

I don't know of any jQuery plugins that do that off the top of my head. But really it's just a series of Ajax calls.
When an option is selected from the Make drop down, you send that to the server (via Ajax), get the associated Models back, and populate the next drop down with those options. Then repeat for Trim.
As for validation, you'll probably want to use validates_inclusion_of or just write it manually:
validate :model_matches_make?
def model_matches_make?
unless Make_Model.where(make: self.make).map(&:model).includes?(self.model)
errors.add(:make, "is not valid for your model")
end
end
(using map feels wrong there so maybe there's a better way)

Related

Edit models with complex primary key with Active Admin

I'm having a trouble with opening AA edit-page for a model, which has a lot of associations.
What I had it's like 50 selects, opening at once. And this page turns to be deadly slow.
After reading this ActiveAdmin: How to handle large associations I considered to use select2 instead of usual select, but things get even worse.
That was because most of the time Rails spent in generating views, not in querying database. So with fancy select2 it reasonably spends even more time in views.
With that knowledge in mind, I decided to not have select inputs on that page at all. So I'll edit "main" object on that slow page, but connected with has_and_belongs_to_many objects should be edited separately.
But after that decision I've faced with a trouble: how should I edit tables with a complex primary key: not just id, but :person_id and :organization_id.
AA by default generates urls like that: /admin/person_organizations/:id/edit, but I need something like this: /admin/person_organizations/:person_id/:organization_id/edit
Any ideas?
ActiveAdmin should be able to handle custom primary keys by default. Just be sure that you add the definition to your model like this:
class Person < ActiveRecord::Base
self.primary_key = 'person_id'
end
After a while I've decided that I don't even need to have multiple keys here since Rails generates artificial id field for habtm tables. And as my goal was to edit this table, I've finished with standard ways of doing this.

Rails, managing history of model updates

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.

Add a calculated field to AR model in RoR 2

I am new to RoR and working on an existing Rails 2 app. The app reports on a number of metrics, and I need to add a new metric that is a ratio of two of the others. I'd like to understand the "right" Rails way to do this kind of thing. But I also want to get it done quickly and with minimal risk to the rest of the code. I want to extend the reporting, summary, graphing, and aggregation logic on the existing metrics to the new calculated field, without having to re-implement everything in a slightly different way.
I could add a field to the DB and install a trigger procedure to maintain it. This has the advantage of pushing the work into the DB, and allowing me to index the field if necessary, but it consumes another field in the DB, and I don't think I really need an index on the field at the moment. What would the AR migration look like?
I could create a view that calculates the field. How do I just switch my model to use the new view that has the new field without disrupting the rest of the code? What does the AR migration look like?
I could add the new field into the queries ... SELECT my_table.*, a/b AS ab_ratio FROM my_table ... does this mean I need to examine all of the .find calls on that particular model and change those? Is there a better way to do it?
It would be very helpful to have some code examples of where and how this kind of thing is implemented and/or documented.
I recommend using events on the model to calculate a synthetic value and keeping any business logic/triggers out of the database:
class MyRecord < ActiveRecord::Base
before_save :update_ratio
private
def update_ratio
self.ratio = self.a / self.b
end
end

Composite entity scaffolding in Ruby on Rails

I am new to Ruby on Rails. So far, I have only created CRUD operations by using scaffolding. Now, I need to integrate two entities into single form using scaffolding, not by hard coding it.
How can we scaffold two entities together using script?
I have two entities, Student_address and Student_phnumber. I want to scaffold these two entities into a single form where I can do CRUD operations, and I want to achieve this by scaffolding.
Student_address is an entity consisting of Hse_name, Street_name, etc.
Student_phnumber another entity consisting of ph_number, type, etc.
I want to scaffold these two entities together.
Scaffolding is nothing more than a generator set up to model a complete basic resource. There are many other generators, other than scaffolding, that come with Rails by default. None of them are set up to generate resources for a set of related models. I suspect that a large part of this is because of the wide range of methods to express such a relationship make creating a generic UI virtually impossible. Also, scaffolding is more set up to get you up and running very quickly, with the intention of being modified to suit your needs. These modifications are usually fairly involved for any non-trivial application. There are many 3rd party generators out there, including the popular nifty generators, but none that create the kind of code you want to generate, as far as I know. If this is a relationship that you need to set up frequently, you may consider creating a generator of your own to handle the task - it's actually pretty easy. A good way to do it is to implement your ideal case, then create a generator from it.
Edit:
Also, you may wish to adjust your variable/attribute names. They should be lowercase and underscored, so Street_name would become street_name. Arbitrary abbreviations also make it very hard to code/maintain, so Student_phnumber would be better expressed as student_phone_number. The reason for doing this, apart from consistency (ph_number vs Student_phnumber, for example), is that Rails actually uses the casing and spacing in internal methods like these.
Let me see if I understand you.
The model/entity relationship you are describing is:
student
address
- house_name
- street_name
- etc
phone_number
- number
- area_code
- etc
You want to:
a) automatically generate the models
b) automatically generate a controller/view with a form to create a student, including fields to set up the address and phone number
Okay. b) can't be done via a Rails scaffold. You can, however, use the ActiveSupport gem (docs here) to achieve this. Here's what you do:
gem install active_scaffold
rails g active_scaffold Student name:string
rails g active_scaffold PhoneNumber area_code:integer number:integer student_id:integer
rails g active_scaffold Address first_line:string second_line:string student_id:integer
The only manual work you'll have to do here is pop into the models and add the relationships:
Address
belongs_to :student
PhoneNumber
belongs_to :student
Student
has_one :address
has_one :phone_number
What ActiveScaffold will do is automatically produce for you a view like this:
Fill in that form and your models will all be saved and linked together!
Is this what you are looking for?
rails generate scaffold Student student_address:string student_phnumber:string

Using a select field with Rails nested object forms

Is it possible to use select fields with nested object forms feature of Rails 2.3?
Example:
Suppose you have a Article model, Category model, and a ArticleCategories join model. Article has_many Categories through ArticleCategories.
On our Edit Article form, you want to have an HTML select list of all the available categories. The user can select one or more Category names to assign to the Article (multiple select is enabled).
There are lots of ways to do this, but I'm wondering if there is a simple way to accomplish this using the nested objects feature. What would the form look like in your view?
Check out the nested form example from Github:
http://github.com/alloy/complex-form-examples
It's been a while since I looked at it, so I'm not sure if it covers exactly what you wanna do, but its a nice source for ideas / patterns.
Assuming you have defined the models and their relationships so you can do this:
#art = Article.find(article_id)
#art.categories # returns list of category objects this article is assigned to.
Then I usually use http://trendwork.kmf.de/175
You need to copy the JavaScript file into public/javascripts but after that you can just create the form element with something like:
swapselect(:article,#art,:categories,Category.find(:all).map { |cat| [cat.name, cat.id] })
(I would tend to wrap that in a helper to make the call even cleaner)
One small gotcha is that for very long lists it can run a little slow in IE6 because there's quite a lot of appendChild calls in the js which is notorioulsy slow in IE6
Update: Apologies. This doesn't really answer your original question, which was specifically about the Rails 2.3 feature. The swapselect option is version independent and doesn't make use of newer Rails functionality.

Resources