Three forms for one object in a modal - ruby-on-rails

I have a webpage with a list of offices. Currently I'm trying to make three forms for editing/adding/deleting an office. This is what I have:
A model:
class ChangeOfficeAddress < ApplicationRecord
belongs_to :office
belongs_to :insurer
belongs_to :city
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates_presence_of :email
validates_format_of :email, with: VALID_EMAIL_REGEX
validates_presence_of :edit_office_address
validates_presence_of :add_office_address
validates_presence_of :delete_office_address
validates_presence_of :city_id
validates_presence_of :insurer_id
validates_presence_of :name
end
In a view I have my modals in partials:
<div id="addModal" class="modal fade" role="dialog" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<div class="text-center">
<div class="btn-group topbar header-buttons" role="group" aria-label="...">
<%= link_to 'Add', '#', class: 'btn btn-default disabled' %>
<%= link_to 'Edit', '#editModal', { 'class' => 'btn btn-default', 'data-toggle' => 'modal', 'data-dismiss' => 'modal' } %>
<%= link_to 'Delete', '#deleteModal', { 'class' => 'btn btn-default', 'data-toggle' => 'modal', 'data-dismiss' => 'modal' } %>
</div>
</div>
</div>
<div class="modal-body">
<%= form_for (#change_office_address), remote: true, format: :json, html: { class: :contact_form } do |f| %>
<div id="error_explanation" style='display:none;' class="bg-danger text-danger alert fade in alert-danger alert-dismissable errors">
<ul>
<% if #change_office_address.errors.any? %>
<% #change_office_address.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<% end %>
</ul>
</div>
<%= f.text_field :name, placeholder: 'Name', class: 'form-control' %>
<br>
<%= f.text_field :email, placeholder: 'e-mail', class: 'form-control' %> <br>
<%= f.label :city_id %>
<%= f.collection_select :city_id, City.order(:name), :id, :name,
{ include_blank: true }, { class: 'form-control' } %>
<br>
<%= f.label :insurer_id, 'Insurer' %>
<%= f.collection_select :insurer_id, Insurer.order(:short_name), :id, :short_name,
{ include_blank: true }, { class: 'form-control' } %>
<br>
<%= f.text_area :add_office_address, placeholder: 'Add address', class: 'form-control', cols: '30',
rows: '5' %> <br>
<div class="text-center">
<%= f.submit, class: 'btn btn-default' %>
</div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
And two other modals, the only differences between them is that :add_office_address is substituted with :edit_office_address and :delete_office_address.
When there are no validations in the model, the form submits, and everything is Ok, but when I add validations to :add_office_address, :edit_office_address and :delete_office_address, the validation doesn't pass, cause these fields(I mean :edit_office_address, :delete_office_address or :add_office_address) are blank.
How can I make different forms? Thanks ahead!

For some context, what are the reasons for different fields for [add|edit|delete]_office_address?
However, to solve your issue, you should probably do something like:
class ChangeOfficeAddress < ApplicationRecord
belongs_to :office
belongs_to :insurer
belongs_to :city
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates_presence_of :email
validates_format_of :email, with: VALID_EMAIL_REGEX
validates_presence_of :edit_office_address, if: :edit_office_address_changed?
validates_presence_of :add_office_address, if: :add_office_address_changed?
validates_presence_of :delete_office_address, if: :delete_office_address_changed?
validates_presence_of :city_id
validates_presence_of :insurer_id
validates_presence_of :name
end
Let me know if that works.

Related

Simple_Form Auto Disabling Inputs on Reload

Updating simple_form works fine but when I reload the page, it renders all the inputs as disabled. Any ideas? I can't find anything in the documentation that says what causes it to do this automatically. Thanks
the simple form.
<%= simple_form_for #product_campaign, url: update_completion_criteria_rules_partner_product_product_campaign_path(partner_id: #partner.id, product_id: #product.id, id: #product_campaign.id), remote: true, html: { id: "product-campaign-completion-criteria-rules"} do |f| %>
<div class="">
<%= f.simple_fields_for :completion_criteria_rules, f.object.completion_criteria_rules.order(:created_at) do |complete_criteria_rule| %>
<%= render 'completion_criteria_rule_fields', :f => complete_criteria_rule %>
<% end %>
<%= link_to_add_association "Add Completion Criteria Rule", f, :completion_criteria_rules, class: "btn btn-info float-left mt-10", id: "add-completion-criteria-rule", data: { } %>
<button type="submit" class="btn btn-info float-right mt-10" id="update-product-campaign-form" ><span id="save-journey-button-text">Save Changes</span></button>
</div>
<% end %>
completion_criteria_rule_fields partial
<div class="form-row">
<div class="form-group col-md-6">
<%= f.input :events, collection: CompletionCriteriaRule::EVENTS_OPTIONS, label: 'Choose Events', include_blank: false, input_html: { class: "form-control form-field-type", "data-provide": "selectpicker", multiple: true } %>
</div>
<div class="form-group col-md-6">
<%= f.input :actions, collection: [['Add Campaign', 'add_campaign']], label: 'Choose Action', input_html: { class: "form-control form-field-type actions-dropdown", "data-provide": "selectpicker", multiple: true } %>
</div>
</div>
<div class="form-row add-campaign-dropdown-wrapper" <% unless f.object.actions&.include?('add_campaign') %>style="display:none;<% end %>">
<div class="form-group col-md-6">
<%= f.input :transition_campaign_id, collection: #product_campaign.product.product_campaigns.where.not(id: #product_campaign.id).published.map{|k,v| [k.name.titleize, k.id]}, label: 'Select Campaign To Add', input_html: { class: "form-control form-field-type", "data-provide": "selectpicker" } %>
</div>
<div class="form-group col-md-6">
<label>Campaign Start Delay</label>
<div class="input-group">
<%= f.input_field :transition_campaign_delay, class: "form-control form-field-type" %>
<span class="input-group-addon">days</span>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<span class="float-right">
<%= link_to_remove_association 'Remove Rule', f, class: "btn btn-danger btn-xs" %><br>
</span>
</div>
</div>
<div class="divider"></div>
</div>
completion_criteria_rule.rb
class CompletionCriteriaRule < ApplicationRecord
EVENTS_OPTIONS = [["Appointment Booked", "appointment.booked"], ["Appointment Attended", "appointment.attended"], ["Appointment Cancelled", "appointment.cancelled"], ["Lifecycle Changed to Client", "lifecycle.client"], ["Lifecycle Changed to Lead", "lifecycle.lead"], ["Lifecycle Changed to Former Client", "lifecycle.former_client"], ["Lifecycle Changed to None", "lifecycle.none"]].freeze
belongs_to :product_campaign
belongs_to :transition_campaign, class_name: 'ProductCampaign', foreign_key: 'transition_campaign_id', optional: true
validates :product_campaign, :events, :actions, presence: true
validates :transition_campaign, :transition_campaign_delay, presence: true, if: -> { actions&.include? 'add_campaign' }
before_save :reject_blank_events
before_save :reject_blank_actions
def reject_blank_events
events.reject!(&:blank?)
end
def reject_blank_actions
actions.reject!(&:blank?)
end
end
Found out that I had some js that was disabling form inputs with a certain class that was disabling the inputs after page load. All working now.

Setting the end_time value the same as start_time value in a rails form

Rails 6.0.3
I am using a form to schedule meetings.
It is being used for both single time meetings that span over several days (with start_time and end_time) and tasks that last only one day.
For singular day meetings, I need the end_time to be set to the same value as start_time, without user selecting it.
I have tried many things in the controller, but can't work it out.
How would you go about this.
Thanks for the help
<div class="border border-grey-light rounded" style ="padding: 10px;">
<%= form_with(model: meeting, local: true, :html => {:id => "flatpickr-form-single"} ) do |form| %>
<div class="mb-6">
<%= form.label :name, class: 'label' %>
<%= form.text_field :name, required: true, class: 'form-control', placeholder: "Task name" %>
</div>
<div class="mb-6">
<%= form.label :body %>
<%= form.rich_text_area :body, class: 'form-control' %>
</div>
<div class="start_time_result mb-6" style ="width: 30vw;">
<%= form.label :start_time, class: 'label' %>
<div class="flex items-center justify-between max-w-md">
<%= form.text_field :start_time, data: { behavior: "flatpickr" }, placeholder: "Date and time select ...", class: "form-control" %>
</div>
</div>
<div class=" field" style ="width: 30vw;">
<%= form.label :end_time, class: 'label' %>
<div class="end_time_result flex items-center justify-between max-w-md" >
<%= form.text_field :end_time, data: { behavior: "flatpickr" }, placeholder: "Date and time select ...", class: "form-control required" %>
</div>
</div>
<%= form.submit class: "btn btn-primary text-base py-1.5 px-5", value: "Confirm" %>
<% end %>
</div>
<script>
const selectElement = document.querySelector('.start_time_result');
selectElement.addEventListener('change', (event) => {
const end_time_result = document.querySelector('.end_time_result');
end_time_result.textContent = `${event.target.value}`;
});
</script>
You can add a before_action in the controller and set the end_time parameter value to the same as the start_time from there.

Can't seem to submit collection_select and receiving Unpermitted parameter: :hero_id

Sorry for the messy post, my first time posting. I have been trying to get this collection submit to work, but every time I press create report button I have it goes back to the screen and puts out Unpermitted parameter: :hero_id in the rails server terminal.
Model
class Report < ApplicationRecord
validates :subject, presence: true, length: { minimum: 6, maximum: 100 }
validates :description, presence: true, length: { minimum: 10, maximum: 300 }
belongs_to :requester
has_and_belongs_to_many :heros
end
View/Form
<div class="container">
<div class="row justify-content-center">
<div class="col-10">
<% if #report.errors.any? %>
<h2>The following errors prevented the article from being saved</h2>
<ul>
<% #report.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= form_with(model: #report, class: "shadow p-3 mb-3 bg-dark rounded", local: true) do |f| %>
<div class="form-group row">
<%= f.label :subject, class: "col-2 col-form-label text-light" %>
<div class="col-10">
<%= f.text_field :subject, class: "form-control shadow rounded", placeholder: "Subject of Report" %>
</div>
</div>
<div class="form-group row">
<%= f.label :description, class: "col-2 col-form-label text-light" %>
<div class="col-10">
<%= f.text_area :description, rows: 10, class: "form-control shadow rounded", placeholder: "Description of Issue" %>
</div>
</div>
<div class="form-group row">
<%= f.label :hero, class: "col-2 col-form-label text-light" %>
<div class="col-10">
<%= f.collection_select(:hero_ids, Hero.all, :id, :hero_name, {prompt: "Select a Hero"}, {:required => true}) %>
</div>
</div>
<div class="btn-toolbar p-2 mb-2 row justify-content-center">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
</div>
<div class="mb-3">
<%= link_to '[ Cancel and return to reports listing ]', reports_path, class: "text-info" %>
</div>
</div>
</div>
Controller
def report_params
#byebug
params.require(:report).permit(:subject, :description, hero_ids: [])
end
Console
(byebug) params.require(:report)
<ActionController::Parameters {"subject"=>"Test report", "description"=>"Test report", "hero_ids"=>"1"} permitted: false>

How can I use optional attributes on an object using Ruby on Rails?

I have several attributes on a Player model. My form contains fields for a player to be added. I want to have optional fields where a second player can enter their name, and rather than having to retype the address and other things for the second player, I want the second player to inherit all the other information that the first player entered without having to type it in again. How can I do this?
players/_form.html.erb
<%= form_for #player, html: {class: "horizontal-form"} do |player| %>
<div class="form-group">
<div class = row>
<%= player.label :first_name, "First Name", class: "col-sm-2 control-label"%>
<div class="col-sm-offset-2">
<%= player.text_field :first_name, class: "form-control", :required => true %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :last_name, "Last Name", class: "col-sm-2 control-label"%>
<div class="col-sm-offset-2">
<%= player.text_field :last_name, class: "form-control", :required => true %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :address, "Address", class: "col-sm-2 control-label"%>
<div class="col-sm-offset-2">
<%= player.text_field :address, class: "form-control", :required => true %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :city, "City", class: "col-sm-2 control-label"%>
<div class="col-sm-offset-2">
<%= player.text_field :city, class: "form-control", :required => true %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :state, "State", class: "col-sm-2 control-label"%>
<div class="col-sm-offset-2">
<%= player.text_field :state, class: "form-control", :required => true %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :zip_code, "Zip Code", class: "col-sm-2 control-label"%>
<div class="col-sm-offset-2">
<%= player.text_field :zip_code, class: "form-control", :required => true %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :email, "Email", class: "col-sm-2 control-label"%>
<div class="col-sm-offset-2">
<%= player.text_field :email, class: "form-control", :required => true %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :veteran, "Veteran", class: "col-sm-2 control-label"%>
<div class="checkbox col-sm-offset-3">
<%= player.check_box :veteran %>
</div>
</div>
</div>
<div class="form-group">
<div class = row>
<%= player.label :branch_id, "Branch", class: "col-sm-2 control-label" %>
<%= player.collection_select(:branch_id, Branch.all, :id, :name, :prompt => true) %>
</div>
</div>
<%= player.submit 'Submit', class: 'col-sm-2 col-sm-offset-2 btn btn-primary' %>
<% end %>
Thank you for any suggestions!
This is probably more of a javascript question than a RoR one.
Assuming you want them to have the option to fill in different information, the easiest way I can think to do this is to have a bunch of hidden fields for the player two information (other than their name), give the player one fields onkeypress events that would call a function that would take in the id of the corresponding player two field and use that to find the hidden player two field and fill in their html to be the same as the field you're currently filling in, something like
function fillPlayerTwoField(id) {
$(id).text(this.value)
}
then if they start filling in the player two name unhide all the player two fields so the have the option to change that information if they so choose

Rails 4 Nested Attributes has Unpermitted parameter error

Below is my api model:
class Api < ActiveRecord::Base
validates_presence_of :name
belongs_to :service
has_many :statuses
accepts_nested_attributes_for :statuses, reject_if: proc { |attributes| attributes['name'].blank? }
end
Below is my description model:
class Description < ActiveRecord::Base
validates_presence_of :value
belongs_to :status
end
Below is my status model:
class Status < ActiveRecord::Base
belongs_to :api
has_many :descriptions
accepts_nested_attributes_for :descriptions, reject_if: proc { |attributes| attributes['value'].blank? }
end
And below is my new and create action of controller:
def new
#api = Api.new
#status = #api.statuses.new
#status.descriptions.new
end
def create
#api = Api.new(api_params)
if #api.save
flash[:info] = request.original_url + ".do?apiname=" + "#{#api.name}"
redirect_to root_path
else
#api.statuses.new
render :new
end
private
def api_params
params.require(:api).permit(:name, statuses_attributes: [:name, descriptions_attributes:[:value]])
end
Below is my new template:
<div class="form-horizontal">
<%= form_for #api, :url => commons_path do |f| %>
<div class="form-group">
<%= f.label :name, "API Name", class: "col-sm-2 control-label" %>
<div class="col-sm-8">
<%= f.text_field :name, class: "form-control" %>
</div>
</div>
<%= f.fields_for :statuses do |status| %>
<div class="form-group">
<%= status.label :name, "Status", class: "col-sm-2 control-label" %>
<div class="col-sm-8">
<%= status.text_field :name, class: "form-control" %>
</div>
</div>
<%= f.fields_for :description do |description| %>
<div class="form-group">
<%= description.label :value, "Body", class: "col-sm-2 control-label" %>
<div class="col-sm-8">
<%= description.text_area :value, class: "form-control", rows: 12, cols: 65 %>
</div>
</div>
<% end %>
<% end %>
<%= f.submit("Create Data", class: 'btn btn-primary col-sm-offset-2') %>
<%= link_to "Cancel", root_path, class: "btn btn-danger" %>
<% end %>
After I create new data.It seems like only description's value did not save to my data base. and find an error "Unpermitted parameter: description" in my console.
Any one know what happen?
<div class="form-horizontal">
<%= form_for #api, :url => commons_path do |f| %>
<div class="form-group">
<%= f.label :name, "API Name", class: "col-sm-2 control-label" %>
<div class="col-sm-8">
<%= f.text_field :name, class: "form-control" %>
</div>
</div>
<%= f.fields_for :statuses do |status| %>
<div class="form-group">
<%= status.label :name, "Status", class: "col-sm-2 control-label" %>
<div class="col-sm-8">
<%= status.text_field :name, class: "form-control" %>
</div>
</div>
<%= status.fields_for :descriptions do |description| %>
<div class="form-group">
<%= description.label :value, "Body", class: "col-sm-2 control-label" %>
<div class="col-sm-8">
<%= description.text_area :value, class: "form-control", rows: 12, cols: 65 %>
</div>
</div>
<% end %>
<% end %>
<%= f.submit("Create Data", class: 'btn btn-primary col-sm-offset-2') %>
<%= link_to "Cancel", root_path, class: "btn btn-danger" %>
<% end %>

Resources