Why do my model attributes save out of order? - ruby-on-rails

This happens particularly often when I try and update a model.
I have a quiz app, and I add a quiz using this form:
<%= form_for(#quiz) do |f| %>
<% if #quiz.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#quiz.errors.count, "error") %> prohibited this quiz from being saved:</h2>
<ul>
<% #quiz.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class = 'field'>
<%= f.label :difficulty, "Difficulty of Quiz, 1 to 3 with 3 being most difficult" %>
<%= f.text_field :difficulty %>
</div>
<div class="field">
<%= f.label :for_unsubscribed, "Check to have this quiz be visible to logged in but unsubscribed users" %>
<%= f.check_box :for_unsubscribed %>
</div>
<%= f.fields_for :questions do |question_attribute| %>
<div class = 'inner-c'>
<p>
<%= question_attribute.label :content, "Question" %> <span><b><%= question_attribute.index + 1 %></b></span> <br/>
<%= question_attribute.text_area :content, :cols => 100, :rows => 4 %>
</p>
<p>
<%= question_attribute.label :explanation, "Answer Explanation" %> <br/>
<%= question_attribute.text_area :explanation, :cols => 100, :rows => 6 %>
</p>
<%= question_attribute.label :_destroy, "Remove Question"%>
<%= question_attribute.check_box :_destroy %><br/>
<%= question_attribute.label :passage, "Reference Passage" %> <br/>
<%= question_attribute.text_area :passage, :rows => 3, :class => 'passage-input' %>
<%#= question_attribute.label :question_explanation, "Question Explanation" %>
<%#= question_attribute.text_area :question_explanation, :rows => 10 %>
</p>
<%= question_attribute.fields_for :answers do |answer_attribute| %>
<p>
<%= answer_attribute.label :content, "Answer" %>
<%= answer_attribute.text_field :content %>
<%= answer_attribute.label :correct_answer, "Check to indicate correct answer", :class => 'inline' %>
<%= answer_attribute.check_box :correct_answer, :class => 'inline'%>
</p>
<% end %>
</div> <!-- inner-c -->
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
A new form would be generated by the controller like so:
def new
#quiz = Quiz.new
50.times do
question = #quiz.questions.build
5.times { question.answers.build }
end
end
Taking advantage of using nested models, where a Quiz has_many Questions which has_many Answers.
The problem is -- when I create a quiz (with 50 questions), then I try and update the quiz afterwards, to fix a mistake for example, The questions move out of order. Question 43 and Question 1 might switch places. I absolutely need the questions to stay in the same order after I update them but I can't figure out how to make this happen. Any ideas?

Generally in RDBMS order is not specified by default, unless you explicitly state it. Therefore if you don't specify the order you can get results in any order an that is an expected behaviour.
But according to your description question 43 swapped with question 1 after an update, so I can think you are ordering them by an updated_at timestamp. Try to order explicitly order questions by id – id is [normally] a PrimaryKey and it never changes, so your questions will stay in order.

Related

How to get model attributes to save in order?

I'm building a quiz app, to create a quiz I do this:
def new
#quiz = Quiz.new
50.times do
question = #quiz.questions.build
5.times { question.answers.build }
end
end
enter code here
Which uses nested parameters. The problem is, sometimes the quiz doesn't save in order (such as when I create a new quiz OR I update an existing quiz). If I create a quiz in particular order, say Question 1, Question 2, Question 3, I want the questions in that quiz to remain in the same order after I update or create it. Right now, if I update a quiz the order gets jumbled up if I want to show the quiz using something like quiz.questions.each do |question|
I wasn't aware that ruby databases don't enforce order, so how do I make sure that if I create a quiz, the order in which I enter the questions (top to bottom) will always be the order that the questions are presented in?
If you are interested, this is the form I use to create the quiz:
<%= form_for(#quiz) do |f| %>
<% if #quiz.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#quiz.errors.count, "error") %> prohibited this quiz from being saved:</h2>
<ul>
<% #quiz.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class = 'field'>
<%= f.label :difficulty, "Difficulty of Quiz, 1 to 3 with 3 being most difficult" %>
<%= f.text_field :difficulty %>
</div>
<div class="field">
<%= f.label :for_unsubscribed, "Check to have this quiz be visible to logged in but unsubscribed users" %>
<%= f.check_box :for_unsubscribed %>
</div>
<%= f.fields_for :questions do |question_attribute| %>
<div class = 'inner-c'>
<p>
<%= question_attribute.label :content, "Question" %> <span><b><%= question_attribute.index + 1 %></b></span> <br/>
<%= question_attribute.text_area :content, :cols => 100, :rows => 4 %>
</p>
<p>
<%= question_attribute.label :explanation, "Answer Explanation" %> <br/>
<%= question_attribute.text_area :explanation, :cols => 100, :rows => 6 %>
</p>
<%= question_attribute.label :_destroy, "Remove Question"%>
<%= question_attribute.check_box :_destroy %><br/>
<%= question_attribute.label :passage, "Reference Passage" %> <br/>
<%= question_attribute.text_area :passage, :rows => 3, :class => 'passage-input' %>
<%#= question_attribute.label :question_explanation, "Question Explanation" %>
<%#= question_attribute.text_area :question_explanation, :rows => 10 %>
</p>
<%= question_attribute.fields_for :answers do |answer_attribute| %>
<p>
<%= answer_attribute.label :content, "Answer" %>
<%= answer_attribute.text_field :content %>
<%= answer_attribute.label :correct_answer, "Check to indicate correct answer", :class => 'inline' %>
<%= answer_attribute.check_box :correct_answer, :class => 'inline'%>
</p>
<% end %>
</div> <!-- inner-c -->
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

I'm missing an attribute that needs to be permitted

I know I'm missing something, but I can't figure out what.
It's quite nested. I have a quiz which has_many questions which has_many answers. Answers belongs_to Questions which belongs_to a Quiz.
What I have so far:
params.require(:quiz).permit(:name, questions_attributes: [:content, :quiz_id, :explanation, :passage, answers_attributes: [:content, :question_id, :correct_answer]])
My form:
<%= form_for(#quiz) do |f| %>
<% if #quiz.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#quiz.errors.count, "error") %> prohibited this quiz from being saved:</h2>
<ul>
<% #quiz.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= f.fields_for :questions do |question_attribute| %>
<div class = 'inner-c'>
<p>
<%= question_attribute.label :content, "Question" %> <span><b><%= question_attribute.index + 1 %></b></span> <br/>
<%= question_attribute.text_area :content, :cols => 100, :rows => 4 %>
</p>
<p>
<%= question_attribute.label :explanation, "Answer Explanation" %> <br/>
<%= question_attribute.text_area :explanation, :cols => 100, :rows => 6 %>
</p>
<%= question_attribute.label :_destroy, "Remove Question"%>
<%= question_attribute.check_box :_destroy %><br/>
<%= question_attribute.label :passage, "Reference Passage" %> <br/>
<%= question_attribute.text_area :passage, :rows => 3, :class => 'passage-input' %>
<%#= question_attribute.label :question_explanation, "Question Explanation" %>
<%#= question_attribute.text_area :question_explanation, :rows => 10 %>
</p>
<%= question_attribute.fields_for :answers do |answer_attribute| %>
<p>
<%= answer_attribute.label :content, "Answer" %>
<%= answer_attribute.text_field :content %>
<%= answer_attribute.label :correct_answer, "Check to indicate correct answer", :class => 'inline' %>
<%= answer_attribute.check_box :correct_answer, :class => 'inline'%>
</p>
<% end %>
</div> <!-- inner-c -->
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

Date is not working in rails application with mongo id

I have create an rails application with mongoid but im facing one problem at DATE
I created an scaffold with a name "posting"
When im editing date it will updated....
I follow the instruction of Railscast #238 Mongoid here
there is my posting.rb file
class Posting
include Mongoid::Document
field :title
field :description
field :comments
field :published, :type => Date
end
this my _from.html.erb
<%= form_for(#posting) do |f| %>
<% if #posting.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#posting.errors.count, "error") %> prohibited this posting from being saved:</h2>
<ul>
<% #posting.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :published %><br>
<%= f.date_select :published %>
</div>
<div class="field">
<%= f.label :comments %><br>
<%= f.text_area :comments %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and finally my show.html.erb file
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= #posting.title %>
</p>
<p>
<strong>Description:</strong>
<%= #posting.description %>
</p>
<p>
<strong>published:</strong>
<%= #posting.published %>
</p>
<p>
<strong>Comments:</strong>
<%= #posting.comments %>
</p>
<%= link_to 'Edit', edit_posting_path(#posting) %> |
<%= link_to 'Back', postings_path %>
What do you mean by not working? doesn't look like you have used published property in any of your views.
in your show.html.erb you are using
<%= f.date_select :pub %>
and in your show.html.erb you are using
<%= #posting.pub %>
However there is no property called pub in your Posting model. What you have there is called published
field :published, :type => Date
You either need to rename it in the model, or in the views to match.

How do I submit one param multiple times on rails?

So I have Users and Interests and they are associated with a has_and_belongs_to_many relation through an interests_users table. What I want to do is to let users select 5 interests when they create their account through checkboxes, but I don't now how to submit the same param 5 times in the same form and I am currently submiting it with checkbox, but Interest is not a boolean. The code right now is like this:
<div class = "field">
<%= f.label :interests %><br>
<% all_interests = Interest.all.map{ |f| [f.name, f.id] } %>
<% all_interests.each do |interest| %>
<p> <%= interest[0] %> <%= f.check_box :interests %> <p>
<% end %>
</div>
In view use the flowing
<% for interest in Interest.all %>
<%= check_box_tag "user[interest_ids][]", interest.id, #user.interests.include?(interest) %>
<%= interest.name %>
<% end %>
In controller accept params as following
params.require(:user).permit( { interest_ids:[] })
You should try this code :
<div class = "field">
<%= f.label :interests %><br>
<% Interest.all.each do |interest| %>
<p> <%= interest.name %> <%= f.check_box :interests, { :multiple => true }, interest.id, nil %> </p>
<% end %>
</div>

Rails how to show on one page existing associated records AND permit new associated record input

My main record is a Plate (as in license plate).
It can have many Translations (meanings or comments).
On one page I want to:
1)show a plate record and allow users to rate the plate
2)show all existing translation records and allow users to vote for one
3)allow the user to create a new translation record
I am using form_for the Plate, and fields_for for the existing translation records.
My research suggests there should be a way to do this, but my code is not delivering a blank form. Currently I am trying a second fields_for loop.
At the moment, I am just focused on my rendered forms page, I have not gotten to processing the input yet.
The final fields_for which is meant to display a blank box for a new translation input, is instead showing the last existing translation.
I will appreciate any suggestions.
Below is my edit form: _rate_or_vote.html.erb
<!-- app/views/plates/_rate_or_vote.html.erb -->
<%= form_for(#plate) do |f| %>
<% if #plate.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#plate.errors.count, "error") %>
prohibited this plate from being updated:</h2>
<ul>
<% #plate.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<h1>Rate the Plate</h1>
<span class="form-group">
<%= f.label :input_rating, "Your Plate Rating" %>
<%= f.select :input_rating, options_for_select(RATINGS) %>
</span>&nbsp&nbsp
<span class="form-group">
<%= f.label :rating, "Average Rating" %>
<%= f.text_field :rating , :value => (number_with_precision(f.object.rating, :precision => 2) || 0) %>
</span>&nbsp&nbsp
<span class="form-group">
<%= f.label :plate_number, "Plate Number" %>
<%= f.text_field :plate_number %>
</span>&nbsp&nbsp
<span class="form-group">
<%= f.label :state, "State" %>
<%= f.text_field :state, class: "form-control" %>
</span><br><br>
<span style="background-color:#DCDCDC; color:#000000; font-style: normal; font-family:Georgia;">
Contributor</span>
<span style="border:1px solid black;padding:3pt;">
<%= #plate.user.full_name %></span>&nbsp&nbsp
<span class="form-group">
<%= f.label :plate_image, "Plate Image File" %>
<%= f.file_field :plate_image %>
</span><br><br>
<h1>Existing Translations and/or Comments - You can vote for one</h1>
<!-- %= f.fields_for :translations do |ff| %-->
<%= f.fields_for :translations, #plate.translations do |ff| %>
<span>Click this box to vote for this translation:</span>&nbsp
<span><%= check_box_tag "translation_ids[]", :id %></span>&nbsp&nbsp
<span><%= ff.label "Current votes" %>
<%= ff.text_field :votes, :value => (number_to_percentage(ff.object.votes / ( #plate.translation_votes.nonzero? || 1 ) * 100,
precision: 0)) %>
</span>&nbsp&nbsp
<span style="background-color:#DCDCDC; color:#000000; font-style: normal; font-family:Georgia;">
Contributor</span>
<span style="border:1px solid black;padding:3pt;">
<%= ff.object.user.full_name %></span><br><br>
<span>Translation and/or Comment</span><br>
<span>
<%= ff.text_area :meaning, :cols => 60, :rows => 10 %>
</span><br><br>
<% end %>
<h1>Offer a new Translation and/or Comment</h1>
<!-- %= f.fields_for :translations do |ff| %-->
<%= f.fields_for :translations, #plate.translations do |fff| %>
<div>
<!-- %= fff.label :meaning, "Translation" %-->
<%= fff.text_field :meaning %>
</div><br><br>
<% end %>
<%= f.submit "Save and/or Return", :name => "update", class: "btn btn-default" %>
ok, so #plate.translations is the set of current translations that are already on the plate.
If you want a fields-for section for a new one... you have to actually build a new one.
eg:
<%= f.fields_for :translations, [#plate.translations.build] do |fff| %>
<div>
<%= fff.text_field :meaning %>
</div><br><br>
<% end %>

Resources