Ruby on Rails - Form for multiple new Objects - ruby-on-rails

I got a backend(Namespace admin) and want to create 4 new database entries with 1 form submit(4 new countries). What I got so far:
In my countries_controller.rb
class Admin::CountriesController < Admin::AdminController
def new
#countries = Array.new(4) { Country.new }
end
end
In my new.html.erb:
<%= form_for [:admin, #countries] do |f| %>
<% #countries.each do |country| %>
<div class="row">
<div class="col-md-6">
<div class="form-group col-md-6">
<%=f.text_field :country, :name, :class => "form-control", :placeholder => "Country 1" %><br>
<%=f.text_field :country, :iso, :class => "form-control", :placeholder => "us" %>
</div></div></div>
<% end %>
<% end %>
But that doesn't work and I get a undefined method model_name for Array:Class error. What is the right way to do this?

form_for is for a single ActiveRecord object, but you're using it with an Array of object :
<%= form_for [:admin, #countries] do |f| %>
Either create a form per object (with each form a save button):
<% #countries.each do |country| %>
<%= form_for [:admin, country] do |f| %>
...
<% end %>
<% end %>
Or see this question for a solution using only one form: Multiple objects in a Rails form

Related

Ruby on Rails: Keep check boxes selected after search

In my RoR application I have a form whereby users can search for their contacts by first name and select the ones that they want to send an email to. My problem is that after searching for say "Tom", and selecting the checkbox for "Tom", if they then reset the search to display all check boxes "Tom" is no longer selected.
Can someone please tell me how this can be sorted?
The code in the view is:
<div class="panel-body">
<%= form_tag '/emails/contact_search', :method => 'get' do %>
<p>
<%= text_field_tag :search_string, params[:search_string], :placeholder => "Search by firstname" %>
<%= submit_tag "Search" %>
</p>
<% end %>
<%= form_for(#email) do |f| %>
<fieldset>
<div class="form-group">
<label>From Email Address</label></br>
<% #useraccounts.each do |useraccount| %>
<%= f.radio_button :account_id, useraccount.account_id, :checked => false %>
<%= f.label :account_id, useraccount.account.email, :value => "true" %><br>
<% end %>
</div>
<div class="form-group">
<label>Contacts</label></br>
<%= f.collection_check_boxes :contact_ids, #contacts, :id, :fullname, checked: #selected_contact_ids %>
</div>
<div class="form-group">
<label>Groups</label></br>
<%= f.collection_check_boxes :group_ids, Group.where(user_id: session[:user_id]), :id, :name ,{ prompt: "name" } %>
</div>
<div class="form-group">
<label>Attachment</label>
<%= f.file_field :attachment, :size => 42 %><br>
</div>
<div class="actions">
<%= f.submit "Continue", {:class => 'btn btn-primary '} %>
<%= render "/error_messages", :message_header => "Cannot save: ", :target => #email %>
</div></br>
</fieldset>
<% end %>
</div>
The controller code for the search is:
def contact_search
#email = Email.new(session[:email_params])
#email.current_step == session[:email_step]
#useraccounts = Useraccount.where(user_id: session[:user_id])
#contacts = Contact.contact_search(params[:search_string])
if #contacts.empty?
flash[:notice] = "There are no emails with that subject"
#contacts = Contact.all
end
render :action => "new"
end
private
def email_params
params.require(:email).permit(:subject, :message, :account_id, { contact_ids: [] }, { group_ids: [] }, :attachment)
end
And in the model:
def self.contact_search(search_string)
self.where("firstname LIKE ?", search_string)
end
I cannot work out how to keep a checkbox selected after a user then searches for something else or resets the search, can someone please shed some light on how this can be achieved?
This seems to be one of those obscure and badly documented features of Rails. What has to be done is pass an array if ids to be checked into the checked parameter
= f.collection_check_boxes :contact_ids, #contacts, :id, :fullname, checked: #selected_contact_ids
and then check boxes with items of id 1, 2 and 3 will be checked. You will need to pass this array obviously from the controller somehow. E.g.
#selected_contact_ids = email_params.fetch(:contact_ids, [])

How do i make one form for two related models?

I want to write data for 2 different models that are related to each other like this:
class Post < ActiveRecord::Base
has_many :roads
accepts_nested_attributes_for :roads, :allow_destroy => true
end
class Road < ActiveRecord::Base
belongs_to :post
end
Of course de roads table has a "post_id column". My form_for in the post view looks like this
<%= form_for #post do |f| %>
<div class="form-group">
<%= f.label :Tu_Nombre %>
<%= f.text_field :creador, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :año %> (Cuando fue tu experiencia?)
<%= f.text_field :año, class: "form-control" %>
</div>
<div class="form-group">
<%= fields_for :roads do |r| %>
<%= r.label :principio %> (desde?)
<%= r.text_field :principio, class: "form-control" %>
<%= r.label :final %> (hasta?)
<%= r.text_field :final, class: "form-control" %>
<% end %>
</div>
<div class="form-group">
<%= f.label :historia %> (Cuentanos la historia de tu viaje!)
<%= f.text_area :historia, class: "form-control", size: "50x15" %>
</div>
<div>
<%= f.submit class: "btn btn-success" %>
</div>
<% end %>
Finally my posts_controller create method
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post, notice: 'Post was successfully created.'
else
render :new
end
end
with the private
def post_params
params.require(:post).permit(:historia, roads_attributes: [:pricipio, :final, :post_id])
end
The post is submitted and if i check the console all the atributes for post has been saved but the ones for road, has not. How can i use just one form two make records for these two models and that the post_id gets registered so i can relate the tables?
Thanks a lot!!
Update your posts_controller new method to include .build
def new
#post = Post.new
#post.roads.build
end
Please read the Nested Forms in Form Helpers chapter of Rails Guide. You could use fields_for to build the nested attributes form for your roads and permit nested attributes like the example. Below is an example from rails guide, you could try and figure it out yourself.
_form.html.erb
<%= form_for #person do |f| %>
Addresses:
<ul>
<%= f.fields_for :addresses do |addresses_form| %>
<li>
<%= addresses_form.label :kind %>
<%= addresses_form.text_field :kind %>
<%= addresses_form.label :street %>
<%= addresses_form.text_field :street %>
...
</li>
<% end %>
</ul>
<% end %>
permit nested attributes in people_controller.rb
def person_params
params.require(:person).permit(:name, addresses_attributes: [:id, :kind, :street])
end
Attach your fields_for to the parent form builder like so:
<%= f.fields_for :roads do |r| %>

Nested model doesn't update

I have two models: PointPage and PointPageClass, which belongs_to :point_page. When user create PointPage rails creates several (now there're 6 of them) PointPageClasses in database. I need to edit all of them on PointPage edit page. So, I'm using nested attributes in controller and fields_for in view.
point_page_form
<%= form_for #point_page, role: 'form' do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
... # some other PointPage fields
<% #point_page.point_page_classes.each do |class| %>
<%= f.fields_for :point_page_classes do |builder| %>
<div class="row">
<div class="col-lg-6">
<%= builder.text_field :distance_price, class: 'form-control' %>
</div>
<div class="col-lg-6">
<%= builder.text_field :show_price, class: 'form-control' %>
</div>
</div>
<% end %>
<% end %>
<%= f.submit 'Save', class: 'btn btn-default' %>
<% end %>
point_page_controller
def update
#point_page = PointPage.find(params[:id])
if #point_page.update_attributes(point_page_params)
respond_to do |format|
format.html { redirect_to new_point_path }
format.js
end
end
end
private
def point_page_params
params.require(:point_page).permit(:name, :url, :article,
point_page_classes_attributes: [:distance_price, :show_price])
end
So, I've added in point_page_controller PointPageClass attributes, but when I save the changes, it only saves changes for PointPage, but not for PointPageClass (distance_price and show_price).
Thanks for any help!
One of the problem could be not permitting the :id in the point_page_params.For the update to take place you need to permit the :id.
Try changing your point_page_params to like this
def point_page_params
params.require(:point_page).permit(:id,:name, :url, :article,point_page_classes_attributes: [:id,:distance_price, :show_price])
end

Ruby Rails submit two forms in one click

I have these forms:
<%= form_for(#user) do |f| %>
<div>
<%= f.number_field :money, :value => #user.money %>
</div>
<% end %>
and
<%= form_for #product, :url => product_path, :html => { :multipart => true } do |f| %>
<div>
<%= f.label :count, 'How Many product?' %><br />
<%= f.number_field :count, :value => "1" %>
</div>
<div>
<%= f.submit('submit') %>
</div>
<% end %>
is there any way to submit this two at once when clicking submit button ? Thanks!
A service object might be a good way to approach this.
class Order
include ActiveModel::Model
attr_accessor :money, :count
def initialize(user=nil, product=nil)
#user = user
#product = product
#money = user.money
#count = 1
end
def persisted?
false
end
def save
// this code needs to save to db
end
end

How create new instance of a model in relation many to many?

I try to create a furniture object, which is in relation by a has_many_and_belongs_to with stores, this is my model:
class Furniture < ActiveRecord::Base
attr_accessible :area, :description, :name, :size
has_and_belongs_to_many :stores
end
My problem is that I don't know how create a new furniture, because i try to associate furniture with one or more store with check box, but I obtain this error: undefined method merge for #<Store:0x007ff16ae27e40>.
These are my view with form and my controller with new and create action:
View:
<%= form_for #furniture do |f| %>
<%= f.label :name %>
<%= f.text_field :name %> <br><br>
<%= f.label :description %>
<%= f.text_field :description %> <br><br>
<%= f.label :size %>
<%= f.text_field :size %> <br><br>
<% #store.each do |store| %>
<div>
<%= f.check_box :stores, store %>
<%= store.name %>
</div>
<% end %>
<%= f.submit %>
<% end %>
Controller:
def new
#furniture = Furniture.new
#store = Store.order('name ASC')
end
def create
#furniture = Furniture.create(params[:furniture])
redirect_to admins_path
end
How can I solve it?? Have you some suggestion to create a new object with this relation ship??
Thank you very much
EDIT:
I have a join table between furniture and store
The has_and_belongs_to association adds a method collection_singular_ids= that for the current case will be #furniture.store_ids=. According to the docs
The collection_singular_ids= method makes the collection contain only the objects identified by the supplied primary key values, by adding and deleting as appropriate.
So, you can use this idea to add the stores to your furniture. Replace
<% #store.each do |store| %>
<div>
<%= f.check_box :stores, store %>
<%= store.name %>
</div>
<% end %>
with
<% #store.each do |store| %>
<div>
<%= f.check_box :store_ids, {:multiple => true}, store.id, nil %>
<%= store.name %>
</div>
<% end %>

Resources