I have 3 models, Product, Variation and Color. I'm using the nested_form gem.
Product has_many :variations
Variation belongs_to :product
Variation has_and_belongs_to_many :colors
Color has_and_belongs_to_many :variations
Through Product form I have nested_form for Variations. I want to associate colors through checkbox but receive undefined local variable or method "color_ids"
Product model
def new
#product = Product.new
1.times { #product.variations.build }
end
def create
#product = Product.new(params[:product])
...
end
My form //edited//
<%= nested_form_for(#product) do |f| %>
<% if #product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% #product.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="inline-form">
<%= f.fields_for :variations %>
<p><%= f.link_to_add "Add a variation", :variations %></p>
</div>
<div class="actions">
<%= submit_or_cancel(f) %>
</div>
</div>
<% end %>
And nested form is a basic table with
<table id="new_item">
<tr>
<th>Name</th>
<th>Color</th>
</tr>
<tr>
<td><%= f.text_field :name, :size => 40 %></td>
<td><% for color in Color.all %>
<%= check_box_tag 'variation[color_ids][]', color.id, variation.color_ids.include?(color.id), :id => dom_id(color) %><%= label_tag dom_id(color), color.name, :class => "check_box_label" %>
<% end %>
</td>
</tr>
</table>
I'm guessing that your issue is the part of the form doing color_ids.include?(color.id). I'd need to see the rest of your form erb to tell you how to fix it.
It's going to be something like variation.color_ids.
Another thing to note, that style of for loop is odd to see in typical/idiomatic ruby.
This is more typical:
<% Color.all.each do |color| %>
<%= check_box_tag 'variation[color_ids][]', color.id, color_ids.include?(color.id), :id => dom_id(color) %><%= label_tag dom_id(color), color.name, :class => "check_box_label" %>
<% end %>
Related
I'm trying to create inline radio buttons which also has its label inline (at the very left).
As I state in the title, using Bootstrap and SimpleForm.
My code looks like this:
<%= f.input :breakdown_or_size,
:collection => ["Breakdown", "Manual"],
:as => :radio_buttons,
:item_wrapper_class => 'inline',
:label => 'Select One: ' %>
This is what I get:
(source: webpagescreenshot.info)
I looked high and low for simple_form_for help. In the end I couldn't find anything, but at least with form_for you can do this:
<%= form_for(#book) do |f| %>
<% if #book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#book.errors.count, "error") %> prohibited this book from being saved:</h2>
<ul>
<% #book.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="actions", style='inline'>
<%= f.label 'Select One: ' %>
<br/>
<%= f.radio_button :collection, "Breakdown" %> Breakdown
<%= f.radio_button :collection, "Manual" %> Manual
<br/>
<%= f.submit %>
</div>
Which at least solves the inline rendering.
I was wondering what the syntax is to link to an attribute on the same page
I have a list of dates
<ul>
<% #response.each_pair do |date, movie| %>
<li><%= link_to date_format(date), date, :class => 'scroll_to' %></li>
<% end %>
</ul>
These then have movies underneath each date like so
<% #response.each_pair do |date, movie| %>
<h3 class="resultTitle fontSize13">Available on <%= date_format(date) %></h3>
<% movie.each do |m| %>
<div class="thumbnail clearfix">
<img class="pull-left" src=<% if m.image_link %> <%= m.image_link %> <% else %> "/assets/noimage.jpg" <% end %>>
<div class="caption pull-right">
<%= link_to m.name, m.title_id, :class => 'resultTitle fontSize11' %>
<p class="bio"><%= m.bio %></p>
<p class="resultTitle">Cast</p>
<p class="bio"><%= m.cast.join(", ") unless m.cast.empty? %></p>
<%= link_to "Remind me", reminders_path(:title_id => m.title_id), :method => :post, :class => 'links button' %>
</div>
</div>
<% end %>
<% end %>
What i would like to achieve is that when a user clicks on a date in the list then it will take them to that date with movies on the same page
My attribute for each date is
"release_date"
Do i need to link to that, maybe a piece of Jquery aswell to scroll down to that date? or would it jump to the date in one step?
Any advice appreciated, I have linked to other pages before but not the same page like this
EDIT
I have tried this but the page just re renders
<li><%= link_to date_format(date), params.merge(:release_date => 'release_date'), :class => 'scroll_to' %></li>
Am i on the right track?
Thanks
All you need is to give your date a unique identifier and link to that in you list. For instance below we give the h3 for each date an id relative to the date object. The browser knows how to handle internal links and will simply jump to the corresponding identifier. Notice how the id of the field you're linking to gets appended to the end of the url when you click on the link.
<ul>
<%- index = 0 %>
<% #response.each_pair do |date, movie| %>
<%- index += 1 %>
<li><%= link_to date_format(date), "##{index}", :class => 'scroll_to' %></li>
<% end %>
</ul>
<%- index = 0 %>
<% #response.each_pair do |date, movie| %>
<%- index += 1 %>
<h3 class="resultTitle fontSize13" id="<%= index %>">Available on <%= date_format(date) %></h3>
<% movie.each do |m| %>
<div class="thumbnail clearfix">
<img class="pull-left" src=<% if m.image_link %> <%= m.image_link %> <% else %> "/assets/noimage.jpg" <% end %>>
<div class="caption pull-right">
<%= link_to m.name, m.title_id, :class => 'resultTitle fontSize11' %>
<p class="bio"><%= m.bio %></p>
<p class="resultTitle">Cast</p>
<p class="bio"><%= m.cast.join(", ") unless m.cast.empty? %></p>
<%= link_to "Remind me", reminders_path(:title_id => m.title_id), :method => :post, :class => 'links button' %>
</div>
</div>
<% end %>
<% end %>
For the added JQuery transition you can replace
<li><%= link_to date_format(date), "##{index}", :class => 'scroll_to' %></li>
with
<li><%= link_to_function date_format(date), "$('html, body').animate({scrollTop:$('##{index}').offset().top }, 'slow');", :class => 'scroll_to'%></li>
The above isn't exactly a DRY approach, but the important thing to abstract out of that is that you're linking to a unique ID elsewhere on the page and not the code itself.
I am a beginner working on a RoR app that allows users to update their resume with experiences and education. I have two models for these different items and would like to display them together in chronological order. I want to know how to set this up in my profile controller and view.
I'd like to adopt this same practice to a separate part of the app that will combine post and discussion items from users in the same way. However, currently, my focus is on the experience and education portion.
profiles/show.html.erb:
<% if #experiences.any? or #educations.any? %>
<div class="postExpOuter">
<% #experiences.each do |experience| %>
<div class="postExp">
<div>
<h2><%= experience.position %></h2>
<h3><%= experience.company %> | <%= experience.location %></h3>
<h4>
<%= experience.start_month %> <%= experience.start_year %>
<% if experience.end_year %>
<%= " - " + experience.end_month %> <%= experience.end_year %>
<% else %>
<span> - Present</span>
<% end %>
</h4>
</div>
</div>
<% end %>
<% #educations.each do |education| %>
<div class="postExp">
<div>
<h2><%= education.degree %></h2>
<h3><%= education.school %></h3>
<h4>
<% if education.end_year %>
<span>Class of </span><%= education.end_year %>
<% else %>
<%= education.start_year %><span> - Present</span>
<% end %>
</h4>
</div>
</div>
<% end %>
</div>
<% end %>
just hacked in my browser, don't know if it works directly:
<%- (#experiences.to_a + #educations.to_a).sort_by(&:end_year).each do |item| -%>
<%- if item.is_a? Experience -%>
your markup here...
<%- else -%>
your other markup here...
<%- end -%>
<%- end -%>
haven't written ERB since... uhh, long. basically it's just the following: merge the 2 ActiveRecord-Relations as Arrays into one big Array, sort them by the timestamp you want (you may add .reverse at the end if you want). While iterating through the list, check the type of object you have.
Hope this helps.
profiles_controller.rb:
class ProfilesController < ApplicationController
def show
#user = User.find_by_profile_name(params[:id])
if #user
#posts = #user.posts.all(:order => "created_at DESC", :limit => 3)
#experiences = #user.experiences.all(:order => "start_year DESC")
#educations = #user.educations.all(:order => "start_year DESC")
#items = (#experiences.to_a + #educations.to_a).sort_by(&:start_year).reverse[0,3]
render action: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
end
end
profiles/show.html.erb:
<% if #items.any? %>
<div class="postExpOuter">
<% #items.each do |item| %>
<% if item.is_a? Experience %>
<div class="postExp">
<div>
<h2><%= item.position %></h2>
<h3><%= item.company %> | <%= item.location %></h3>
<h4>
<%= item.start_month %> <%= item.start_year %>
<% if item.end_year %>
<%= " - " + item.end_month %> <%= item.end_year %>
<% else %>
<span> - Present</span>
<% end %>
</h4>
</div>
</div>
<%- else -%>
<div class="postExp">
<div>
<h2><%= item.degree %></h2>
<h3><%= item.school %></h3>
<h4>
<% if item.end_year %>
<span>Class of </span><%= item.end_year %>
<% else %>
<%= item.start_year %><span> - Present</span>
<% end %>
</h4>
</div>
</div>
<% end %>
<% end %>
</div>
<% end %>
I have Category and Products, Category has many product in it. I'm able to Edit Delete Create the Category, Also able to Create Delete Products in the Each Category, but want to Edit the each Product.
I can access the single Product of particular Category by using link_to , and product controller is receiving the the product of particular Category.
In html of Category where all Product belongs of that category has
<%= link_to 'Edit', edit_category_product_path(product.category, product) %>
Controller of Product, edit function is
#product = Product.where(params[:id])
then my edit html is
<%= form_for #product do |f| %>
<% if #product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% #product.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :price %><br />
<%= f.text_field :price %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Back', category_products_path %>
I'm getting this error when try to Edit the product
NoMethodError in Products#edit
Showing C:/Sites/propoolpro6/app/views/products/edit.html.erb where line #3 raised:
undefined method `model_name' for ActiveRecord::Relation:Class
Extracted source (around line #3):
1: <h1>Editing product</h1>
2:
3: <%= form_for #product do |f| %>
4: <% if #product.errors.any? %>
5: <div id="error_explanation">
6: <h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
Rails.root: C:/Sites/propoolpro6
Application Trace | Framework Trace | Full Trace
app/views/products/edit.html.erb:3:in `_app_views_products_edit_html_erb___584392485_32651052'
Request
Parameters:
{"category_id"=>"1",
"id"=>"3"}
Note: i have used this 2, but same error,
<%= form_for(#product) do |f| %>
I think following line create array
#product = Product.where(params[:id])
which could not be used by the form_helper (expecting a Model name generally provided by an ActiveRecord Relation).you can inspect the #product to see the result.
so it is better if you use find instead of where like
#product = Product.find(params[:id])
I hope this answer would help you.
Thanks.
I have a rails3 form that allows the user to edit a list of answers, as part of an assessment.
I use a fields_for loop to generate each text input:
app/models/assessment.rb :
class Assessment < ActiveRecord::Base
serialize :answers, Hash # answers is a t.text field used to store all answers.
end
app/view/assessments/new.html.erb :
<p>Initialized answers: <%= #assessment.answers %></p>
<% item_counter = 0 %>
<% form.fields_for :answers do |answer_fields| %>
<% item_id = "item" + item_counter.to_s %>
<% item_counter = item_counter + 1 %>
<div class="field">
<%= answer_fields.label "the appropriate question, omitted for brevity" %>
<br/>
<% #assessment.answers[item_id] = "" %>
<%= answer_fields.text_field item_id, :value => #assessment.answers[item_id] %>
</div>
<% end %>
PROBLEM: The fields_for loop does zero iteration, no field gets printed.
( despite "Initialized answers:" showing correctly: {"a"=>143, "b"=>42} )
This should do. Tested locally.
<p>Initialized answers: <%= #assessment.answers %></p>
<% #assessment.answers.each do |key, value| %>
<%= form.fields_for :answers, #assessment.answers[key] do |answer_fields| %>
<div class="field">
<%= answer_fields.label key %>
<br/>
<%= answer_fields.text_field key, :value => value %>
</div>
<% end %>
<% end %>
Turns Hash to OpenStruct object solved my problem.
<% form.fields_for :answers, OpenStruct.new(answers) do |answer_fields| %>
<% item_id = "item" + item_counter.to_s %>
<% item_counter = item_counter + 1 %>
<div class="field">
<%= answer_fields.label "the appropriate question, omitted for brevity" %>
<br/>
<% #assessment.answers[item_id] = "" %>
<%= answer_fields.text_field item_id, :value => #assessment.answers[item_id] %>
</div>