how to add details in two database table in one submit - ruby-on-rails

I have 3 tables: coaches, categories and also a join table categories_coaches, on submit I want to store category_id and coach_id in join table categories_coaches and name, email, university, batch, phone in coach table. how to do so?
now details are storing in coach table but not storing in join table
please help me to solve this problem.
coach.rb
class Coach < ActiveRecord::Base
has_and_belongs_to_many :categories
end
category.rb
class Category < ActiveRecord::Base
belongs_to :coach
end
registrationcontroller.erb
class Coaches::RegistrationsController < Devise::RegistrationsController
def new
#individual=#individual ||= Coach.new
super
end
def create
build_resource sign_up_params
#individual=#individual ||= Coach.new
super
end
private
def sign_up_params
params.require(:coach).permit(:name, :email, :university, :batch, :linkedin_url, :code, :phone,category_ids: []
)
end
end
view page
<%= simple_form_for(#individual, as: :coach, url: registration_path(:coach)) do |f| %>
<%= f.input :name, required: true, %>
<%= f.input :university %>
<%= f.input :batch %>
<%= f.input :email%>
<%= f.input :phone%>
<div class="category-scroll">
<% Category.all.each do |c| %>
<% if c.parent_id != nil %>
<div class="category-left">
<%= check_box_tag "category_ids[]", c.id, false, :id => "category_ids_#{c.id}" %>
<%= c.name %>
</div>
<% else %>
<b><%= c.name %></b>
<% end %>
<% end %>
</div>
<div class="form-group">
<%= f.button :submit, "SUBMIT", class: "apply-continue_form" %
<% end %>

What you've mentioned sounds like a has_and_belongs_to_many relationship to me.
I'll detail what you should do, and the underlying mechanics of the association:
#app/models/coach.rb
class Coach < ActiveRecord::Base
has_and_belongs_to_many :categories
end
#app/models/category.rb
class Category < ActiveRecord::Base
has_and_belongs_to_many :coaches
end
This, as opposed to the has_many :through relationship, does most of the legwork for you. You were correct in setting up your join_table as you did:
The importance of getting this right is that each time you CRUD either your Coach or Category objects, you'll have access to their associated data through the :categories and :coaches methods respectively.
Thus, you'll be able to populate the data like this:
#config/routes.rb
resources :coaches #-> url.com/coaches/new
#app/controllers/coaches_controller.rb
class CoachesController < ApplicationController
def index
#coaches = Coach.all
end
def new
#coach = Coach.new
end
def create
#coach = Coach.new coach_params
end
private
def coach_params
params.require(:coach).permit(:name, :email, :university, :batch, :phone, :categories)
end
end
This will then allow you to make the following view:
#app/views/coaches/new.html.erb
<%= form_for #coach do |f| %>
<%= f.text_field :name %>
<%= f.email_field :email %>
<%= f.text_field :university %>
<%= f.text_field :batch %>
<%= f.text_field :phone %>
<%= f.collection_select :categories, Category.all, :id, :name %>
<%= f.submit %>
<% end %>

Related

Edit and Update for assosiated model Rails

I tried to create edit and update action for my assosiated model named as Entity.
But When edit pages pop up no saved data shown. Means it is showing all field as empty and when I put values in it, creates a another object.
And also validation messages are not showing
Entities Controller
class EntitiesController < ApplicationController
def edit
#schema = Schema.find(params[:schema_id])
#entity = #schema.entities.find(params[:id])
end
def update
#schema = Schema.find(params[:schema_id])
#entity = #schema.entities.find(params[:id])
if #entity.update(entity_params)
redirect_to schema_entities_path(#schema)
else
render 'edit'
end
end
private
def entity_params
params.require(:entity).permit(:clientId, :name, :description, :mnemonic)
end
end
edit form for it:
<%= form_for([#schema, #schema.entities.build], data: { turbo: false }) do |f| %>
<%= f.text_field :clientId, placeholder:"ClientId" %>
<%= f.text_area :name, placeholder: "Name" %>
<%= f.text_area :description, placeholder: "Description" %>
<%= f.text_area :mnemonic, placeholder: "Mnemonic" %>
<%= f.submit 'Submit' %>
<% if #entity.errors.any? %>
<div id="error_explanation">
<% #entity.errors.full_messages.each do |msg| %>
<p class="error_msg"><%= msg %></p>
<% end %>
</div>
<% end %>
<% end %>
Its model:
class Entity < ApplicationRecord
belongs_to :schema
has_many :fields, dependent: :destroy
has_many :joins, through: :fields
validates :name, presence: true, uniqueness: true
def self.search(search)
where("name LIKE ?", "%#{search}%")
end
end
This is how I am passing values from index page:
<%= link_to 'Edit', edit_schema_entity_path(schema_id: #schema.id, id: data.id) if data.id %>

Create multiple new records from checkboxes in form using nested attributes in Rails

I'm trying to come up with a contact form that creates a contact record and potentially multiple location records, if multiple locations are checked in a list of checkboxes. I thought of having all location records created and then destroyed, if they aren't checked. I don't think that's optimal though.
I'm using many to many relationships in the models.
This is what they look like at the moment:
contact.rb
class Contact < ApplicationRecord
has_many :contact_locations, dependent: :destroy
has_many :locations, through: :contact_locations
accepts_nested_attributes_for :contact_locations, allow_destroy: true, reject_if: :empty_location?
private
def empty_location?(att)
att['location_id'].blank?
end
end
location.rb
class Location < ApplicationRecord
has_many :locations, dependent: :destroy
has_many :contacts, :through => :contact_locations
has_many :contact_locations
end
contact_location.rb
class ContactLocation < ApplicationRecord
belongs_to :location
belongs_to :contact
end
contacts_controller.rb
def new
#contact = Contact.new
#locations = Location.all
4.times {#contact.contact_locations.new}
end
private
def contact_params
params.require(:contact).permit(:name, :phone, ..., contact_locations_attributes: [:location_ids])
end
new.html.rb
<%= form_with model: #contact do |f| %>
...
<%= #locations.each do |location| %>
<%= f.fields_for :contact_locations do |l| %>
<%= l.check_box :location_id, {}, location.id, nil %><%= l.label location.name %>
<% end %>
<% end %>
...
<% end %>
Does anyone how to make it work properly?
I'm working on Ruby 2.5.1 and Rails 5.2.1.
Thanks a lot.
I think your solution is the form objects pattern.
You can have something like this:
<%= form_for #user do |f| %>
<%= f.email_field :email %>
<%= f.fields_for #user.build_location do |g| %>
<%= g.text_field :country %>
<% end %>
<% end%>
And convert it in something more readable that permits you to instance the locations inside the registration object, checking the value of the checkboxes.
<%= form_for #registration do |f| %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.input :password %>
<%= f.text_field :password %>
<%= f.input :country %>
<%= f.text_field :country %>
<%= f.input :city %>
<%= f.text_field :city %>
<%= f.button :submit, 'Create account' %>
<% end %>
Here you will find how to apply the pattern: https://revs.runtime-revolution.com/saving-multiple-models-with-form-objects-and-transactions-2c26f37f7b9a
I ended up making it work with Kirti's suggestion on the following question:
Rails Nested attributes with check_box loop
It turns out I needed to make a small adjustment in my form's fields_for tag.
Thanks a lot the help!

Nested forms: How to correctly access a certain instance with fields_for

I have an Order, which always has exactly two addresses: A invoice address and a shipping address. In the view, I have a form, where you can enter both addresses. From my controller I pass on the instance #order, with two sub instances of addresses already built.
Extract from my OrdersConntroller:
def new
#order = Order.new(orderCreationDate: Time.now)
2.times{ #order.addresses.build }
end
In the view, how can I access just the first #order.addresses, and then in some other place the second #order.addresses?
What I've tried so far:
<%= form_for #order do |f| %>
...
<%= f.fields_for :addresses do |ff| %>
<%= ff.text_field :firstName %>
...
<% end %>
<% end %>
But then the HTML result is the following (where the name and id is not right).
<input type="text" name="order[a][firstName]" id="order_a_firstName">
Extract from my Order model:
has_many :addresses, foreign_key: "orderID"
accepts_nested_attributes_for :addresses, allow_destroy: true
Thx for the support.
You need to create two model 1) InvoiceAddress and 2) ShippingAddress
class InvoiceAddress < ActiveRecord::Base
self.table_name = :address
end
class ShippingAddress < ActiveRecord::Base
self.table_name = :address
end
and in order model use association as follows
has_one :invoice_address
has_one :shipping_address
and orders_controller.rb
def new
#order = Order.new(orderCreationDate: Time.now)
#invoice_address = #order.build_invoice_address
#shipping_address = #order.build_shipping_address
end
form will be
<%= form_for #order do |f| %>
...
<%= f.fields_for :invoice_address, #invoice_address do |ff| %>
<%= ff.text_field :firstName %>
...
<% end %>
<%= f.fields_for :shipping_address, #shipping_address do |ff| %>
<%= ff.text_field :firstName %>
...
<% end %>
<% end %>

Rails 4.0 nested object forms not rendered

I have two models in my app: "WorkPost" and "Contacts".
WorkPost
class WorkPost < ActiveRecord::Base
has_one :contacts
end
Contacts
class Contacts < ActiveRecord::Base
belongs_to :work_post
end
In my controller's new method I do:
def new
#work_post = WorkPost.new
#work_post.contacts
end
And in view I create form:
<%= form_for(#work_post) do |f| %>
<div class="field">
<%= f.label 'Vacation' %><br>
<%= f.text_field :post_title, :placeholder => 'Vacation here' %>
</div>
<div class="field">
<%= f.label 'Vacation description' %><br>
<%= f.text_area :post_body, :placeholder => 'Vacation description here' %>
</div>
<% f.fields_for :contacts do |cf| %>
<div class="field">
<%= cf.label 'Email' %><br>
<%= cf.text_field :emails, :placeholder => 'Email here' %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Post vacation", :class => 'btn_act' %>
</div>
<% end %>
But it seems like line <% f.fields_for :contacts do |cf| %> doesn't work.
Everything is rendered fine but email field.What I am doing wrong?
The problem is with this line
<% f.fields_for :contacts do |cf| %>
which should be
<%= f.fields_for :contact do |cf| %>
Also, the class name for the model and the association name for has_one/belongs_to should be singular.
#work_post.rb
class WorkPost < ActiveRecord::Base
has_one :contact #should be singular
end
#contact.rb
class Contact < ActiveRecord::Base #should be singular
belongs_to :work_post
end
Also, notice the change :contacts to :contact, as it is a has_one association.
Update:
Also, try the below changes
Include accepts_nested_attributes_for :contact in work_post.rb model
#work_post.rb
class WorkPost < ActiveRecord::Base
has_one :contact
accepts_nested_attributes_for :contact
end
Change the new method to below
def new
#work_post = WorkPost.new
#work_post.build_contact
end

nested forms : update child foreign key

I have a nested association:
class User < ActiveRecord::Base
has_many :hostels
accepts_nested_attributes_for :hostels
end
class Hostel < ActiveRecord::Base
belongs_to :user
end
The form :
<%= form_for #user do |f| %>
<%= f.label :email %><br>
<%= f.text_field :email %>
<% f.object.hostels << #hostel -%>
<%= f.fields_for :hostels do |ff| %>
<%= ff.hidden_field :id %>
<% end -%>
<%= f.submit %>
<% end -%>
the controller
def create
#user = User.new(user_params)
raise #user.hostels.inspect
end
private
def user_params
params.require(:user).permit(:email, hostels_attributes: [:id])
end
I would like to relink existing records of hostels to new users by updating hostel foreign key. This way, it definitly don't work.
Tried update_only: true parameter to nested too.
Any ideas about the subject or am I totally wrong about trying to do the operation like that ?
you can use a multiple select for hotels in you form, then in the controller you must require hostel_ids.
Models:
class User < ActiveRecord::Base
has_many :hostels
end
class Hostel < ActiveRecord::Base
belongs_to :user
end
Form: where :name is what you see in your multiple select
<%= form_for #user do |f| %>
<%= f.label :email %><br>
<%= f.text_field :email %>
<%= f.label "Hostels" %><br>
<%= select_tag :hotel_ids, options_for_select(Hostel.all.map{|h| [h.name, h.id]}), { :multiple => true } %>
<%= f.submit %>
<% end %>
Controller:
def create
#user = User.new(user_params)
end
private
def user_params
params.require(:user).permit(:email, hostel_ids)
end
I did not test the code but must work well.

Resources