Build answer with opposite attribute of first answer - ruby-on-rails

My form creates a question and answers. For true and false I currently have one answer being submitted that is the correct answer. I am trying to figure out how to make another answer with the same attributes except have the opposite value, either True or False.
Since the answers are created with the question I'm not sure what to do. I was thinking of the controller having something like, #question.answers.build(question: params[:content]) but am lost. Is there a #question.answers.build.where(content: (#question.content.opposite)) or something? Any help aprreciated
The controller:
def new_tf
#question = Question.new
#question.answers.build
end
def create
#question = Question.new(question_params)
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' }
format.json { render action: 'show', status: :created, location: #question }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
def question_params
params.require(:question).permit(:content, :question_type, :category, :product_id, :active, :user_id, answers_attributes: [ :content, :correct, :question_id ] ).
merge user_id: current_user.id
end
The form:
<h1>New True/False Question</h1>
<%= link_to 'Back', questions_path %>
<%= form_for #question, url: new_tf_question_path(#question) do |f| %>
<%= render 'shared/error_questions' %>
<%= f.label :content, "Question" %><br>
<%= f.text_field :content, class: "input-lg" %>
<%= f.label :category %><br>
<%= f.select :category, [ ["IP Voice Telephony", "ip_voice"], ["IP Video Surveillance", "ip_video_surveillance"], ["IP Video Telephony", "ip_video_telephony"], ["Enterprise Gateways", "enterprise_gateways"], ["Consumer ATAs", "consumer_atas"], ["IP PBX", "ip_pbx"] ], {prompt: "Select Category"}, class: "input-lg" %>
<%= f.label :product_id %><br>
<%= f.collection_select :product_id, Product.all, :id, :name, {prompt: "Select a product"}, {class: "form-control input-lg"} %>
<%= f.label :active %><br>
<%= f.check_box :active %>
<%= f.fields_for :answers do |builder| %>
<%= render 'tf_answers', :f => builder %>
<% end %>
<%= f.select :question_type, [["True False", "TF"]], {class: "form-control input-lg"}, style: "visibility: hidden" %>
<%= f.submit "Create Question", class: "btn btn-lg btn-primary", style: "margin-top: 45px;" %>
<% end %>
The _tf_answers.erb.rb
<%= f.check_box :correct, {checked: true, style: "visibility: hidden"} %>
<%= f.label :content, "Answer" %>
<%= f.text_field :content, :value => 'True', :readonly => true, :class => "input-lg", :id => "answer" %>
<%= button_tag "Toggle True/False", :id => "toggle", :class => "btn btn-small btn-inverse", :type => "button" %>
<script>
function checkAnswer() {
var answer = $('#answer').val();
if ('False' == answer) {
$("#answer").val('True');
} else {
$("#answer").val('False');
}
}
$(document).ready(function(){
$('#toggle').click(function () {
checkAnswer();
});
});
</script>

I ended up creating a new answer after the first one saved.
if #question.save
#answer = Answer.find_by_question_id(#question.id)
if #answer.content == "True"
Answer.create(content: "False", question_id: #answer.question_id, correct: false)
end
if #answer.content == "False"
Answer.create(content: "True", question_id: #answer.question_id, correct: false)
end
Ta-da!

Why doesn't your model automatically create both answers? Extend the save method in your model and you won't have to have this logic in your controller. It probably belongs there anyway.

Related

Inline error messages in a form_for with remote: true

I have a form in a modal that looks like this:
<%= 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.hidden_field :city_id, value: #office.city.id %>
<%= f.hidden_field :office_id, value: #office.id %>
<%= f.hidden_field :insurer_id, value: #office.insurer.id %>
<%= f.text_field :name, placeholder: 'Name', class: 'form-control' %>
<br>
<%= f.text_field :email, placeholder: 'e-mail', class: 'form-control' %> <br>
<%= f.label :city_name, 'City' %>
<%= f.text_field :city_name, class: 'form-control', value: #office.city.name.mb_chars.titleize, readonly: true %>
<br>
<%= f.label :insurer_name, 'Insurer' %>
<%= f.text_field :insurer_name, class: 'form-control', value: #office.insurer.short_name, readonly: true %>
<br>
<%= f.label :office_name, 'Insurer\'s office address' %>
<%= f.text_field :office_name, class: 'form-control', value: #office.address, readonly: true %>
<br>
<%= f.text_field :edit_office_address, placeholder: 'New address', class: 'form-control' %> <br>
<%= f.text_area :comment, placeholder: 'Comment', class: 'form-control', cols: '30', rows: '5' %> <br>
<div class="text-center">
<%= f.submit 'Inform about deleting', class: 'btn btn-danger' %>
<%= f.submit 'Inform about changing address', class: 'btn btn-default' %>
</div>
<% end %>
After the form was submitted, and validations didn't pass, I can see error messages at the top of my form. But I'd like to show errors inline. I tried to add <span class="help-inline"><%= #change_office_address_.errors[:email] %></span> into my form, but it doesn't work.
A controller:
class ChangeOfficeAddressesController < ApplicationController
def create
#change_office_address = ChangeOfficeAddress.new(change_office_addresses_params)
respond_to do |format|
if params[:commit] == 'Inform about changing address'
if #change_office_address.save
format.html { ChangeOfficeAddressMailer.change_office_address_new(#change_office_addres).deliver_now
redirect_to :back, notice: 'Thanks.' }
format.json { redirect_to :back, status: :created, location: #change_office_address,
notice: Thanks.' }
else
format.json { render json: #change_office_address.errors.full_messages, status: :unprocessable_entity }
end
elsif params[:commit] == 'Inform about changing address'
#change_office_address.delete_office_address = 'Some text'
#change_office_address.edit_office_address = nil
if #change_office_address.save
format.html { ChangeOfficeAddressMailer.change_office_address_new(#change_office_addres).deliver_now
redirect_to :back, notice: 'Thanks.' }
format.json { redirect_to :back, status: :created, location: #change_office_address,
notice: 'Thanks.' }
else
format.json { render json: #change_office_address.errors.full_messages, status: :unprocessable_entity }
end
else
if #change_office_address.save
format.html { ChangeOfficeAddressMailer.change_office_address_new(#change_office_addres).deliver_now
redirect_to :back, notice: 'Thanks.' }
format.json { redirect_to :back, status: :created, location: #change_office_address,
notice: 'Thanks.' }
else
format.json { render json: #change_office_address.errors.full_messages, status: :unprocessable_entity }
end
end
end
end
private
def change_office_addresses_params
params.require(:change_office_address).permit(:email, :name, :edit_office_address, :add_office_address,
:delete_office_address, :office_id, :insurer_id, :city_id, :comment)
end
end
And application.js:
$(document).ready(function() {
return $(document).bind("ajaxError", "form.contact_form", function(event, jqxhr) {
var $contact_form, $error_container, $error_container_ul;
$contact_form = $(event.data);
$error_container = $("#error_explanation", $contact_form);
$error_container_ul = $("ul", $error_container).empty();
if ($error_container.is(":hidden")) {
$error_container.show();
} else {
$("#error_explanation").remove("#error_explanation");
}
return $.each(jqxhr.responseJSON, function(index, message) {
return $("<li>").html(message).appendTo($error_container_ul);
});
});
});
Is there any way to add those error messages? Thanks.
To get inline validations, I would use Jquery Validate and validate on your change_office_address model.
When I had to do something similar I used this SO post as reference, which I paraphrase after:
How to use jquery validation plugin in rails
First include the jquery validation file in your layout, which can be found here:
https://jqueryvalidation.org/
Then in your form add a class to the required fields such as <%= f.text_field :firstname, :class => "required" %>. Then write a method with the form_id to trigger the validation.
function validateofficeFuction() {
$("#change_office_form").validate({
errorClass: "authError"
})
}
$(document).ready(validateofficeFuction);
$(document).on('page:load', validateofficeFuction);
If you're using turbolinks 5, which is included in rails 5 instead of using $(document).ready use $(document).on "turbolinks:load"
If this is set up properly, you should get your error messages right underneath each field that failed instead at the top of the page or form.

Rails 4, Cocoon, ERB Template, how to make selected an options_from_collection_for_select in Edit Action?

This is my first time with Cocoon, and maybe this is a really dumb question, but I already spend many time looking how to do this with ERB template and avoid using simple_form or other helper.
Take a look of my models:
models/loot.rb
class Lot < ActiveRecord::Base
has_many :colindanciums, dependent: :destroy
has_many :cardinal_points, through: :colindanciums
accepts_nested_attributes_for :colindanciums, allow_destroy: true
end
models/colindancium.rb
class Colindancium < ActiveRecord::Base
belongs_to :cardinal_poing
belongs_to :lot
end
models/cardinal_point.rb
class CardinalPoint < ActiveRecord::Base
has_many :colindanciums
has_many :lots, through: :colindanciums
end
The form:
views/lots/_form.html.erb
<%= form_for(#lot, remote: true) do |f| %>
<%= render 'shared/error_messages', object: #lot %>
...
...
...
<fieldset id="colindancium-orientation">
<ol>
<%= f.fields_for :colindanciums do |colindancium| %>
<%= render 'colindancium_fields', f: colindancium %>
<% end %>
</ol>
<%= link_to_add_association 'Nueva Colindancia', f, :colindanciums, 'data-association-insertion-node' => "#colindancium-orientation ol", 'data-association-insertion-method' => "append" %>
</fieldset>
...
...
...
<% end %>
The partial:
views/lots/_colindancium_fields.html.erb
<li class="control-group nested-fields">
<div class="controls">
<%= f.label :description, "Descripcion:" %>
<%= f.text_field :description %>
<%= f.label :linear_meters, "Metros Lineales:" %>
<%= f.text_field :linear_meters %>
<%= f.label :cardinal_point_id, "Orientacion:" %>
<%= f.select :cardinal_point_id,
options_from_collection_for_select(CardinalPoint.all, :id, :name), { }, { :class => "form-control", :prompt => "Seleccione un Punto Cardinal" } %>
<%= link_to_remove_association "Eliminar", f %>
</div>
</li>
Everything works great when I insert new fields, it saves it in DB, it Update it in DB, my problem is in the options_from_collection_for_select when I open the form in Edit Action, the fourth parameter of this helper is the selected value... I can't find the way to make selected the value that is stored in my db, it always show the 1 index... I can't access the #... object from the _form, the other fields (:description, :linear_meters) are working quite good my problem is in the f.select, I don't know how to do it.
EDIT My controller:
# GET /lots/new
def new
#lot = Lot.new
#lot.colindanciums.build
authorize #lot
end
# PATCH/PUT /lots/1
# PATCH/PUT /lots/1.json
def update
authorize #lot
respond_to do |format|
if #lot.update(lot_params)
format.html { redirect_to #lot, notice: 'Lot was successfully updated.' }
format.json { render :show, status: :ok, location: #lot }
format.js
else
format.html { render :edit }
format.json { render json: #lot.errors, status: :unprocessable_entity }
format.js { render json: #lot.errors, status: :unprocessable_entity }
end
end
end
I change my logic in the select, i made it works in this way:
<div class="form-group">
<%= f.label :cardinal_point_id, "Orientacion:", :class => "control-label" %>
<%= f.select :cardinal_point_id , CardinalPoint.all.collect {|p| [ p.name, p.id ] }, { :include_blank => 'Seleccione un Punto Cardinal'}, :class => "form-control" %>
</div>
I post my answer in case anybody have the same issue.
You forgot to put the parenthesis correctly
<%= f.select (:cardinal_point_id,
options_from_collection_for_select(CardinalPoint.all, :id, :name), { }, { :class => "form-control", :prompt => "Seleccione un Punto Cardinal" }) %>

Devise redirects to index action on error

I am using devise, and is having an issue if you try to signup with an existing email.
When you signup you do it from this url:
http://localhost:3000/accounts/new
So I have an account, where I add a user (devise). If I try to signup as a user which already exists I get the correct error:
"Users email has already been taken"
But it redirects to http://localhost:3000/accounts
The controller looks a bit like this:
def create
name = account_params[:name]
first_name = Modules::NameHelpers.get_first_name(name)
last_name = Modules::NameHelpers.get_last_name(name)
#account = Account.new(account_params_wo_user_name)
#account.users.first.first_name = first_name
#account.users.first.last_name = last_name
respond_to do |format|
if #account.save
sign_in #account.users.first
format.html { redirect_to root_path, notice: "Thanks for signing up." }
format.json { render action: 'show', status: :created, location: #account }
else
format.html { render action: 'new' }
format.json { render json: #account.errors, status: :unprocessable_entity }
end
end
end
I can't seem to find what redirects to the index page.
Update:
Here is the form:
<%= form_for(#account) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div>
<%= f.label :name, 'Account Name' %> <br />
<%= f.text_field :name, :required => true, :placeholder => 'Your account name' %>
</div>
<%= f.fields_for :users do |user_form| %>
<div><%= user_form.label :name %><br />
<%= user_form.text_field :name, :autofocus => true, :required => true, :placeholder => 'Your name' %></div>
<div><%= user_form.label :email %><br />
<%= user_form.email_field :email, :required => true, :placeholder => 'Your email' %></div>
<div><%= user_form.label :password, :required => true %><br />
<%= user_form.password_field :password, :required => true, :placeholder => 'Enter a 8 character password'%></div>
<div><%= user_form.label :password_confirmation, :required => true %><br />
<%= user_form.password_field :password_confirmation, :required => true, :placeholder => 'Confirm password' %></div>
<% end %>
<div><%= f.submit "Sign up" %></div>
<% end %>

Rails4 Displaying Nested Form saves only one row

I need a form that allows users to accept 4 set of inputs to invite four users into an entity. The following is the code.
# GET /company_members/new
def new
#company_member = CompanyMember.new
#company_member.company_members.build
end
# POST /company_members
# POST /company_members.json
def create
#company_member = CompanyMember.new(company_member_params)
#company_member.user_id = 1
#company_member.company_id = 1
respond_to do |format|
if #company_member.save
format.html { redirect_to #company_member, notice: 'Company member was successfully created.' }
format.json { render action: 'show', status: :created, location: #company_member }
else
format.html { render action: 'new' }
format.json { render json: #company_member.errors, status: :unprocessable_entity }
end
end
end
Form:
<%= form_for(#company_member) do |f| %>
<!--<% if #company_member.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#company_member.errors.count, "error") %> prohibited this company_member from being saved:</h2>
<ul>
<% #company_member.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>-->
<%= f.fields_for #company_member do |yes| %>
email: <%= yes.text_field :email %> role: <%= yes.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<% end %><br>
<%= f.fields_for #company_member do |yes| %>
email: <%= yes.text_field :email %> role: <%= yes.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<% end %><br>
<%= f.fields_for #company_member do |yes| %>
email: <%= yes.text_field :email %> role: <%= yes.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<% end %>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
<%= show_errors(#company_member, :email) %>
</div>
<!--<div class="field">
<%= f.label :company_id %><br>
<%= f.collection_select :company_id, Company.all, :id, :name %>
</div>-->
<div class="field">
<%= f.label :company_member_role_id %>
<%= f.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<%= show_errors(#company_member, :company_member_role_id) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It just saves one Row in the Database while it has to save 4 rows. Also is there a way to remove the un filled rows if any?

Ruby: Use f.select or f.text_field if "other" is chosen in f.select

I need ruby to either take the value from an f.select or an f.text_field if 'other' is chosen in the select form. how is this possible?
in the view:
<div class="field">
Parent</br>
<% f.label :parent1 %>
<%= select("jobs","parent1_id",["None","8.5x11","shells"]) %>
Other:
<% f.label :parent2 %>
<%= text_field("jobs","parent2_id") %>
</div>
in the controller:
def create
#job = Job.new(params[:job])
if params[:parent1_id] == "None" #params[:option1_id].nil? #params.has_key?(:option1_id) #Take your pick
#job.parent = params[:parent2_id]
else
#job.parent = params[:parent1_id]
end
respond_to do |format|
if #job.save
format.html { redirect_to #job, :notice => 'Job was successfully created.' }
format.json { render :json => #job, :status => :created, :location => #job }
else
format.html { render :action => "new" }
format.json { render :json => #job.errors, :status => :unprocessable_entity }
end
end
end
The simplest way around the problem would be to use {:include_blank => "none"} in the select, and check if its parameter is null in the controller, if it is then use the other parameter.
How I personally used it:
<%= form_for #thing, :html => { :class => 'form-horizontal' } do |f| %>
.....
<div class="field">
<%= f.label :name %><br />
<%= select_tag "count", "<option>None</option><option>8.5x11</option><option>shells</option>".html_safe %>
</div>
<div class="field">
<%= f.label :name %><br />
<%= text_field_tag "users" %>
</div>
........
<div class="form-actions">
<%= f.submit "Submit", :class => 'btn btn-primary' %>
.......
</div>
<% end %>
Note collection_select is a variation on select where I pass in another model's items.
In the controller:
def create
.......
if params[:option1_id] == "" #params[:option1_id].nil? #params.has_key?(:option1_id) #Take your pick
#thing.attribute = params[:option2_id]
else
#thing.attribute = params[:option1_id]
else
end

Resources