Find_or_initializes_by for a complex model - ruby-on-rails-5

Newbie Rails user here so sorry if I'm totally overlooking something; I'm just looking for direction on what resources I should use to solve this problem.
I have a Rails app running that uses virtual attributes to define a complicated has_many :through relationship. What I'm looking to do is to use the id of an existing entry rather than creating a new one when a user submits a form. I have attempted to use find_or_initializes_by and find_or_create to no avail. Depending on how I set it up, it either changes one of the diagnosis columns on the join table successfully (but leaves the other diagnosis column blank, causing a rollback), or it doesn't work at all.
Background for my use case: a Case can have many diagnoses (Diagnosis), some of which are primary, and others are "differential" diagnoses. Cases and multiple diagnoses are related in a join table.
My current setup:
case.rb
def new
#case = Case.new
#case_and_diagnoses = #case.case_and_diagnoses.build
#primary_diagnoses = #case_and_diagnoses.build_primary_diagnosis
#differential_diagnoses = #case_and_diagnoses.build_differential_diagnosis
end
The relevant section of the case form:
<%= f.fields_for :case_and_diagnoses do |x| %>
<%= x.fields_for :primary_diagnosis do |diagnosis| %>
<%= diagnosis.label :name, "Diagnosis" %>
<%= diagnosis.text_field :name %>
<% end %>
<%= x.fields_for :differential_diagnosis do |differential| %>
<%= differential.label :name, 'Differential diagnosis' %>
<%= differential.text_field :name %>
<% end %>
<% end %>
What's the best way to tackle this problem? I don't need an explicit code block to use, but I'm looking for a strategy so I can maybe find my own way. Thank you very much!
Update:
The models:
class Case < ApplicationRecord
before_save :get_diagnoses
belongs_to :submitter, class_name: 'User', foreign_key: 'submitter_id'
belongs_to :resident, class_name: 'User', foreign_key: 'resident_id'
belongs_to :faculty, class_name: 'User', foreign_key: 'faculty_id'
has_one :service
has_many :case_and_diagnoses
has_many :primary_diagnoses, through: :case_and_diagnoses
has_many :differential_diagnoses, through: :case_and_diagnoses
accepts_nested_attributes_for :case_and_diagnoses
end
class Diagnosis < ApplicationRecord
has_many :case_and_diagnoses
has_many :cases, through: :case_and_diagnoses
end
class CaseAndDiagnosis < ApplicationRecord
belongs_to :case
belongs_to :primary_diagnosis, class_name: 'Diagnosis', foreign_key: :primary_diagnosis_id, optional: true
belongs_to :differential_diagnosis, class_name: 'Diagnosis', foreign_key: :differential_diagnosis_id, optional: true
accepts_nested_attributes_for :primary_diagnosis, :differential_diagnosis
end

Related

Grouping posts by user in has_many through relation collection with Rails 5

I'm trying to display Users (devise) in a collection (has_many through).
<%= #collection.posts.count %> designs by
<% #collection.posts.each do |post| %>
<%= link_to image_tag(post.designer.avatar.url.to_s, class: "avatar-small"), post.designer %>
<% end %>
but it displaying duplicates as in
I need to group by designer.id. So I added #collection_designers line but I could not manage to group by designer id.🤷‍♂️
class CollectionsController < ApplicationController
def show
#collection = Collection.find(params[:id])
#I need to group for designer.id I guess but I could not manage it
#collection_designers = Collection.find(params[:id]).groups(designers.id)
end
...
Relations:
models/collection.rb
class Collection < ApplicationRecord
belongs_to :designer
has_many :collectivizations
has_many :posts, through: :collectivizations
end
models/collectivization.rb
class Collectivization < ApplicationRecord
belongs_to :post
belongs_to :collection
end
models/post.rb
class Post < ApplicationRecord
belongs_to :category
belongs_to :designer
has_many :collectivizations
has_many :collections, through: :collectivizations
You need to find uniq designers ids at first
designer_ids = #collection.posts.distinct.pluck(:designer_id)
And after it find designers by these ids
#designers = Designer.where(id: designer_ids)

