Rails 4 Nested Attributes has Unpermitted parameter error - ruby-on-rails

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 %>

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.

How to update unique fields using a confirm page?

So I have this book edit page which contains unique fields(Title, ISBN). But before I submit the form to update, I need to send first the form information to another confirmation page and then update. But when I pass the form info to the confirmation page, the unique validations for Title and ISBN fails. I have this code:
book.rb
validates :title, presence: true,
uniqueness: true
validates :isbn, presence: true,
uniqueness: true,
format: { with: /[0-9]/ }
edit.html.erb
<%= form_for #book, url: confirm_edit_admin_book_path, method: :patch, html: { class: "form" } do |f| %>
<%= f.hidden_field :id %>
<div class="float-right">
<button class="btn btn-primary">Confirm</button>
</div>
<h4 class="card-title">Edit Book</h4>
<div class="form-group row mt-5">
<%= f.label :title, class: "col-md-2 col-form-label required" %>
<div class="col-md-10">
<%= f.text_field :title, class: "form-control" %>
<%= render "admin/shared/error_field", field: :title %>
</div>
</div>
<div class="form-group row">
<%= f.label :isbn, "ISBN", class: "col-md-2 col-form-label required" %>
<div class="col-md-10">
<%= f.text_field :isbn, class: 'col-sm-12 form-control' %>
<%= render "admin/shared/error_field", field: :isbn %>
</div>
</div>
<div class="form-group row">
<%= f.label :released_at, class: "col-md-2 col-form-label required" %>
<div class="col-md-10">
<%= f.date_field :released_at, class: 'col-sm-12 form-control' %>
<%= render "admin/shared/error_field", field: :released_at %>
</div>
</div>
<div class="form-group row">
<%= f.label :description, class: "col-md-2 col-form-label" %>
<div class="col-md-10">
<%= f.text_area :description, class: 'col-sm-12 form-control' %>
<%= render "admin/shared/error_field", field: :description %>
</div>
</div>
<div class="form-group row">
<%= f.label :quantity, class: "col-md-2 col-form-label required" %>
<div class="col-md-10">
<%= f.number_field :quantity, class: 'col-sm-12 form-control' %>
<%= render "admin/shared/error_field", field: :quantity %>
</div>
</div>
<div class="float-right">
<%= f.submit "Confirm", class: "btn cur-p btn-primary" %>
</div>
<% end %>
books_controller.rb
def confirm_edit
#book = Book.new(book_params)
book_info = Book.find(#book.id)
if #book.valid?
session[:book_update] = #book
else
render 'edit'
end
end
def update
#book = Book.find(params[:id])
#book.update_attributes(session[:book_update].compact)
session.delete(:book_update)
redirect_to admin_book_url
end
In the confirm_edit action you are creating a new instance of Book using the params from the update action, which are presumably the params from an existing book.
#book = Book.new(book_params)
You are then calling #book.valid? which is going to fail (unless you've changed the Title and ISBN) because a book with the same values is already in the database.
You could retrieve the book from the database and then use .assign_attributes to check validity that way perhaps?
def confirm_edit
#book = Book.find(params[:id])
#book.assign_attributes(book_params)
if #book.valid?
session[:book_update] = #book
else
render 'edit'
end
end

Duplicating a record in Rails except for one attribute?

In my Rails application I am getting the duplication of last Expense record after the creation of new record but I want to exclude one attribute while duplication that is :description_other, " ".
expenses_controller.rb
class ExpensesController < ApplicationController
# GET /expenses/new
def new
if Expense.last.present?
#expense = Expense.last.dup
else
#expense = Expense.new
end
end
def expense_params
params.require(:expense).permit(:date, :description, :description_other, :trips, :fare, :credit)
end
end
_form.html.erb
<div class="row">
<div class="col-md-3 col-md-offset-4">
<%= form_for(#expense) do |f| %>
<div class="form-group">
<%= f.label :date %><br>
<span class="datetime"><%= f.date_select :date %></span>
</div>
<div class="form-group">
<%= f.label :credit %><br>
<%= f.text_field :credit, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :description %><br>
<%= f.select(:description, options_for_select([['PLEASE SELECT...', ''],['METRO', 'METRO'], ['BUS', 'BUS'], ['TAXI', 'TAXI'], ['OTHERS', 'OTHERS'], ['FOOTLOOSE', 'FOOTLOOSE']]), {}, {class: "form-control", id: "expense_description"}) %>
<br>
<div id="otherDesc">
<%= f.text_field :description_other, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :trips %><br>
<%= f.number_field :trips, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :fare %><br>
<%= f.text_field :fare, class: "form-control" %>
</div>
<br>
<div style="margin-left: 70px;" class="form-group">
<%= f.submit #expense.new_record? ? "Create Expense" : "Update Expense", class: "btn btn-lg btn-primary" %>
</div>
<% end %>
</div>
</div>
I have tried but unable to get the desired result.
Any suggestions are most welcome.
Thank you in advance.
You should add
<div id="otherDesc">
<%= f.text_field :description_other, class: "form-control", value: " "%>
</div>
use tap and then exclude property by setting to nil
def new
if Expense.last.present?
# exclude here
#expense = Expense.last.dup.tap do | exp |
exp.description_other = nil
end
else
#expense = Expense.new
end
end

Three forms for one object in a modal

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.

Submit multiple entries in database table through single object in rails

I am new to rails, And stuck in this problem from last two days
I have a student and student_parent model they have a one-to-many relationship i want to build database attribute through one object from form to datase.
controller's method
def new
#student = Student.new
1.times{ #student.student_parents.build }
.....
.....
end
Create Method:-
def create
#student = Student.new(params[:student])
respond_to do |format|
if #student.save
format.html { redirect_to Student, notice: 'Student was successfully created.' }
format.json { render json: #student, status: :created, location: #student }
else
format.html { render action: "new" }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
Model:-
class Student < ActiveRecord::Base
include ErrorMessages
belongs_to :user
has_many :student_parents
attr_accessible :birth_date, :blood_group, :first_name, :gender, :last_name, :middle_name,
:school_name, :student_rollno, :email, :user_id, :student_parents_attributes
accepts_nested_attributes_for :student_parents
end
form:-
<%= simple_form_for #student, :html => { :class => 'form-horizontal' } do |f| %>
<div class="row-fluid">
<div class="span3">
<%= f.label :first_name, :class => 'control-label',:required => true %>
<%= f.text_field :first_name %>
</div>
<div class="span3">
<%= f.label :middle_name, :class => 'control-label'%>
<%= f.text_field :middle_name %>
</div>
<div class="span3">
<%= f.label :last_name, :class => 'control-label',:required => true %>
<%= f.text_field :last_name %>
</div>
</div>
<div class="control-group">
<label class = "control-label"> Email </label>
<div class="controls">
<%= f.text_field :email, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<label class = "control-label"> Birth Date <abbr title="required">*</abbr></label>
<div class="controls">
<%= f.text_field :birth_date, :class => 'text_field' ,'data-behaviour' => 'datepicker' %>
</div>
</div>
<% model_class = StudentParent %>
<div class="page-header">
<h4> Parent Information</h4>
</div>
<%= f.fields_for :student_parents do |student_parent| %>
<div class="row-fluid">
<!--<div class="span9">-->
<h5> Father Name </h5>
<div class="span3">
<%= student_parent.label :first_name, :class => 'control-label',:required => true %>
<%= student_parent.text_field :first_name %>
</div>
<div class="span3">
<%= student_parent.label :middle_name, :class => 'control-label'%>
<%= student_parent.text_field :middle_name %>
</div>
<div class="span3">
<%= student_parent.label :last_name, :class => 'control-label',:required => true %>
<%= student_parent.text_field :last_name %>
</div>
</div>
<div class="row-fluid">
<h5> Mother Name </h5>
<div class="span3">
<%= student_parent.label :first_name, :class => 'control-label',:required => true %>
<%= student_parent.text_field :first_name %>
</div>
<div class="span3">
<%= student_parent.label :middle_name, :class => 'control-label'%>
<%= student_parent.text_field :middle_name %>
</div>
<div class="span3">
<%= student_parent.label :last_name, :class => 'control-label',:required => true %>
<%= student_parent.text_field :last_name %>
</div>
</div>
<% end %>
<div class="form-actions">
<%= f.button :submit, :class => 'btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
students_path, :class => 'btn' %>
</div>
when submit it only build student information in student table and mother information in student_parent table. But it miss the parent information.

Resources