can't get mongoid/rails field to accept input as array - ruby-on-rails

I'm creating a Question/Answer model in a Mongoid/Rails project. I want users to create their own questions and then create possible answers: 2 answers or 3 answers or more. I've got the form so they can add as many questions as they want, but I get this error:
Field was defined as a(n) Array, but received a String with the value "d".
Not only am I not getting the array, but it's wiping out "a" "b" and "c" answers and only saving "d".
My model:
class Question
include Mongoid::Document
field :question
field :answer, :type => Array
end
The relevant section of _form.html.haml:
.field
= f.label :question
= f.text_field :question
%p Click the plus sign to add answers.
.field
= f.label :answer
= f.text_field :answer
#plusanswer
= image_tag("plusWhite.png", :alt => "plus sign")
.actions
= f.submit 'Save'
The jQuery that repeats the answer field when they need it:
$("#plusanswer").prev().clone().insertBefore("#plusanswer");
I've tried several of the solutions here involving [] in the field but getting nowhere.
Thanks much.

Two approaches:
One is to edit the form such that instead of returning back question[answer], it returns question[answer][] which will build answer to be an array.
EDIT: I'm reading your question closer and it seems like you have some JS dynamically rendering forms. In that case, setting the id with an empty bracket set [] at the end should turn the form object returned into an array
The other is to override the setter in the model to convert a string into an array. The safest way is to create a matching getter
class Question
field :answer, type: Array
def answer_as_string
answer.join(',')
end
def answer_as_string=(string)
update_attributes(answer: string.split(','))
end
end
Then use :answer_as_string in your form

If you don't want to do a lot wrangling back and forth of the values between javascript and your model and you understand how to use fields_for and nested attributes a better approach might be to make answers separate model and embed them in the question model as so:
class Question
include Mongoid::Document
embeds_many :answers
end
class Answer
include Mongoid::Document
field :content # or whatever you want to name it
end
Your form would look like this (pardon my HAML):
.field
= f.label :question
= f.text_field :question
%p Click the plus sign to add answers.
= f.fields_for :answers do |ff|
.field
= ff.label :content
= f.text_field :content
#plusanswer
= image_tag("plusWhite.png", :alt => "plus sign")
.actions
= f.submit 'Save'

Related

Creating a form for a has_and_belongs_to_many relationship

