I have created an app, where I require a form to be submitted remotely. If the form does not pass validation, errors need to be displayed. If it is submitted successfully, the for should be cleared. I am using the Reform gem to strip validation logic out of my models.
I have installed the client_side_validations as well as client_side_validations-simple_form gems as per the installation instructions. For some reason though, validation errors are not displaying and I'm not sure why... I've tried all the debugging options I could think of.
Here is my code:
foo_form.rb
class FooForm < ApplicationForm
property :bar, validates: {
presence: true
},client_validations: { class: 'Foo' }
end
foos_controller.rb
def create
#foo = FooForm.new( Foo.new )
respond_to do |format|
if #foo.validate(params[ :foo ])
#foo.save
format.html { redirect_to root_path }
format.json { render :show, status: :created, location: #foo.model }
else
format.html { render :new }
format.json { render json: #foo.errors, status: :unprocessable_entity }
end
end
end
form.haml
= simple_form_for #foo, url: foos_path, as: :foo, remote: true, validate: true do |f|
.input-field
= f.input :bar
.right-align.card-button
= f.button :submit, class: "waves-light blue", data: { disable_with: "Loading..." }
Could anybody help with identifying what I'm missing? Thanks
Related
I have a model with movies and actors and I want both to be taggeable. I know there's a gem for that but I thought I'd teach myself polymorphic associations :)
Basic functionality works (I can do stuff like amovie.tags.create etc...) but now I want forms for movies and actors where tags can be selected and deselected.
Problem : I cannot deselect a tag:
While selecting a tag (that exists) works, when I deselect a tag, I get an error. Here's the relevant code:
Movie Form:
<%= form.collection_select(:tag_ids, Tag.order(:name), :id, :name, {}, { class: 'selectize-tag', multiple: true }) %>
movies controller - update section as well as movies_params private function:
def update
respond_to do |format|
if #movie.update(movie_params)
format.html { redirect_to #movie, notice: "Movie was successfully updated." }
format.json { render :show, status: :ok, location: #movie }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #movie.errors, status: :unprocessable_entity }
end
end
end
def movie_params
params.require(:movie).permit(:title, :runtime, :country, :release_year, :sort_title, tag_ids: [])
end
Error I get:
Mysql2::Error: Column 'taggeable_id' cannot be null
Params - I think the problem is the line that has tag IDs and one of them is ""
{"_method"=>"patch",
"authenticity_token"=>"[FILTERED]",
"movie"=>
{"title"=>"The Avengers",
"sort_title"=>"Avengers",
"release_year"=>"2012",
"country"=>"US",
"runtime"=>"143",
"tag_ids"=>["", "3"]},
"commit"=>"Update Movie",
"id"=>"48"}
So not sure what I need to do for that empty tag id there to not be submitted but rather to trigger "remove tag with ID xyz from movie abc?
I have a ruby on rails app. I added date_field to the view for add/Edit dates. the problem is that I have problem for saving and updating new dates but it brings the date from variable to the form(Edit) and after editting a date and creatine a new date. it doesn't come back to the home page or have problem with saving. as I saw in the console params, my date variable(start) changed when the user select new date but it does not load the first page afterward and I got this error:
F, [2018-02-01T16:03:44.784113 #723] FATAL -- :
NoMethodError (undefined method `year' for nil:NilClass):
app/controllers/weeks_controller.rb:27:in `create'
here is my form page where it shows date to edit:
.form-group
= f.label :course
= #course.name
.form-group.form-inline
= f.label :start
= f.date_field :start, as: :date, value: f.object.try(:strftime,"%m/%d/%Y"), class: 'form-control'
//= f.date_select :start, {}, { :class => "form-control" }
.actions
= f.submit 'Save', :class => "btn btn-primary"
an the error says about controller. but I do not have any 'year' method in controller:
def create
#week = Week.new(week_params.merge(course_id: #course.id))
respond_to do |format|
if #week.save
format.html { redirect_to '/weeks', notice: 'was successfully created.' }
format.json { render action: 'show', status: :created, location: #week }
else
format.html { render action: 'new' }
format.json { render json: #week.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #week.update(week_params)
format.html { redirect_to '/weeks', notice: 'starting week was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #week.errors, status: :unprocessable_entity }
end
end
end
weeks_params defined as follows:
def week_params
params.require(:week).permit(:start, :course_id)
end
I have at first problem of showing date with date_select but now with date_field it shows that but I do not know where this error refers to. I would be thankful if any one would help me.
The model is:
class Week < ActiveRecord::Base
belongs_to :course
has_many :assessments
def select_name
start.strftime("Week of %b %d")
end
end
this is my first question on stackoverflow and I'm new to Ruby on Rails, so I'm really sorry if I'm asking the question wrong.
My problem: I have two classes (word and category) and now I try to assign several categories to one word over the variable syntactical_category, for that I use a select_tag. This works nicely, when the user creates a new word as you can see in this snippet from the command line:
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"EwGk/QrOma4JGJhSBjAT6fW9BqvuCJCEPYgNC9i/okOuQZBbh1ArNEfvuHvDRwY0Q2tABYTc/b3n3tAIlQmJRg==",
"word"=>{
"name_de"=>"This is a test",
"description_de"=>"Test Description",
"syntactical_category"=>"5721e7fa8cc4b3285c000004",
"semantical_categories_ids"=>["57921a358cc4b36e42000001"]
},
"locale"=>"de"
}
But when the user tries to edit a word afterwards, the select_tag ignores the value(s) from the database and only displays the first category of all potential categories and overwrites the old value(s) if the user submits the word again. This is not what i want.
Does anybody have a solution for this problem?
I'm using Ruby 2.2.3, RubyonRails 4.2.4 and MongoDB 3.0.9, Mongoid and haml if this information helps you.
Please find below my code.
word.rb
class Word
include Mongoid::Document
include Mongoid::Attributes::Dynamic
include MultiLanguageText
belongs_to :syntactical_category, class_name: "Category", inverse_of: nil, :autosave => true
has_and_belongs_to_many :semantical_categories, class_name: "Category", inverse_of: nil, :autosave => true
field :name_de, type: String
field :name_en, type: String
field :description_de, type: String
field :description_en, type: String
end
words_controller.rb
class WordsController < ApplicationController
helper MultiLanguageText
def index
#word = Word.all
end
def show
#word = Word.find(params[:id])
end
def new
#word = Word.new
end
def create
#word = Word.new(word_params)
respond_to do |format|
if #word.save
format.html { redirect_to #word, notice: t("word_create_success") }
format.json { render :index, status: :created, location: #word }
else
format.html { render :new }
format.json { render json: #word.errors, status: :unprocessable_entity }
end
end
end
def edit
#word = Word.find(params[:id])
end
def update
#word = Word.find params[:id]
#word.update_attributes(word_params)
respond_to do |format|
if #word.update(word_params)
format.html { redirect_to #word, notice: t("word_update_success") }
format.json { render :index, status: :ok, location: #word }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def destroy
#word = Word.find(params[:id])
#word.destroy
flash[:notice] = t(:delete_confirmation)
redirect_to words_path
end
def word_params
allow = [:name_de, :name_en, :description_de, :description_en, :syntactical_category, {:semantical_categories_ids => []}]
params.require(:word).permit(allow)
end
end
words/_form.html.haml
= form_for #word do |w|
.field
.input-append
= select_tag 'word[semantical_categories_ids][]', options_for_select(Category.where(category_type: 'semantic').where(:name_de.exists => true).collect{|c| [c.name_de, c.id]})
Thank you in advance for your help!
Just pass #word.semantical_categories_ids after the collection
= select_tag 'word[semantical_categories_ids][]', options_for_select(Category.where(category_type: 'semantic').where(:name_de.exists => true).collect{|c| [c.name_de, c.id]}, #word.semantical_categories_ids)
and I think it should accept multiple values. If yes add multiple: true at the end
I think you have multiple selection select_tag
So, you have to do below
= select_tag 'word[semantical_categories_ids][]', options_for_select(YOUR_COLLECTION,ARRAY_OF_SELECTED_VALUES),{multiple: true}
Note: Add ,{multiple: true} to your select_tag
i found a solution for my problem. I'm not sure if this is "the way to do it" but for me it works fine.
- #word['semantical_categories_ids'] = [''] if !#word['semantical_categories_ids'].is_a? Array
- #word['semantical_categories_ids'].each do |entry|
= select_tag 'word[semantical_categories_ids][]', options_for_select(Category.where(category_type: 'semantic').where(:name_de.exists => true).collect{|c| [c.name_de, c.id]}, entry)
Trying to save parameters from url into a database.
I have a link:
- #kits.each do |kit|
= link_to 'Submit Video', new_challenge_path(kit: kit)
#this will append a new parameter into the url
The link goes to a form page with this:
= simple_form_for #challenge, html: { class: "form-horizontal" } do |f|
= f.input :video_title
= f.input :video_url
= f.input :video_desc, as: :text
= f.button :submit, "Upload video"
In my controller, I have this:
def create
#challenge = Challenge.new(challenge_params)
#challenge.kit_id = params[:kit]
respond_to do |format|
if #challenge.save
format.html { redirect_to #challenge, notice: 'Challenge was successfully created.' }
format.json { render :show, status: :created, location: #challenge }
else
format.html { render :new }
format.json { render json: #challenge.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_challenge
#challenge = Challenge.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def challenge_params
params.require(:challenge).permit(:video_title, :video_url, :video_desc, :kit_id)
end
Association between kit and challenge
class Challenge < ActiveRecord::Base
belongs_to :kit, counter_cache: true
end
class Kit < ActiveRecord::Base
has_many :challenges
end
The parameter doesn't save into the :kit_id. Doesn't this: #challenge.kit_id = params[:kit] supposed to take care of saving it?
You are right to do the kit_id assignment in controller, not in the form, since doing so in the form (even by means of using the hidden field) is not secure, because changing the value of a hidden_field is just a matter of inspecting the elements of the page.
What you are doing wrong, is I assume that params[:kit] is just nil.
You would probably want to use params[:kit_id].
If that won't help, put binding.pry here:
# ... code omitted
#challenge.kit_id = params[:kit]
binding.pry
# ... code omitted
and check the value of params in opened console.
I'm a bit new in ruby/rails/POO and I'm a bit lost in a form that I'm realizing.
I'm using the gem formtastic and I'm doing it in haml.
I have this model
class Help < ActiveRecord::Base
attr_accessible :answer, :category, :question
validates :category, presence: true, uniqueness: true
validates :question, presence: true
validates :answer, presence: true
end
In my form, I want the possibility to create a new Question/Answer with its category.
The category should be selected in a selectbox but if the category I want is not listed yet, I want to have the ability to add it.
Here's the form
= semantic_form_for #help do |f|
= f.inputs do
= f.input :category, :as => :select, :collection => Help.category
= f.input :category
= f.input :question
= f.input :answer
= f.action :submit, :as => :button
EDIT :
class HelpsController < ApplicationController
# GET /helps
# GET /helps.json
def index
#helps = Help.all.sort_by {|f| f.category}
respond_to do |format|
format.html # index.html.erb
format.json { render json: #helps }
end
end
# GET /helps/1
# GET /helps/1.json
def show
#help = Help.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #help }
end
end
# GET /helps/new
# GET /helps/new.json
def new
#help = Help.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #help }
end
end
# GET /helps/1/edit
def edit
#help = Help.find(params[:id])
end
# POST /helps
# POST /helps.json
def create
#help = Help.new(params[:help])
respond_to do |format|
if #help.save
format.html { redirect_to #help, notice: 'Help was successfully created.' }
format.json { render json: #help, status: :created, location: #help }
else
format.html { render action: "new" }
format.json { render json: #help.errors, status: :unprocessable_entity }
end
end
end
# PUT /helps/1
# PUT /helps/1.json
def update
#help = Help.find(params[:id])
respond_to do |format|
if #help.update_attributes(params[:help])
format.html { redirect_to #help, notice: 'Help was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #help.errors, status: :unprocessable_entity }
end
end
end
# DELETE /helps/1
# DELETE /helps/1.json
def destroy
#help = Help.find(params[:id])
#help.destroy
respond_to do |format|
format.html { redirect_to helps_url }
format.json { head :no_content }
end
end
end
When I try to reach /help/new it actually says to me :
undefined method `model_name' for NilClass:Class
The aim is to have in the selectbox, categories already registered, and if the user is not founding the category he wants to use in the selectbox, he can create one by typing it in the input.
Any clues to help me doing this ?
Cordially ,
Rob
Try this:
= f.collection_select :category
I found a method that does half what i wanted.
It's the method pluck.
I defined a static method in my model :
def self.getcat
Help.pluck(:category)
end
Then in my form in simply call this method on my collection :
= f.input :category, :as => :select, :collection => Help.getcat