attempting to use this railscast as a guide:
http://railscasts.com/episodes/197-nested-model-form-part-2?view=asciicast
and running into this error:
`#search[queries_attributes][new_queries][queries' is not allowed as an instance variable name
models:
#search.rb
class Search
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :user
field :name, :type => String
embeds_many :queries
accepts_nested_attributes_for :queries, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
#query.rb
class Query
include Mongoid::Document
field :columns, :type => String
field :types, :type => String
field :keywords, :type => String
embedded_in :search, :inverse_of => :queries
end
searches controller :
def new
#search = Search.new
#search.queries.build
#3.times { #search.queries.build }
end
_form.html.haml partial:
= form_for(#search) do |f|
= f.label 'Name this search'
= f.text_field :name, :class => 'text_field'
= render :partial => 'query', :collection => #search.queries, :locals => { :f => f }
= link_to_add_fields "Add Query", f, :queries
.actions
= f.submit
_query.html.haml partial:
.fields
= f.fields_for "queries[]", query do |q|
= q.label 'Search Datatype'
= q.select :types, Query::TYPES
= q.label 'In Column'
= q.select :columns, #search.record_columns
= q.label 'For Keywords:'
= q.text_field :keywords, :class => 'text_field'
= q.hidden_field :_destroy
= link_to_function "remove", "remove_fields(this)"
searches helper:
module SearchesHelper
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize , :f => builder)
end
link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
end
end
javascript:
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g");
$(link).parent().before(content.replace(regexp, new_id));
}
when the line:
= link_to_add_fields "Add Query", f, :queries
is commented out, it works as expected, but I need to be able to add additional queries
via this helper.
for testing multi queries I am triggering the creation in the controller 3.times
also in the error message the last "]" is stripped off.. not sure what I am missing
sorry for all the tags, but not sure where the issue lies
looks like this was the fix:
= f.fields_for :queries, query do |q|
Two thoughts:
I would name the Query class something else, it probably conflicts with some stuff inside mongoid as per the error message you specified:
#search[queries_attributes][new_queries][queries' is not allowed as an instance variable name]
Also googling your problem I came across this:
http://www.jtanium.com/2009/11/03/rails-fields_for-is-not-allowed-as-an-instance-variable-name/
Something must be nil where it shouldn't be.
Related
I have a nested model form with parent Foo and child Bar.
I followed http://railscasts.com/episodes/196-nested-model-form-revised through getting this setup for me. It was worked great. I can add and delete Bars easily, through javascript (per the railscast)
Background:
I have a required field of "name" in Bar.
Problem:
If the user leaves the name field blank and then deletes that Bar (through javascript), it does not let me save the form. I do not get any sort of notification. I believe because of the client side validation has kicked it on the required field that I deleted, the form won't let me submit to the server.
Foo.rb
validates :title, presence: true
has_many bars
accepts_nested_attributes_for :workouts, :allow_destroy => true
Bar.rb
validates :name, presence: true
views/foos/_form.html.haml
= simple_form_for(#foo) do |f|
.form_inputs
= f.input :title
= f.simple_fields_for :bars do |p|
= render "bar_fields", f: p
%br
= link_to_add_fields "Add Bar", f, :bars
%br
= f.button :submit
views/foos/_bar_fields.html.haml
%h4 Bar
= f.input :name
= f.input :description
= f.hidden_field :_destroy
= link_to "Delete Bar", '#'
helpers/application_helper.rb
def link_to_add_fields(name, f, association, css_class = "add_fields btn btn-sm btn-info icon-plus")
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: css_class, data: {id: id, fields: fields.gsub("\n", "")})
end
application.js
function remove_fields_(link) {
$(link).prev("input[type='hidden']").val("true");
$(link).closest(".fields").hide();
}
What am I doing wrong? Any workaround?
Don't see 'accepts_nested_attributes_for :bars' in your code example, be sure you use this.
For a certain employee I have a report. Each report has some shifts. Each shift can be corrected. I am migrating from Ruby 2 to Ruby 3. I am working with partial pages. When I click on Correct, a partial page appears, when I click on Update, page should go back to the partial page Details with the ID of that employee.
_modify_item.html.erb:
<%= form_for :modified_item, :url => {:action => :modify_item, :report_id => #monthly_report.id, :modified_item_id => #modified_item.id,remote: true} do |form| %>
<table width=100% height=100%>
<td width=150 style='border: 0px; background-color: #eee' align=center>
<%= form.hidden_field :report_id, :value => #monthly_report.id %>
<%= submit_tag 'Update', :name => 'update', :value => 'Update', :class => 'highlighted_button' %>
<%= link_to 'Cancel',
{:action => 'details', :report_id => #monthly_report.id},
:class => 'highlighted_button',
remote: true %>
</td>
</tr>
</table>
<% end %>
controller.rb:
def modify_item
#modified_item = Employee::MonthlyReportItem.find(params[:modified_item_id])
#monthly_report = #modified_item.report
begin
#modified_item.update_attributes!(params[:modified_item])
flash[:notice] = 'Position was updated.'
flash[:warning]=#modified_item.verification_problems if !#modified_item.correct?
redirect_to('/accounts/salary/details', :report_id => #monthly_report.id) and return
rescue Exception => e
flash.now[:error] = "Some of the values are missing or are incorrect. Try again."
end
#render(:partial => 'details') and return
end
modify_item.js.erb: (tried didn't succeed)
//$("#salary_popup").html("<%= j(render partial: 'details') %>");
Update: Forgot to mention the exact error which points inside of the if
Couldn't find Employee::MonthlyReport without an ID
Rails goes into details function and tries this:
def details
if params[:item].nil?
#monthly_report = Employee::MonthlyReport.find(params[:report_id])
else
#monthly_report = Employee::MonthlyReport.find(params[:item][:report_id])
end
..
end
Does the hidden field you create have the name attribute? If not trying adding that.
I am in the early stages of creating an app, and am just putting some basic code in place. Here is the current code...
app/views/cards/front.html.erb
<%= form_for(front_of_card_path) do |f| %>
<%= f.fields_for :competency_templates do |builder| %>
<%= render 'add_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Add New Tag", f, :skill %>
<% end %>
routes
controller :cards do
get '/front', action: 'front', as: 'front_of_card'
post '/save', action: 'create', as: 'save_card'
get '/my_contact_info', action: 'back', as: 'back_of_card'
put '/save', action: 'update', as: 'save_card'
get '/my_card', action: 'show', as: 'card'
end
controller
def create
#skill= Skill.new(params[:skill])
#tag = Tag.new(params[:tag])
#tag.save
#skill.tag_id = #tag.id
#skill.save
redirect_to front_of_card_path, notice: 'Skill was successfully created.'
#get user/session
#save skills & tags
end
cards.js.coffee
jQuery ->
$('form').on 'click', '.remove_fields', (event) ->
$(this).prev('input[type=hidden]').val('1')
$(this).closest('fieldset').hide()
event.preventDefault()
$('form').on 'click', '.add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()
app_helper
module ApplicationHelper
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
end
So right now this code gives me two text fields. One for the a tag name and another for a tag weight, and the controller inserts everything in the DB. I would like use some javascript to dynamically add as many of these tag/weight fields as I like. Everything I've found seems to focus on nested attributes. Any ideas appreciated.
Update
Added more code to flesh this out. The issue I am having is the 3rd variable I am passing in on this line...
<%= link_to_add_fields "Add New Tag", f, :skill %>
It does not like ':skill', but I am not sure what I should be passing here.
So here is what I came up with...here are my two models...
class Skill < ActiveRecord::Base
belongs_to :tag
attr_accessible :tag_id, :weight
end
class Tag < ActiveRecord::Base
has_many :skills
attr_accessible :name
end
I'm calling a partial from app/views/skills/_form.html.erb and using a js tag to add new fields. Also note that I am re-rendering the partial, then hiding it in the last div tag.
<div id="skillSet">
<%= render partial: "skills_form" %>
</div>
Add New Tag
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<div class="hide" id="new_skills_form">
<%= render partial: "skills_form", locals: {skill: false} %>
</div>
The partial is pretty simple. All I am doing here is storing the values in an array...
<div class="skillsForm">
<%= label_tag 'tag' %>
<%= text_field_tag 'tags[]' %>
<%= label_tag 'weight' %>
<%= text_field_tag 'weights[]' %>
</div>
...here is the javascript...real straight forward, just say when #addNewTag is clicked, appeand #new_skills_form to #skillSet
$(document).ready(function(){
$("#addNewTag").click(function(){
$("#skillSet").append($("#new_skills_form").html());
});
});
...and finally the controller action decontructs the arrays, and saves them...
def create
#skill = Skill.new(params[:skill])
tags = params[:tags]
weights = params[:weights]
tags.each_with_index do |tag, index|
tag = Tag.create :name => tag
Skill.create :tag_id => tag.id, :weight => weights[index]
end
end
Hey I´m following the Railscast #196,197 from Ryan Bates (http://railscasts.com/episodes/197-nested-model-form-part-2) for nested forms, but it didn´t work.
my model:
class Book < ActiveRecord::Base
attr_accessible :abstract, :status, :titel, :user_tokens, :chapters_attributes, :user_ids
has_and_belongs_to_many :users
attr_reader :user_tokens
has_many :chapters, :dependent => :destroy, :autosave => true, :order => 'slot'
validates :titel, :presence => true
accepts_nested_attributes_for :chapters, :allow_destroy => true
after_initialize :init
def init
self.status = false if self.status?
end
def user_tokens=(ids)
self.user_ids = ids.split(",")
end
end
the partial _chapter_fields.erb :
<div class="fields">
<%= f.label :chapter_title, "Chapter Title" %>
<%= f.text_field :chapter_title %>
<%= f.hidden_field :_destroy %>
<%= link_to_remove_fields "remove", f %>
</div>
the _form :
<p><%= f.label :chapters, "Chapters:" %></p>
<%= f.fields_for :chapters do |builder| %>
<%= render "chapter_fields", :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add chapter", f, :chapters , [] %></p>
the application_helper.rb :
module ApplicationHelper
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
end
def link_to_add_fields(name, f, association, attributes)
if(attributes.size == 0)
new_object = f.object.class.reflect_on_association(association).klass.new
else
new_object = f.object.class.reflect_on_association(association).klass.new(attributes)
end
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
end
end
the application.js :
//= require jquery
//= require jquery_ujs
//= require_tree .
function remove_fields(link) {
$(link).previous("input[type=hidden]").value = "1";
$(link).up(".fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g");
$(link).up().insert({
before: content.replace(regexp, new_id)
});
}
Everything is exactly like the tutorial... what am I missing???
I found the same Question but without answer...
same Question
thats my firebug output:
<a rel="nofollow" data-method="delete" data-confirm="Are you sure?" href="/books/6">Destroy</a>
i have followed the railscasts episode on nested forms(part 1 and 2) and having difficulty with adding fields using jquery, however when i click the remove fields link, the field gets removed.
Here is the code.
In my question model i have
class Question < ActiveRecord::Base
has_many :tags, :class_name => "Tag", :dependent => :destroy, :foreign_key => "question_id"
accepts_nested_attributes_for :tags, :reject_if => lambda { |a| a[:keyword].blank? }, :allow_destroy => true
In my tag model i have
class Tag < ActiveRecord::Base
attr_accessible :keyword, :question_id
belongs_to :question, :class_name => "Question", :foreign_key => 'question_id'
end
In my question form i have
<%= form_for #question, :url => { :controller => "questions", :action => "create" } do |f| %>
<%= f.label(:name, "Request Question:") %>
<%= f.text_field(:name, :size => 72, :maxlength => 120) %><br />
<%= f.fields_for :tags, :url => { :controller => "tags", :action => "create" } do |builder| %>
<%= render "tag_fields", :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add new tag", f, :tags %></p>
<% end %>
In my tag_fields partial
<p class="fields">
<%= f.label(:keyword, "Keywords:") %>
<%= f.text_field(:keyword, :size => 20, :maxlength => 25) %>
<%= link_to_remove_fields "remove", f %>
</p>
In application_helper.rb
module ApplicationHelper
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
end
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
end
end
Then finally in my application.js
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
I have checked to see if files are included in page source. The jquery works because
other parts of my app are working. I do not get any error when i click add new tag.
I have looked at other solutions, but none work for me. I cannot seem to add a field.
Thanks for the help
I managed to figure this on out, but i am not sure if it is the best way.
In application_helper.rb i changed the following line from this
link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
to this
link_to_function(name, "add_fields(this, '#{association}', '#{escape_javascript(fields)}')", :remote => true)
i am not 100% sure why it works, but i believe its got to do with rails 3 no longer having the link_to_function. Hope this help