Rails - Incorrect database entries in Postgresql - ruby-on-rails

I am trying to create a form to handle the creation of addresses. I have three models, AddressInfo, Address, and Client. AddressInfo will store the type of address such as present, mailing or employer and link to a ClientID and an AddressID. This is used to prevent duplicate addresses in case someone uses their employer address as a mailing address. The problem I am having at the moment is that I can't seem to get the AddressID to link to the AddressInfo row.
This is my rails console attempt and the desired behavior:
This is my output: Ignore the entries in address at the moment since those are just seed files. Addressinfo(3) is the entry I tried to add through the interface and it doesn't create a new address.
Here is my view:
<%= form_for(#client) do |f| %>
<%= f.fields_for :address_infos do |presinfo_form|%>
<%= presinfo_form.fields_for :addresses do |address_form| %>
<%= address_form.label :"Present Address" %>
<%= address_form.text_field :street %>
end
<%= presinfo_form.label :"Type" %>
<%= presinfo_form.text_field :addresstype, :value => "present" %>
end
end
And the models:
class AddressInfo < ActiveRecord::Base
belongs_to :client
belongs_to :address
accepts_nested_attributes_for :address
end
class Address < ActiveRecord::Base
has_many :address_infos
has_many :clients, through: :address_infos
end
class Client < ActiveRecord::Base
has_many :address_infos
has_many :addresses, through :address_infos
accepts_nested_attributes_for :addresses, :address_infos, reject_if: :all_blank, allow_destroy: true
end
Client controller:
class ClientsController < ApplicationController
def new
#client = Client.new
#client.address_infos.build
#client.addresses.build
end
def create
#client = Client.new(client_params)
if #client.save
redirect_to root_url
else
render 'new'
end
end
private
def client_params
params.require(:client).permit(:firstname, :middlename, :lastname,
address_infos_attributes: [:ownorrent, :addresstype, :yearsofresidency,
addresses_attributes: [:street, :city, :state, :zipcode]]
)
end
end

Related

Validate presence of fields from another model

With the following associations:
class Profile < ActiveRecord::Base
belongs_to :visitor
belongs_to :contact_point
validates :contact_point, presence: true
end
class Visitor < User
has_one :profile, dependent: :destroy
has_one :contact_point, through: :profile
end
class ContactPoint < User
has_many :profiles
has_many :visitors, through: :profiles
end
Each ContactPoint has a email. When the visitor creates her profile using the following form, she needs to determine the profiles contact point using the email address belonging to ContactPoint. The contact point users are already created and the visitors should not be able to update ContactPoint model.
<%= form_for #profile do |f| %>
<%= f.label 'First Name' %>
<%= f.text_field :first_name %>
<%= f.label 'Last Name' %>
<%= f.text_field :last_name %>
<%= fields_for :contact_point, #profile.contact_point do |ff| %>
<%= ff.label 'Contact point email' %>
<%= ff.text_field :email %>
<% end %>
<% end %>
In ProfilesController I am passing parameters to profile model this way:
def create
#profile = Profile.create(profile_params)
end
def profile_params
contact_point = ContactPoint.find_by_email(params[:contact_point][:email])
params.require(:profile).permit(:first_name, :last_name)
.merge(visitor_id: current_user.id, contact_point: contact_point)
end
With the above setup, when there is no ContactPoint with the provided email address, the contact_point variable will set to be nil and the validator can't distinguish whether the contact point email in the filled in from was empty or not.
Now, how can I add a validation to check the presence of this email address in contact_points table and show a custom error message?
You would have to do it yourself in your controller, something like:
def create
#profile = Profile.create(profile_params)
if !#profile.contact_point
if params[:contact_point][:email].present?
#profile.errors.add(:contact_point, 'No contact with found')
else
#profile.errors.add(:contact_point, 'Please provide an email')
end
render :new
end
end
The best would be to use a custom validation that checks if contact_pounts.email is blank? If yes, then return false.
EDIT:
My brain is functioning better now after some sleep. You can do this using rails. This is how I would do it.
class Profile < ActiveRecord::Base
belongs_to :visitor
belongs_to :contact_point
validates :contact_point, presence: true
accepts_nested_attributes_for :contact_point
end
class Visitor < User
has_one :profile, dependent: :destroy
has_one :contact_point, through: :profile
end
class ContactPoint < User
has_many :profiles
has_many :visitors, through: :profiles
validates :email, presence: true
end
What is going on here? We accept nested attributes for the association (ContactPoint) from Profile, so we can pass them through the #profile form you have to the controller. The models will handle the validation and set the error messages accordingly.
Does this makes sense?

can't write unknown attribute `company_profile_id`

I'm trying to add a set of users to a company_profile object. The idea is a user will create a company and then add more users to the company in various roles.
The company profile has an address object, and when I pull up the form on the new call I get this error:
"can't write unknown attribute company_profile_id"
company_profile -> new
<%= form_for(setup_companyProfile(#companyProfile), validate: true, html: { multipart: true }) do |f| %>
<%= f.fields_for :address do |address| %>
<%= render :partial => 'shared/address', :locals => {:f => address} %>
<% end %>
<% end %>
user.rb
belongs_to :company_profile
helper.rb
def setup_companyProfile(companyProfile)
if(companyProfile.address.present? == false)
companyProfile.address ||= Address.new
end
companyProfile
end
company_profile.rb
class CompanyProfile < ApplicationRecord
has_many :users
has_one :address
accepts_nested_attributes_for :address
end
company_profile_controller.rb
class CompanyProfileController < ApplicationController
def new
#companyProfile = CompanyProfile.new
end
def edit
#companyProfile = CompanyProfile.find(current_user.company_profile_id)
end
def update
end
def show
end
end
When you use has_one from the company-profile model... Rails expects there to be a belongs_to :company_profile on the Address model... and this belongs_to requires a column called company_profile_id on the addresses table... do you have that? If not - you will need to create a migration that adds it.

Rails nested fields creation in loop

I have three model classes related to each other.
class Student < ActiveRecord::Base
has_many :marks
belongs_to :group
accepts_nested_attributes_for :marks,
reject_if: proc { |attributes| attributes['rate'].blank?},
allow_destroy: true
end
This class describes a student that has many marks and I want to create a Student record along with his marks.
class Mark < ActiveRecord::Base
belongs_to :student, dependent: :destroy
belongs_to :subject
end
Marks are related both to the Subject and a Student.
class Subject < ActiveRecord::Base
belongs_to :group
has_many :marks
end
When I try to create the nested fields of marks in loop labeling them with subject names and passing into in it's subject_id via a loop a problem comes up - only the last nested field of marks is saved correctly, whilst other fields are ignored. Here's my form view code:
<%= form_for([#group, #student]) do |f| %>
<%= f.text_field :student_name %>
<%=f.label 'Student`s name'%><br>
<%= f.text_field :student_surname %>
<%=f.label 'Student`s surname'%><br>
<%=f.check_box :is_payer%>
<%=f.label 'Payer'%>
<%= f.fields_for :marks, #student.marks do |ff|%>
<%#group.subjects.each do |subject| %><br>
<%=ff.label subject.subject_full_name%><br>
<%=ff.text_field :rate %>
<%=ff.hidden_field :subject_id, :value => subject.id%><br>
<%end%>
<% end %>
<%= f.submit 'Add student'%>
<% end %>
Here`s my controller code:
class StudentsController<ApplicationController
before_action :authenticate_admin!
def new
#student = Student.new
#student.marks.build
#group = Group.find(params[:group_id])
#group.student_sort
end
def create
#group = Group.find(params[:group_id])
#student = #group.students.new(student_params)
if #student.save
redirect_to new_group_student_path
flash[:notice] = 'Студента успішно додано!'
else
redirect_to new_group_student_path
flash[:alert] = 'При створенні були деякі помилки!'
end
end
private
def student_params
params.require(:student).permit(:student_name, :student_surname, :is_payer, marks_attributes: [:id, :rate, :subject_id, :_destroy])
end
end
How can I fix it?
#student.marks.build
This line will reserve an object Mark.
If you want multi marks, May be you need something like this in new action :
#group.subjects.each do |subject|
#student.marks.build(:subject=> subject)
end
Hope useful for you.

Rails form multiple checkboxes for associated model

I'm creating an application where a "submission" can be made using a form which creates client details and allows "referrals" to be created depending on the branch(es) that can provide the required service
class Submission < ActiveRecord::Base
has_many :referrals, :inverse_of => :submission, dependent: :delete_all
accepts_nested_attributes_for :referrals, :allow_destroy => true
end
class Referral < ActiveRecord::Base
belongs_to :submission
end
class Branch < ActiveRecord::Base
has_many :referrals
end
Submissions controller:
def new
#submission = Submission.new
#submission.build_client
#submission.client.build_address
#submission.referrals.build
end
def submission_params
params.require(:submission).permit(:consent, :user_id, client_attributes:
[:client_id, :first_name,
address_attributes:
[:first_line, :second_line,]
],
referrals_attributes:
[:branch_id]
)
end
The Submission form:
<%= form_for(#submission) do |f| %>
<%= f.fields_for :referrals do |referral| %>
<%= render 'referral_fields', f: referral %>
<% end %>
<% end %>
_referral_fields.html.erb:
<% Branch.all.where(referrable: true).each do |branch| %>
<label>
<%= check_box_tag 'branch_ids[]', branch.id %>
<%= branch.name %>
</label>
<% end %>
What I want is to have checkboxes for each referrable branch. When a branch is ticked and the submission is created, a referral will be created for that branch. However, when I submit the form, I get a validation error of "Referrals can't be blank". Any idea why this is not working?
Any help is most appreciated
Use collection_check_boxes.
<% # _referral_fields.html.erb %>
<%= f.collection_check_boxes(:branch_ids, Branch.where(referrable: true), :id, :name) do |b|
b.label { b.check_box } # wraps check box in label
end %>
You would need to whitelist submission[referrals_attributes][branch_ids] - not branch_id.
def submission_params
params.require(:submission)
.permit(
:consent,
:user_id,
client_attributes: [
:client_id,
:first_name,
address_attributes: [
:first_line, :second_line,
]
],
referrals_attributes: [:branch_ids]
)
end
Edited.
However for this to work you need to setup a relation between Referral and Branch. In this case you could use either a has_and_belongs_to_many (HABTM) or has_many though: (HMT) relationship.
See Choosing Between has_many :through and has_and_belongs_to_many.
class Referral < ActiveRecord::Base
belongs_to :submission
has_and_belongs_to_many :branches
end
class Branch < ActiveRecord::Base
has_and_belongs_to_many :referrals
end
You need to create a join table as well:
rails g migration CreateBranchReferralJoinTable branch referral

Nested Forms Rails 4.0 Strong Parameters

Been trying this all night and I can't get the photo upload to work. The 2 tables work just fine but no dice on a polymorphic table that holds photos. Any fresh new eyes would be such great help.
def restaurant_params
params.require(:restaurant).permit(:res_name, :res_description, restaurant_branches_attributes: [ :id, :address_line1, :address_line2, :address_line3, :address_line4, :address_line5, :address_line6, :number_phone, :number_fax, :email, :_destroy ], pictures_attributes: [ :id, :name, :image] )
end
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
mount_uploader :image, ImageUploader
end
class Restaurant < ActiveRecord::Base
has_many :restaurant_branches
accepts_nested_attributes_for :restaurant_branches, allow_destroy: true
end
class RestaurantBranch < ActiveRecord::Base
belongs_to :restaurants
has_many :pictures, as: :imageable
accepts_nested_attributes_for :pictures, allow_destroy: true
before_save :set_address
def set_contact_info
contact_info = "Phone: #{self[:number_phone]} Fax: #{self[:number_fax]} Email: #{self[:email]}"
end
def set_address
address = self.address_line2.nil? ? partial_address.titleize : complete_address.titleize
end
private
def complete_address
address = "#{self[:address_line1]} #{self[:address_line2]} #{self[:address_line3]} #{self[:address_line4]} #{self[:address_line5]} #{self[:address_line6]}"
end
def partial_address
address = "#{self[:address_line1]} #{self[:address_line3]} #{self[:address_line4]} #{self[:address_line5]} #{self[:address_line6]}"
end
end
Multi-Level Association
The polymorphic nature of the associations shouldn't be a problem, as Rails will typically send the data to the association - in this case pictures
I think your problem is more to do with the multi-level association you have, specifically that you need to pass the attributes as follows [form submit] > RestaurantBranch > Pictures
--
We've done this before, and here's how you do it:
#app/controllers/restaurants_controller.rb
Class RestaurantsController < ApplicationController
def new
#restaurant = Resaurant.new
#restaurant.restaurant_branches.build.pictures.build #-> notice multi-level nesting
end
def create
#restaurant = Restaurant.new(restaurant_params)
#restaurant.save
end
private
def restaurant_params
params.require(:restaurant).permit(:res_name, :res_description, restaurant_branches_attributes: [ :id, :address_line1, :address_line2, :address_line3, :address_line4, :address_line5, :address_line6, :number_phone, :number_fax, :email, :_destroy, pictures_attributes: [ :id, :name, :image]])
end
end
#app/views/restaurants/new.html.erb
<%= form_for #restaurant do |f| %>
<%= f.fields_for :restaurant_branches do |rb| %>
<%= rb.fields_for :pictures do |p| %>
<%= p.file_field :image %>
<% end %>
<% end %>
<% end %>

Resources