Using a select field with Rails nested object forms - ruby-on-rails

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.

Related

Submitting two tables/model data with single/two form on one webpage with single submit button?

My issue is simple, lets say I have two models/tables named 'abc' and 'pqr', both has three columns as 'a','b','c' in abc and 'p','q','r' in pqr. This two models may or may not be related/nested.
what I want to do is to create a single webpage. On that webpage I want to create a single form which will submit the data for two models/table with single button. May be I will create two form but I want only one submit button. How do solve this issue in ruby on rails.
As in rails we have one model per table.
You can only use accepts_nested_attributes_for if the two models are related. Otherwise, if the models are unrelated, see Anton's answer in rails: a single simple_form with two unrelated models? describing how to use the fields_for helper to accomplish this.
I can suggest you something in Ruby side. It is possible to do that with accepts_nested_attributes_for method.
You can add to
models/abc.rb
accepts_nested_attributes_for :pqr
You can find more information about it here.
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

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.

Dropdown Box Ruby on Rails question

I am new to rails so go easy. I have two tables that I am trying to work with here, 'post' and 'category'.
The 'post' table includes the following columns, title:string content:text category:string.
The 'category' table simply contains name:string.
The idea is that the client can manage the categories and also when adding a new post, they can select from a drop down that references their categories.
What is the best way to accomplish this?
You might want to model the category differently. The usual approach is to create a PostCategory model and controller, and use a relation from posts to PostCategory. Read up on belongs_to and the other rails associations before you get much further into this project. When you're ready to continue, take a look at formtastic, it makes handling the forms for the associations much easier to code
flyfishr64 is right, the "correct" way to do this would be to put the categories in their own model/table.
There's lots of helpers like collection_select that will take your list of categories (PostCategory.all) and make a dropdown list for you with the appropriate name to save it in a specific field.
That said, you could pull a distinct list of the entries in that column already and use that for your dropdown, but it's a lot more hassle than just making a model for the category.

rails lazy load of model attributes

Normally rails loads data with a :select => "*" from the database. I know I could change this. But I'd like to go another way: always only select "id" and load the attributes automatically later on when they are needed.
Example:
accessing user.description should if it's been loaded yet. if not, trigger a "SELECT description FROM users WHERE id=#{self.id}" and set it.
Anyone know if there's a rails plugin which does this? Or how to implement it?
Thanks,
Corin
I wrote a Rails plugins that does exactly this lazy_columns. Notice that a much better approach is to create a new model with the big columns you want to load on demand (since Rails load related objects lazily by default).
A quick google search turned up this, but I'm with glongman. I can't imagine what kind of performance issue would require this...
It is wise to just refactor your main "huge blob" fields into a separate model (like BookBody) which is usually not needed when operating with models in bulk. Alternatively, you can use the :select option on finders
BookWithHugeBlobOfText.find(:first, :select=>"only,small,columns")
Records selected that way will be readonly since the Rails philosophy says (and rightfully so!) that you need to have all data on the model to validate it. Lazy loading would be a nice to have, but as it stands now I would discourage you from using monkeypatch plugins for this.
Another option would be to create a SQL view which would only contain the lightweight fields and run your ops from there.

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