I'm attempting to use the cocoon gem to created some nested forms mixed with simple form and I get getting Undefined method simple_field_for when I implement the form. I'm fairly new to rails so I apologize in advance if this is a stupid fix but I've scanned Stack Overflow and Google long enough where I've decided to just post and ask. The tutorial I'm following uses haml in the views. Below is my code, please let me know if something else needs to be posted to assist with the error. Thank you!
Total Error Message:
undefined method `simple_field_for' for #<#<Class:0x007fa76a658768>:0x007fa76a962d50>
.row
.col-md-6
%h3 Ingredients
#ingredients
= f.simple_field_for :ingredients do |ingredient| #this is the line throwing the error
= render 'ingredients_fields', f: ingredient
.links
= link_to_add_association 'Add Ingredient', f, :ingredients, class: 'btn btn-default add-button'
Partial File Throwing The Error: _form.html.haml
= simple_form_for #recipe, html: { multipart: true } do |f|
- if #recipe.errors.any?
#errors
%p
= #recipe.errors.count
Prevented this recipe from saving.
%ul
- #recipe.errors.full_messages.each do |msg|
%li= msg
.panel-body
= f.input :title, input_html: { class: 'form-control' }
= f.input :description, input_html: { class: 'form-control' }
= f.input :image, input_html: { class: 'form-control' }
.row
.col-md-6
%h3 Ingredients
#ingredients
= f.simple_field_for :ingredients do |ingredient|
= render 'ingredients_fields', f: ingredient
.links
= link_to_add_association 'Add Ingredient', f, :ingredients, class: 'btn btn-default add-button'
= f.button :submit, class: 'btn btn-primary'
Ingredient Field Partial: _ingredients_fields.html.haml
.form-inline.clearfix
.nested-fields
= f.input :name, input_html: { class: 'form-input form-control' }
= link_to_remove_association "Remove", f, class: 'form-button btn btn-default'
Again, let me know if any other files need to be included. Thank you!
Its simple_fields_for, not simple_field_for. You are missing s.
Read Simple Form Documentation for more info.
Related
I want to have form for possible answers in poll and two submit buttons. First one passing all text fields, second one passing one of these fields as nil causing validation error. This is my _form.html.haml file:
= form_for [#poll, #question] do |f|
- if #question.errors.any?
#error_explanation
%h2= "#{pluralize(#question.errors.count, "error")} prohibited this question from being saved:"
%ul
- #question.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :title
= f.text_field :title
%p
= f.label :kind
.radio
-#kind_options.each do |option|
%label
=f.radio_button :kind, option[1]
=option[0]
=f.fields_for :possible_answers do |c|
%p
=c.text_field :title, class: "form-control", placeholder: "Enter a possible answer"
.actions
= f.submit 'Save', class: "btn btn-primary"
- x = f
= x.hidden_field :kind, :value => nil
= x.submit 'Corrupted Sumbit Button', class: "btn btn-primary"
It seems that there is no difference if I submit x or f, :kind is blank even I choose it in radio button and click on f.submit button. How to work this out?
I'm fairly new to rails and I'm attempting to use cocoon and simple_form together to created some nested forms for a recipe app tutorial I'm following. They use haml and I get a missing partial error when I seem to have followed the proper indentation process for haml.
Error Message:
Missing partial recipes/_ingredient_fields, application/_ingredient_fields with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :haml, :jbuilder]}.
.row
.col-md-6
%h3 Ingredients
#ingredients
= f.simple_fields_for :ingredients do |ingredient|
= render 'ingredients_fields', f: ingredient
.links #line below is the error line
= link_to_add_association 'Add Ingredient', f, :ingredients, class: 'btn btn-default add-button'
= f.button :submit, class: 'btn btn-primary'
If I tab over my .links and link_to_add_association line over, the view will show but the ingredient buttons and text areas will not show. I'm following the procedure stated in the cocoon documention (https://github.com/nathanvda/cocoon) but I can't seem to get it to work. Below are the full code for each files. Please tell me if I need to include any other files. Thanks in advance for the help!
_form.html.haml
= simple_form_for #recipe, html: { multipart: true } do |f|
- if #recipe.errors.any?
#errors
%p
= #recipe.errors.count
Prevented this recipe from saving.
%ul
- #recipe.errors.full_messages.each do |msg|
%li= msg
.panel-body
= f.input :title, input_html: { class: 'form-control' }
= f.input :description, input_html: { class: 'form-control' }
= f.input :image, input_html: { class: 'form-control' }
.row
.col-md-6
%h3 Ingredients
#ingredients
= f.simple_fields_for :ingredients do |ingredient|
= render 'ingredients_fields', f: ingredient
.links
= link_to_add_association 'Add Ingredient', f, :ingredients, class: 'btn btn-default add-button'
= f.button :submit, class: 'btn btn-primary'
_ingredients_fields.html.haml
.form-inline.clearfix
.nested-fields
= f.input :name, input_html: { class: 'form-input form-control' }
= link_to_remove_association "Remove", f, class: 'form-button btn btn-default'
Your file is called _ingredients_fields and it's expecting _ingredient_fields (singular ingredient)
The project which I am working in, is developed on Rails using haml markup to views. There is a view with a simple form like this:
= simple_form_for #message, url: [:admin, #request, #message], html: { class: 'form vertical-form} do |f|
= f.input :text, as: :text, input_html: { class: 'form-control', rows: 5 }
%br
= f.input :link_url, input_html: { class: 'form-control'}
%br
- if #message.has_picture_image?
= f.label :image
=link_to #message.picture_image, target: "_blank" do
= image_tag #message.picture_image(:thumb)
= f.file_field :image, class:'imagen-button'
= f.input_field :remove_picture, as: :boolean, inline_label: 'Remove'
%br
.form-actions
= f.submit(t('accept'), class: 'btn btn-large btn-primary')
= link_to(t('cancel'), [:admin, #message.request, #message], class: 'btn btn-large btn-danger')
and in Message model there is the bellow method:
def remove_picture
self.picture.destroy
end
The input_field is used to check if I want to remove the message image if it exists. I understood that input_filed gives me the option to check it so that when I click on accept button, it call the method remove_picture in the Message model. But, before the browser deploys the form, it rise the next error:
undefined method `to_i' for #<Picture:0x007f7675162b58>
Extracted source (around line #39):
37: = image_tag #message.picture_image(:thumb)
38: = f.file_field :image, class:'imagen-button'
39: = f.input_field :remove_picture, as: :boolean, inline_label: 'Remove'
40: %br
41: .form-actions
42: = f.submit(t('accept'), class: 'btn btn-large btn-primary')
and if I reload the page, this time the form is deployed. I guess this is because in the first time, as the picture exists then immediatly the remove_picture is called and the picture removed, and when I reload the form, as the picture already does not exist, the form is shown.
Obviously I am undestanding wrongly the input_field usage.
SimpleForms input_field is a helper which binds an input to a model attribute. It does not create a box which calls your method when the box is ticked! But rather it will call your remove_picture method when it rendering the form.
In some cases like checkboxes you will want to bind inputs to attributes that are not saved in the database. We call these virtual attributes. They are just like any old Ruby attributes:
class Message < ActiveRecord::Base
attr_accessor :remove_picture
# since this method is destructive it should have a bang (!)
def remove_picture!
self.picture.destroy
end
end
You could use it like this:
class MessagesController < ApplicationController
def update
#message.update(update_params)
#message.remove_picture! if message.remove_picture
# ...
end
def update_params
params.require(:message).allow(:remove_picture)
end
end
But there is a better way:
class Message < ActiveRecord::Base
has_one :picture_image
accepts_nested_attributes_for :picture_image, allow_destroy: true
end
accepts_nested_attributes_for lets us create an image with picture_image_attributes and destroy an image with:
#picture.update(picture_image_attributes: { _destroy: true })
This is how we would set up the form:
= simple_form_for #message, url: [:admin, #request, #message], html: { class: 'form vertical-form} do |f|
= f.input :text, as: :text, input_html: { class: 'form-control', rows: 5 }
%br
= f.input :link_url, input_html: { class: 'form-control'}
%br
- if #message.has_picture_image?
f.simple_fields_for :picture_image do |pif|
= pif.label :image
= link_to #message.picture_image, target: "_blank" do
= image_tag #message.picture_image(:thumb)
= pif.file_field :image, class:'imagen-button'
= pif.input_field :_destroy, as: :boolean, inline_label: 'Remove'
%br
.form-actions
= f.submit(t('accept'), class: 'btn btn-large btn-primary')
= link_to(t('cancel'), [:admin, #message.request, #message], class: 'btn btn-large btn-danger')
And your strong parameters whitelist:
def update_attributes
params.require(:message).allow(
:text,
:link_url,
picture_image_attributes: [:image, :_destroy]
)
end
I try to add multipart upload for Carrierwave in my form, but I have two controllers(admin_posts and posts) in one model(post).So I do not understand how to specify this
_form.html.haml
= form_for [:admin, #post] do |f|
= f.fields_for :photos do |photo_fields|
= photo_fields.file_field :image
= f.text_field :title, class: "form-control", placeholder: "Title"
= f.text_area :body, rows: 12, class: "form-control", placeholder: "Body"
.pull-right
= f.submit "Send", class: "btn btn-success"
how fix?
sorry for my English
Try this
= form_for [:admin, #post], url: your_action_path(#post), html: { multipart: true } do |f|
I have a large psychological test of 251 question. Each user can complete that test many times. So I created Summary model to represent each completion. Each Summary has many Answers. For each Summary I created a form that represents collection of answers, using Slim templater and simple_form gem:
= simple_form_for(#summary) do |f|
= f.simple_fields_for :answers do |a|
.question
= a.input :question_id, as: :hidden
div= a.object.question.title
- if a.object.question.kind_of? SpiritualityQuestion
ol class="sortable"
- a.object.question.sortable_variants.each do |sortable_variant|
= content_tag_for :li, sortable_variant
= sortable_variant.title
= a.input :text_data, as: :hidden, input_html: { class: 'sortable_data' }
- elsif a.object.question.kind_of? MultilineQuestion
div Time remaining: <span class="time">60</span> s.
= button_tag 'Start', type: 'button', class: 'start_button btn btn-primary'
= a.input :text_data, label: false, input_html: { class: 'span8 timed_text', cols: '60', rows: '20', disabled: true }
- else
= a.association :variant, collection: a.object.question.variants, as: :radio, label: false
br
= f.input :user_id, as: :hidden
= f.input :psy_test_id, as: :hidden
.actions
= f.button :submit, value: 'Save', class: 'btn btn-large btn-success'
And I have related controller action:
#summary = Summary.where(completed: false, user: current_user, psy_test: PsyTest.first)
.includes(:answers => { :question => :variants })
.first_or_initialize
#summary.build_answers if #summary.new_record?
Summary.build_answers:
def build_answers
# Creating answers for questions
psy_test.questions.includes(:variants).each do |q|
answers.new(question: q)
end
end
Now I'm trying to make the test to be paginated, because it's very large and the form generates very slowly. So I want to add limit and offset to answers. Something like that:
= f.simple_fields_for answers.limit(#limit).offset(#offset) do |a|
How it can be made?
I've looked to do field_for source and found simple answer, which I wasn't able find in any guide:
= f.simple_fields_for :answers, #summary.answers.limit(#limit).offset(#offset) do |a|