I've read through a lot of posts regarding this topic, but not one actually provides a good answer.
I have a class A and a class B who are related through a has_and_belongs_to_many relationship.
class A < ApplicationRecord
has_and_belongs_to_many :bs
end
class B < ApplicationRecord
has_and_belongs_to_many :as
end
What I need is a form for class A showing a selection field with all the instances of B to select. Also, when editing and instance of A, the form should present a list of the related instances of B and a way to mark them for removal.
I have tried creating the list of existing instances by providing a hidden field with the id for each instance of B. And I have created a selection field using the select_tag. The code looked something like that:
= form_for #a do |f|
.field
= f.label :name
= f.text_field :name
.field
- #a.bs.each_with_index do |b, i|
= b.name
= hidden_field_tag "a[b_ids][#{i}]", b.id
.field
= select_tag "a[b_ids][]", options_from_collection_for_select(#bs, "id", "name")
.actions
= f.submit 'Save'
This worked just fine when creating the new instance of A. But when I tried to edit it, there seems to be a problem making the execution fall back to using POST instead of PATCH. And since with there is now route for POST when editing/updating this obviously ended in an exception.
So I wonder if there is any clean way to create the form I need?

Fields_for form fields not displaying in rails form

I have a class Rfsestimation shown below:
class Rfsestimation < ActiveRecord::Base
has_one :rfstaskset
has_one :rfsnote
enum request_type: [:front_end, :back_end, :front_end_and_back_end]
enum band_type: [:Simple, :Medium, :High, :Complex, :VComplex, :Outside_AD]
**accepts_nested_attributes_for :rfstaskset**
**accepts_nested_attributes_for :rfsnote**
validates_presence_of :number, :name, :date_of_estimation, :request_type_id, :band_id, :hours_per_day, :estimated_start_date, :estimated_end_date, :message => "Should be present"
validates_numericality_of :number
end
Please see the two lines for association above marked in bold. I am attempting to create the associated objects, Rfsnote and Rfstask through fields_for shown in below form:
<%= f.fields_for :rfstaskset do |rfs_task| %>
However the fields which are supposed to appear do not appear as expected. But if i use rfstasksets, as below, the form fields appear as expected.
What might be the reason for this?
<%= f.fields_for :rfstasksets do |rfs_task| %>
I think you are not building the associated object in your controller.
You new action need to look like this:
def new
#rfsestimation = Rfsestimation.new
#rfsestimation.build_rfstaskset
end

Rails 4: How to display fields with error in red?

First question: how to validate a model relation and mark it in form when validation failed.
I have a subject model:
class Subject < ActiveRecord::Base
belongs_to :semester
validates_presence_of :semester
end
In my view (form):
<%= select_tag :semester, options_from_collection_for_select(#semesters,"id","name") %>
The validates_presence_of works fine. But when the validation fails (user forgot to enter semester ). The semester input is not marked in red.
Second question: how to validate an input field.
In my view, I also have a university input field, but model subject has no relationship with university, no field university in subject table. So how to validate it and mark it in red.
Thanks in advance.
If you want to get the fields with error displayed in red "out of the box", you must use a form builder. The code will looks like f.select ... instead of using select_tag.
With the form builder, the fields with errors are created inside a <div class="field_with_errors">...</div>. The css file generated by scaffolding displays these fields in red; if you're not using it, you must add the css rules to your css.
# app/models/subject.rb
class Subject < ActiveRecord::Base
belongs_to :semester
validates :semester, :university, presence: true # new syntax http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates
end
# app/views/subjects/_form.html.erb
<%= form_for #subject do |f| %>
Semestr: <%= f.collection_select :semester_id, Semestr.all, :id, :name, prompt: true %>
University: <%= f.text_field :univercity %>
<% end %>
For more information about building forms in rails (with validations enabled) you could find there http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html
Those "red errors" that you hope for are probably coming from a form helper gem like formtastic, feel free to check that out.
I have literally no idea what your second question is asking, but if you're looking for a custom validation. Check out the rails docs on them for help.
If you'd like more help, (please) edit your question to be more clear (thanks)

Search by association in Rails 3 with MetaSearch

I'm using MetaSearch gem in my Rails 3 project.
I have two models:
class Company < ActiveRecord::Base
belongs_to :city
end
class City < ActiveRecord::Base
has_many :companies
end
I have the action in CompaniesController:
def index
#search = Company.search(params[:search])
#companies = #search.all
end
The action's view contains:
= form_for #search do |f|
= f.label :city_id_equals
= f.select :city_id_equals
= f.submit 'Search'
I want a list with city names to be rendered and the opportunity to search the companies by city. But instead of the names and ids of the cities I have something like "City:0x00000102a20488" and the search doesn't work properly.
I think that the mistake is here: ":city_id_equals". How to make it correct?
The solution is found!
Instead of:
= f.label :city_id_equals
= f.select :city_id_equals
I should use:
= f.label :city_id_equals
= f.collection_select :city_id_equals, City.all, :id, :name, :include_blank => true
Not sure your question is really clear.
First of all, I'm guessing you have something like <City:0x00000102a20488>, which is the string representation of a ruby object. If you want to display the name of the city, city.name should make the trick (assuming you have a name member on the city!).
For the search, I don't really get what you are trying to do. What is :city_id_equals supposed to mean to you?

an example of a nested form in simple form?

I am still struggling both writing the controller and the actual form to be able to nest one form in another with an optional model?
I have Message which has many contacts
When submitting a message, I want to add a contact optionally.
I have this as an example:
= simple_form_for Message.new, :remote => true do |f|
#message_form
= f.error_messages
%p
= f.input :account_name, :url => autocomplete_account_name_messages_path, :size => 40, :as => :autocomplete
%p
= f.input :topic, :required => true,
:input_html => {:size => 30}
#add_contact_btn
= link_to "Add Contact"
#contact_form
= f.simple_fields_for :contactd do |fc|
= fc.input :email
= fc.input :first_name
= fc.input :last_name
= f.submit 'Give'
= f.submit 'Request'
For Message.rb model, I have the following:
has_many :contacts
accepts_nested_attributes_for :contacts, :reject_if =>:all_blank
Note: When I used :contacts in the simple_fields_for it didn't work, so it is singular. But the reverse for accepts_nested_attributess_for.
In my create controller for message, I included message.contacts.build
But right now I am still generating nil contacts.
Here is what I see passed as form data from google chrome:
message%5Baccount_name%5D:McKesson
message%5Btopic%5D:testing a contact
message%5Bbody%5D:testing this
sender_id:
receiver_id:23
message%5Bcontacts%5D%5Bemail%5D:888#gmail.com
message%5Bcontacts%5D%5Bfirst_name%5D:Ang
message%5Bcontacts%5D%5Blast_name%5D:Name
The correct method name is simple_fields_for (notice the plural)
Also, you need to keep the f. to call it on the simple_form object
I have a small project where I demonstrate how to use nested forms in simple-form, combined with cocoon (a gem I created to add/remove nested elements dynamically).
The project is on github.
Hope this helps.
In my create controller for message, I included message.contacts.build
But right now I am still generating nil contacts.
Make sure you put in your Message.rb model the ability for it to accept the attributes too.
class Message < ActiveRecord::Base
attr_accessible :contacts_attributes
has_many :contacts
accepts_nested_attributes_for :contacts
I know it doesn't answer your question fully but it may have just been this. When it comes to my project, it would return nil if i didn't include the :contacts_attributes, in my case it deals with products. Hope this helps even if I'm not using simple form as of now!
I faced similar issues working with nested forms. As suggested by JustinRoR you need to define
attr_accessible: contacts_attributes.
You should be able to test the hash in the ruby console ( I am not sure if you have tried this). I suggest you to print the params[:message] and use this to create message from console like Message.new(params[:message]). (Note params[:message] is what you get by printing the params[:message] hash).
Once it works in console it should work like charm

Resources