How to use "accepts_nested_attributes_for" in rails 3?

I'm following the docs and toying with simple_form, formtastic, and nested_form gems with no success. This very simple example yields empty for for me:
resort.rb
class Resort < ActiveRecord::Base
attr_accessible :address, :description, :latitude, :longitude, :name, :phone, :second_name,
:resort_type_id, :infrastructure_attributes
validates_presence_of :name, :address, :phone, :description
has_many :infrastructures
belongs_to :resort_type
accepts_nested_attributes_for :infrastructures
end
infrastructure.rb
class Infrastructure < ActiveRecord::Base
attr_accessible :name, :description, :infrastructure_type_id, :resort_id
belongs_to :resort
belongs_to :infrastructure_type
end
form view
= form_for #resort do |f|
= f.fields_for :infrastructures do |i|
= i.text_field :name
Seems I missed something obvious but can't figure out what exactly is wrong with the code.
If I may ask, in your controller action did you build the appropriate code for your infrastructure. Something like
3.times { #resort = #resort.infrastrucures.build }
To my knowledge you need something like this for your form before it can build the proper nested form content

Form not displayed correctly

i have a form consists of the following models
Employee.rb
class Employee < ActiveRecord::Base
attr_accessible :employee_number, :joining_date, :first_name, :middle_name, :last_name,
:gender, :job_title, :employee_department_id, :qualification, :experience_detail,
:experience_year, :experience_month, :status_description, :date_of_birth, :marital_status,
:children_count, :father_name, :mother_name, :husband_name, :blood_group, :nationality_id,
:home_address_line1, :home_address_line2, :home_city, :home_state, :home_pin_code,
:office_address_line1, :office_address_line2, :office_city, :office_state, :office_pin_code,
:office_phone1, :office_phone2, :mobile_phone, :home_phone, :email, :fax, :user_id,
:reporting_manager_id, :employee_grade_id, :office_country_id,
:home_country_id, :employee_category, :employee_position_id
belongs_to :employee_department
has_many :counselor_supervisors
belongs_to :employee_position
def to_label
full_name = first_name + " " + last_name
end
end
EmployeeDepartment.rb
class EmployeeDepartment < ActiveRecord::Base
attr_accessible :code, :name
has_many :employees
has_many :employee_positions
has_many :counselor_supervisors
has_many :batch_leadership_supervisors
def to_label
name
end
end
CounselorSupervisor.rb
class CounselorSupervisor < ActiveRecord::Base
attr_accessible :employee_id, :employee_department_id, :employee_position_id
belongs_to :employee
belongs_to :employee_department
has_many :batch_counselor_supervisors
def to_label
employee.to_label
end
end
BatchCounselorSupervisor.rb
class BatchCounselorSupervisor < ActiveRecord::Base
attr_accessible :counselor_supervisor_id , :employee_department_id , :counselor_batch_id,
:batch_counselor_advisors_attributes
has_many :batch_counselor_advisors
belongs_to :counselor_supervisor
belongs_to :employee_department
belongs_to :counselor_batch
accepts_nested_attributes_for :batch_counselor_advisors
end
Employee_position.rb
class EmployeePosition < ActiveRecord::Base
attr_accessible :position_title, :employee_department_id
has_many :employees
belongs_to :employee_department
def to_label
position_title
end
end
batch_counselor_supervisors/new.html.erb (part of the form which related to my question)
<%= simple_form_for(#batch_counselor_supervisor) do |f| %>
<%= f.error_messages %>
<%= f.association :employee_department, as: :select %>
<%= f.input :counselor_supervisor_id , collection: EmployeeDepartment.all, as: :grouped_select, group_method: :counselor_supervisors %>
<% end %>
the dropdown list appears like this:
If I added an employee which belongs to the first department "Business Administration", the form will be displayed correctly like this:
Update: after adding label_method: :to_label, so my form became like this :
<%= simple_form_for(#batch_counselor_supervisor) do |f| %>
<%= f.error_messages %>
<%= f.association :employee_department, as: :select %>
<%= f.input :counselor_supervisor_id ,
collection: EmployeeDepartment.all, as: :grouped_select, group_method: :counselor_supervisors, label_method: :to_label %>
<% end %>
the employee name displayed correctly but still the department name not displayed correctly as the following image:
Is this SQLite3 issue ? and What can I do in order to solve this if it sqlite3 issue or not.
From what I see, you only have an issue with the labels not being displayed correctly. Could you try to explicitly set the method on your input:
label_method: :to_label
For more information have a look at https://github.com/plataformatec/simple_form and search for *label_method*
What are the actual relevant rows in your Employee table and your EmployeePosition table?
In your Employee table you happen to have these 2 columns;
employee_position_id
employee_position.
Since employee_position is also a table name, it's bad/reduntant model structure which might be confusing your include method of the query. It's possible that in your tables, the rows are fully filled out to complete the first query, but not for any of your other queries even though you think it is.

rails3 view has_many :through attribute

Three models linked via has_many :through
class Bozza < ActiveRecord::Base
has_many :accessoryvolumes, :dependent => :destroy
has_many :accessories, through: :accessoryvolumes
belongs_to :lavorazione
class Accessory < ActiveRecord::Base
has_many :accessoryvolumes
has_many :bozzas, through: :accessoryvolumes
class Accessoryvolume < ActiveRecord::Base
belongs_to :accessory
belongs_to :bozza
In the view for bozza, the attributes for bozza are accessible
<% #bozza.accessoryvolumes.each do |accessoryvolume| %>
<%= accessoryvolume.numero %>
<%= accessoryvolume.bozza_id %>
<%= accessoryvolume.bozza.lavorazione.name %>
<%= accessoryvolume.accessory_id %>
<%= accessoryvolume.accessory.name %>
save for the last item. Any attribute for the relationship to accessory generates and
undefined method `name' for nil:NilClass
evan though accessory_id has a value. How is the related attribute in one instance being picked up and not the other?
The issue is with the plural handling of "accessory". it was a nasty suspicion for many hours....
This issue arises rather frequently. Pony up and come up with a name that cannot be interpreted mistakenly by rails or someone, somehow, somewhere. Avoid nouns that pluralize irregularly. Moreso when dealing with foreign languages.
Now
class Accessorio < ActiveRecord::Base
has_and_belongs_to_many :lavoraziones
has_many :accessoryvolumes
has_many :bozzas, through: :accessoryvolumes
and
<%= accessoryvolume.accessorio.nome %>
runs as expected

Nested form not saving the data

I have 3 models. Firstly I have a voter which has many votes. Votes is a join table to link the voter and the entry. But when I try to save the votes they are not saving. My models look like this:
class Vote < ActiveRecord::Base
belongs_to :entry
belongs_to :voter
attr_accessible :entry, :voter, :voter_id
class Voter < ActiveRecord::Base
attr_accessible :email_address, :verification_code, :verified, :votes_attributes, :votes
has_many :votes, :class_name => "Vote"
accepts_nested_attributes_for :votes
class Entry < ActiveRecord::Base
attr_accessible :caption, :email_address, :filename
end
I am then my form looks like this:
<%= f.fields_for :votes do |builder| %>
<fieldset>
<%= builder.label :votes, "Vote" %>
<%= collection_select(:votes, :entry_id, Entry.all, :id, :caption, :prompt => 'Please select an Entry') %>
</fieldset>
<% end %>
But the votes are not saving in the database. The response looks like this:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"x5f85viIp/KHJKQF7DotaF3MhebARWcaLDKRbcZw/lM=", "voter"=>{"email_address"=>"sadasfd"}, "votes"=>{"entry_id"=>"3"}, "commit"=>"Create Voter"}
So whats going wrong?
Please try
class Voter < ActiveRecord::Base
attr_accessible :email_address, :verification_code, :verified, :votes
has_many :votes, :class_name => "Vote"
attr_accessible :votes_attributes,
accepts_nested_attributes_for :votes
Modify vote_params in VotesController
private
def vote_params
params.require(:vote).permit(:id, :email_address, :verification_code, :verified, votes_attributes: [:id, :name])
end