Creating a Rails dropdown for related database - ruby-on-rails

I have 2 models, venues and areas (areas consists of id and name fields). They are related as: one area has many venues and each venue belongs to an area.
To assign a venue to an area I am currently entering the area_id number into a text field in the create new venue page. I can then display which area the venue belongs to with:
<%= venue.area.name %>
Instead of having to enter the ID number of the area in the form I would like to have a dropdown listing the area names for all the area records and for the selected one to be associated with that venue on save.
The new venue form:
<% form_for #venue do |f| %>
<p>name: <br>
<%= f.text_field :name %></p>
<p>address line 1: <br>
<%= f.text_field :addressline1 %></p>
<p>address line 2: <br>
<%= f.text_field :addressline2 %></p>
<p>address line 3: <br>
<%= f.text_field :addressline3 %></p>
<p>area_id: <br>
<%= f.text_field :area_id %></p>
<%= submit_tag %>
<% end %>
I have tried:
<p>area_id: <br>
<%= collection_select(:area, :name, #areas, :id, :name) %>
But get:
You have a nil object when you didn't
expect it! You might have expected an
instance of Array. The error occurred
while evaluating nil.map
Any help is much appreciated!

It looks like #areas isn't defined and maybe a couple other issues as well. Try this:
<%= f.collection_select(:area_id, Area.all, :id, :name) %>

As aNoble said, it's right!
If you want to order by name, just use the following:
<%= f.collection_select :area_id, Area.order(:name),
:id, :name %>

Related

Rails Form - Error when deselecting on a collection_select

I have a bare bones rails form. I have minimal javascript for adding and removing the category fields. I don't want it to be fancy so a rails specific solution is what I'm looking for.
The form is for Posts with a has_and_belongs_to_many relationship to Categories.
<%= form.collection_check_boxes :category_ids, Category.all, :id, :name, {prompt: "None", include_hidden: false}, {multiple: true} %>
<% #posts.categories.each do |category| %>
<%= form.fields_for :categories, category do |c_subform| %>
<div>
<%= f.hidden_field :_destroy %>
</div>
<div class="row clearfix">
<%= f.label :name, "Category name", class: 'form-label' %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<% if #posts.new_record? %>
<div>
<%= link_to "Remove Category", '#', class: "remove_fields", style: "color: red" %>
<%= link_to_add_fields "Add Category", form, :categories %>
</div>
<% end %>
<% end %>
<% end %>
I added the ability to select multiple categories and there is another fieldset below allowing the user to create new categories. The issue is while editing a post, if I deselect one of the previously selected categories (in this case, the one with ID of 3), on save I get the error: ActiveRecord::RecordNotFound Couldn't find Category with ID=3 for Post with ID=23.
I would love for the update action to just delete the posts_categories record connecting Post 23 and Category 3 without deleting Category 3.
I want to add that the form worked fine until I decided to add the multi-select functionality by making it checkboxes that could be deselected and also required the category names be unique.

Rails form_for added empty model

I have started the "Get Started Guide" from the ruby on rails website. Everything works fine, but when I change the order of showing all comments and than display the comments-form in the other way round, than the form_forfunction adds a empty comments model to #post.comments and so, I display one empty comment in the loop.
Here is the view:
<h1><%= #post.name %></h1>
<p><%= #post.text %></p>
<h2>Add comment</h2>
<%= form_for([#post, #post.comments.build]) do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :email %><br>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<h2>Comments</h2>
<%= render #post.comments %>
The loop display two comments. One, that exists in the db and one, that has just empty attributes. If I delete the form, than all is shown up correct.
You can select only your persisted comments:
<%= render #post.comments.select(&:persisted?) %>
When you do post.comments.build against some post, it will be added to the post.comments collection and will be displayed along with other comments.
You can always use persisted to check if the object is present in database meaning id is assigned to it.
#post.comments.select(&:persisted?)
Note: .present? check donot work here so you have to use .persisted.?
present check only assosiated to the parent.

Active Admin, one page - two diffrent forms

I have following two resources:
Position
JobTitle
And a position belongs_to job title.
In page Position, I create new position, with job_title select and some other selects. I need also create new job_title in this page, instead of choose select variants. So, in fact, or I choose job title in existing base, or create new, and save it for this position.
How can I make this? I looking for answer, and reading docs, but nothing!
You need to use fields_for in your view to send params for two models at a time.
Here's how I would try to solve to problem:
<%= form_for #job_title do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_field :description %>
</p>
<%= f.fields_for :position do |builder| %>
<p>
<%= builder.label :name %> <br />
<%= builder.text_field :name %>
</p>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>
And then, in your controller, you need to create the association. For more information, you can check out the railscast for nested forms.

Rails: loop through array to create output

I have a model "tube" which is a database having the various data for vacuum tubes. I want to dynamically loop through all the columns and create a basic table for my "new" and "edit" pages.
I grab the attribute names like this:
<% attr_array = #tube.attribute_names %>
And I want to do something like this:
<% attr_array.each{|x| text_field :x } %>
in hopes of dynamically generating this:
<%= form_for #tube do |f| %>
<%= f.label :name, :class=>'std_label' %>:
<%= f.text_field :name, :class=>'std_input' %>
<%= f.label :functional_class, :class=>'std_label' %>:
<%= f.text_field :functional_class, :class=>'std_input' %>
<%= f.label :base_type, :class=>'std_label' %>:
<%= f.text_field :base_type, :class=>'std_input' %>
.... and so forth ....
<%= f.submit %> <% end %>
But of course this does not work, not by a long shot. How can I generate my text_field inputs dynamically based on the attribute_names array? The table I am using has about 30 attributes and I think it's silly to build them all by hand, especially given that if they change in the future then the code will break. Googling and reading the API have given me the lectures on why this doesn't work, but has left me hi and dry with a code example of what does.
Accurate help appreciated.
What about:
<%= form_for #tube do |f| %>
<% #tube.attribute_names.each do |attr| %>
<%= f.text_field attr, :class=>'std_input' %>
<%= f.label attr, :class=>'std_label' %>:
<% end %>
<%= f.submit %>
<% end %>

Adding validations without knowing the fields

My example form
<% form_for #ad do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :ad_type_id %><br />
<%= f.collection_select(:ad_type_id, AdType.all, :id, :name) %>
</p>
<p>
<% #ad.ad_properties.each do |property| %>
<%= property.name %>:
<% f.fields_for :ad_values do |value_field| %>
<%= value_field.text_field :ad_id, :value => #ad.id %>
<%= value_field.text_field :ad_property_id, :value => property.id %>
<%= value_field.text_field :value %>
<% end %><br /><br />
<% end %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p><%= f.submit %></p>
<% end %>
Explanation:
Ad has many properties. I can add new properties at any time (it's a normal model).
Lets say the Ad is of the type 'hotel'. Then I would add properties like 'stars' and 'breakfast_included'
Then I store each of these properties' values in a separate model.
And all this works fine with my form above.
My problem:
These fields are not validated because I can't know what their names are.
I need to add validations dynamically somehow.
My thought:
#Before the normal validations kick in
def add_validations
self.properties.each do |property|
property.add_validation :whatever #somehow :)
end
end
How could I do this?
Have you tried with polymorphic associations ? That's maybe a cleaner approach.
http://railscasts.com/episodes/154-polymorphic-association
Disclaimer: I've never done this before, so I'm not 100% sure it will work.
But as long as you can get the type of the object you are working with, you can use the Rails constantize method to get the model it references (I'm assuming that if ad can be of type Hotel, then you have a Hotel model). At that point you should probably have the appropriate validations on your Hotel model.

Resources