Rails: Errors close to particular fields in forms - ruby-on-rails

I am trying to add some errors to a form close to the field that caused the error and here is how I am doing this:
<%= lesson_form.text_field :description %><br />
<% unless #lesson.errors[:description].blank? %>
<span id="error_explanation">
Description <%= #lesson.errors[:description].join(", ") %>
</span>
<% end -%>
<%= lesson_form.label :category %>
<%= lesson_form.text_field :category %><br />
<% unless #lesson.errors[:category].blank? %>
<span id="error_explanation">
Category <%= #lesson.errors[:category].join(", ") %>
</span>
<% end -%>
I would like to know if there is a better an non repetitive way of doing this. As you see I am repeating the same unless errors... for each of the fields.

Use a helper method:
def errors_for(model, attribute)
if model.errors[attribute].present?
content_tag :span, :class => 'error_explanation' do
model.errors[attribute].join(", ")
end
end
end
And in view:
<%= lesson_form.text_field :description %><br />
<%= errors_for #lesson, :description %>
<%= lesson_form.label :category %>
<%= lesson_form.text_field :category %><br />
<%= errors_for #lesson, :category %>
<% end %>
Or you could use simple_form which will do it all for you like this:
<%= simple_form_for #lesson do |f| %>
<%= f.input :description %>
<%= f.input :category %>
<%= f.button :submit %>
<% end %>
And if you use simple_form and haml, things look a bit neater:
= simple_form_for #lesson do |f|
= f.input :description
= f.input :category
= f.button :submit
The above will show the error next to the field and will detect type of the attribute and show the appropriate input box (eg text, password, checkbox etc.), all with one simple line f.input.

Related

How to put nested fields_for code directly in parent _form?

How can I rewrite the code in duels/_form so I can put the code from dueler_fields directly in there?
duels/_form
<%= simple_form_for(#duel) do |f| %>
<%= f.text_field :consequence %>
<%= f.text_field :reward %>
<%= f.fields_for :duelers do |dueler| %>
<%= render 'dueler_fields', :f => dueler %>
<% end %>
<%= link_to_add_association f, :duelers do %>
<span class="glyphicon glyphicon-plus"></span> Dueler
<% end %>
<% end %>
_dueler_fields
# I want to place these two lines of code in the _form
<%= f.number_field :user_id, placeholder: "Enter User ID" %>
<%= f.number_field :challenge_id, placeholder: "Enter Challenge ID" %>
duels_controller
def new
#duel = Duel.new
respond_with(#duel)
end
duels has_many duelers.
change f to dueler and you should be good to go. or:
<%= simple_form_for(#duel) do |f| %>
<%= f.text_field :consequence %>
<%= f.text_field :reward %>
<%= f.fields_for :duelers do |dueler_form| %>
<%= dueler_form.number_field :user_id, placeholder: "Enter User ID" %>
<%= dueler_form.number_field :challenge_id, placeholder: "Enter Challenge ID" %>
<% end %>
<% end %>

Gem dragonfly. How to make the list of current files on edit view?

I have model Project and in model have field documents(files). I am using gem dragonfly. When editing a project, how to make the list of current files? At this time on the edit page the list of files fields show: "The file is not selected". I do next: ​
projects_controller:
def edit
end
def update
if #project.update(project_params)
redirect_to #project
else
render :edit
end
end
private
def set_project
#project = Project.find(params[:id])
end
def set_payment_types
#payment_types = PaymentOption.all
end
def project_params
params.require(:project).permit(:title, :description, :price, :location,
:anonymity, :price_category, :category_id, :skill_list, documents_attributes: [:attachment], payment_option_ids: [])
end
edit.html.erb:
<%= form_for #project do |f| %>
<p>
<%= f.label 'Name' %>
<%= f.text_field :title %>
</p>
<P>
<%= f.label 'Budget' %>
<%= f.text_field :price %>
für
<%= f.select :price_category, Project::PRICE_CATEGORIES %>
</P>
<p>
<%= f.label 'Description' %>
<%= f.text_area :description %>
</p>
<p>
<%= f.label 'Category' %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
</p>
<p>
<%= f.label 'Skills Freelancer (15 pieces) *' %>
<%= f.text_field :skill_list %>
</p>
<p>
<%= f.label 'Location' %>
<%= f.text_field :location %>
</p>
<ul>
<% #payment_types.each do |type| %>
<li><%= check_box_tag 'project[payment_option_ids][]', type.id %>
<%= type.name %>
</li>
<% end %>
</ul>
<p>
<b>Anonymity order</b>
</p>
Setup allows for players to remain anonymous. Note that this may reduce the number of responses.
<p>
<%= f.label 'Place Order anonymously' %>
<%= f.check_box :anonymity %>
</p>
<p>
<%= f.fields_for :documents do |d| %>
<%= render 'document_fields', f: d %>
<% end %>
<div class="links">
<%= link_to_add_association 'add file', f, :documents %>
</div>
</p>
<P>
<%= f.submit 'Edit' %>
</P>
<% end %>
​_document_fields.html.erb:
<div class="nested-fields">
<%= f.label :attachment %>
<%= f.file_field :attachment %>
<%= link_to_remove_association "remove file", f %>
</div>
document.rb
class Document < ApplicationRecord
belongs_to :project
dragonfly_accessor :attachment
end
On the edit page the list of files fields show: "The file is not selected", but must be specified ​current files.
file_field is for uploading new files only, not for displaying what is already in the database. For displaying a list of uploaded files, you should just display the name of the file and/or an image tag with the thumbnail and provide a destroy link.
You can also provide a link to create a new attachment.
edit.html.erb
<div>
<ul>
<%= #project.documents.each do |document| %>
<li>
<%= document.attachment.name %>
<%= link_to "Delete", document_path(document), method: :delete, data: { confirm: 'Are you sure you want to delete this?' } %>
</li>
<% end %>
</ul>
<div class="links">
<%= link_to_add_association 'add file', f, :documents %>
</div>
</div>

Extend forms without page reload, rails

I'm searching for a solution to extend my form without page reload.
First I tried to render a partial with coffee or javascript, but escape_javascript didnt work.
Here's the view
<%= form_for #recipe = current_user.recipes.build do |f| %>
<%= f.label :name, "Recipe Name" %>
<%= f.text_field :name %>
<%= button_to "Add Ingredient", '#', class: "btn btn-lg btn-primary", id: "add" %>
<p></p>
<%= f.submit class: "btn" %>
<% end %>
The form above should be extented with following partial by every click on the button
<div id="recipe-ingredients">Quantity
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= render 'quantity_fields', f: quantity %>
<% end %>
</div>
_quantity_fields
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
This approach did not work (recipes.js.erb)
$(document).ready(function() {
$("#add").click(function() {
$("p").append("<%= escape_javascript
render(:partial => 'quantities') %>");
});
});
There's a workaround (see below) but I'm searching for a better solution.
$(document).ready(function() {
$("#workout-week").append(<%= escape_javascript(
Haml::Engine.new(File.read(File.join(Rails.root,'app/views',
'_show_period.html.haml'))).render(Object.new, period: #period)) %>);
});
A second approach is to write following lines in Coffee or JavaScript:
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
<% end %>
I'm a newbie so take this with a grain of salt, but have you tried using render :foo instead of redirect_to :foo in the appropriate controller function?
I solved it with cocoon
<%= form_for #recipe do |f| %>
<div class="field">
<%= f.label :name %>
<br/>
<%= f.text_field :name %>
<%= f.fields_for :quantities do |quantity| %>
<%= render 'quantity_fields', :f => quantity %>
<% end %>
<div class="links">
<%= link_to_add_association 'add', f, :quantities %>
</div>
</div>
<%= f.submit %>
<% end %>

Conditional logic in simple_form not working in Ruby?

Trying to include conditional logic within my form. If the user choose a certain type, then information shows up that is associated with that type. How can I make this happen within the form?
<%= simple_form_for #post do |f| %>
<%= f.input :title %>
<%= f.input :image %>
<%= f.input :description %>
<%= f.input :link %>
<%= f.collection_select :typeof, Post::TYPEOFS, :to_s, :humanize %>
<% if #post.typeof.include?('audio') %>
<p>Audio Selected</p>
<% else %>
<p>Something else selected</p>
<% end %>
<%= f.input :typeof %>
<%= f.input :approve %>
<%= f.button :submit, "Submit", class: "button" %>
<% end %>

rails form_for nested data doesnt show up

New to rails and getting confused on how to handle this. I am using rails 4. I am very stuck here and will try to talk through this problem.
I have a listings page which I am trying to add tags too. In my view (listings/new.html.erb) I have the following:
<h1> POST A NEW LISTING </h>
<% if current_user.nil? %>
<h2>You must be logged in to view this page </h2>
<% else %>
<%= form_for [#user, #listing] do |f| %>
<%= f.label :title, 'Title' %> <br />
<%= f.text_field :title %>
<%= f.label :general_info, 'General Information' %> <br />
<%= f.text_area :general_info %>
<%= f.label :included, 'Included' %> <br />
<%= f.text_field :included %>
<%= f.label :length, 'Length' %> <br />
<%= f.text_field :length %>
<%= f.label :price, 'Price' %> <br />
<%= f.text_field :price %>
<% fields_for #tagging do |u| %>
<%= u.label :tag, 'Tag' %> <br />
<%= u.text_field :tag %>
<% end %>
<%= f.submit "submit" %>
<% end %>
<% end %>
The form works correctly for putting in the listing, but the tagging form options do not even appear to allow for content.
my listings_conroller #new looks like this:
def new
if (!current_user.nil?)
#user = User.find(current_user.id)
#listing = #user.listings.build
#tagging = #listing.taggings.build
end
end
I want to be able to create a new listing with this form that also populates the database for the tags and I am very unsure on how to do this. I hope this is enough information, but if needed I have all the code here: https://bitbucket.org/r-s/ath/src . Very stuck on this any help would be appreciated.
Change it to:
<%= f.fields_for #tagging do |u| %>
Note the =.
You forgot to use builder:
<%= f.fields_for #tagging do |u| %>

Resources