Modeling a Mongodb array using Rails form_for - ruby-on-rails

I am working on an application that has a project model that contains tags. The model roughly looks like:
class Project
include Mongoid::Document
field :name, type: String
field :tags, type: Array
...
...
end
I am trying to figure out the best way to make a form for creating/editing a project that would allow a user to add multiple tags. I would like to use rails built-in form_for method, if possible.
The issue I am coming across is that I am unsure how to give the user the ability to add multiple tags.
One idea would be to use a string field, and then before the project is created/updated, I could split the string on comma's, or spaces. I could also easily create a text area and split on a new line character.
However, I would much rather give the user the ability to add tags by typing a value into a field, and then clicking a plus symbol to append it to an array of tags. I can easily accomplish this with javascript, but I was wondering if a solution exists, whether it be through another gem or using an existing rails method, that would not require me to write custom javascript for the form?
Any help or pointers would be appreciated.
Thank you

To generate an array with params you can do by define a "[]". So you can do :
text_field_tag "project[tags][]"

Related

setting mongoid hash field values

I'm using Mongoid in a Rails project (both 4.0.x), and I've got a document with a hash field that stores some schema-less data.
class Thing
field :name, type: String
field :mass, type: Integer
field :info, type: Hash
end
With this setup, I can query for things, say, that have a key :endDate like so:
Thing.where("info.endDate"=>{'$exists'=>true})
And that's all nice and handy. Using a hash field for this :info field is nice because what I want to store doesn't have a fixed schema and varies from one thing to another.
Ok, but, I can't use the same dot syntax to $set key/value pairs in the :info hash. [1]
thing.set("info.endDate"=>Time.now)
Raises a Mongoid::Errors::UnknownAttribute error.
It tells me I'd have to include Mongoid::Attributes::Dynamic in my model to do this, but that doesn't seem right to me. The point of the hash field type seems to be to allow you to work with data that doesn't have a fixed schema. It doesn't seem like I should have to include a special "dynamic attributes" module to use hash fields.
So right now, I'm updating values using regular old [] syntax, and then calling save on the model, like so:
thing.info[:endDate] = Time.now
thing.save
But a lot of the time it happens that it would be nicer to just $set the value. Is there some other syntax for setting hash field values? Am I wrong about the above error message and Dynamic Attributes being wrong-headed? Am I stuck doing two step updates to hash fields for now?
[1] admittedly, I've recently migrated from mongomapper, and so my expectations of this syntax are partly set by having been able to do this previously in mongomapper.
The thing with Hash field is, it can be dynamic as much as you want. Therefore to prevent polluting your DB schema with unintended fields caused by bugs in your code this functionality is disabled by default.
No you are not stuck using 2-step updates for your hashes at all!
[],[]= are the shortcuts for read_attribute() and write_attribute() and should be used if you don't include Mongoid::Attributes::Dynamic. If you try to use $set without enabling dynamic attributes you will get a no-method error because it does not see your dynamic attributes as defined attributes.
If you'll read the source of Mongoid::Attributes::Dynamic then you'd find that this is required to add the dynamic attributes functionality.
To update the values by including Mongoid::Attributes::Dynamic you need to follow these steps:
thing = Thing.first
thing.set("info.endDate" => Time.now)
thing.reload # This will update the current variable
Otherwise if you need you can easily skip this and do the value update by 2-step method
I hope this sheds some light over your query.
Source:
Rails mongoid dynamic fields - no method error
Dynamic attributes with Rails and Mongoid
I think you pass parameter in wrong way. Replace arrow symbol with comma
You can change to this and it will work
thing.set("info.endDate", Time.now)

Using rails form to populate model with hash

I am currently working on a simple rails4 app. As part of the app, I am creating a form to populate the database and a particular column (:additional), I would like to populate with a hash where the key is a string (heading) and the value an array of strings (paragraphs below heading). So, for example: {"Heading" => ["Paragraph1", "Paragraph2"]} etc.
I am confused how I would now set up a form using rails to populate this column. I was thinking of creating a text_field for the title and then one or more text_areas underneath for the paragraphs and then somehow merging them in the controller but when creating the fields, I have to give the object as :additional which leads to problems.
How would I go about best accomplishing this? Is it even possible or should I restructure my database somehow?
Any advice is much appreciated.
If you're using postgres, ActiveRecord has support for using :hstore as the column type. If you're not, you can use serialize.

How can I display data from a related model in a Rails form

I have two models
class Car
has_many :engines
end
class Engine
belongs_to :car
end
In the car form I have a select field where the user can select the engine type. The list might be "1.4L; 1.6L; 2.0L..."
Lets say I want to display additional information from the Engine model when the user selects a engine. This should be displayed on the Car form. This might be e.g. BHP, max revs, ...etc
How do I set something like this up. I guess there are two aspects:
How to display data from the engine
model on the car form without using
a field (this data is not editable).
How to update this data dynamically
when the user selects an option in
the select field.
Can anyone point me towards a starting point for this. I'm a bit lost where to begin.
Many thanks!
If you're working with collection_select in your form, you are setting two arguments, like :id and :name in your collection_select call. :id is the method called to determine the value for the option tag and :name is the method used to display the option tag's content.
Solution: Create a method (e.g. :name_for_select) in your engine model which returns a string with more information about your engine and call collection_select with :id, :name_for_select instead.
This is called a nested form, and if you google that you will find a lot of hints and tips. E.g. check out this and this tutorial.
You should also consider using a form builder like formtastic or simple_form: they have a lot of helpers to make life easier for you.

How would I go about letting a user add and associate a comma separated list of categories while adding an entry?

I've been struggling for quite a while to get this feature working:
I want my user to be able to select categories when uploading a photograph, but additionally be able to specify a comma-separated list of categories to create/find and associate with the photograph. I've had this working by using an attr_accessor :new_categories on the photographs model, but having that there without the column existing breaks both Paperclip and Exifr. Obviously, image upload and EXIF data retrieval are pretty important for a photography website, but not being able to add categories while uploading a photograph is a pain in the arse.
Methods I've tried so far:
Using attr_accessor to add a field for new_categories. Breaks gems.
Using an Ajax sub-form to add categories. Formtastic can't handle it.
Adding a column for new_categories to the photograph model. It works, but it's horrific.
I haven't tried using a nested form, but I'd need to intercept it and stop it from processing it as normal.
Here's an example of what I'm trying to accomplish: http://imgur.com/rD0PC.png
And the function I use to associate the categories:
def process_new_categories
unless self.new_categories.nil?
for title in self.new_categories.split(",")
self.categories << Category.find_or_create_by_title(title.strip.capitalize)
end
end
end
Has anyone got any ideas as to how to do this?
It would be easier to help if I could see your form code, roughly. I don't know anything about Formtastic, but this is very easy and very common in basic Rails.
Simply add a text field to your form:
<%= text_field_tag :new_categories %>
In your controller:
#changing your method to take a parameter here
#and moving method to the model object
model_obj.process_new_categories(params[:new_categories])
Check out this screen-cast http://railscasts.com/episodes/167-more-on-virtual-attributes it shows how to create a tags class which is similar to the categories class that you're trying to re-create.

How to create multiple records at once with ActiveScaffold in ROR

I am wanting to use ActiveScaffold to create assignment records for several students in a single step. The records will all contain identical data, with the exception of the student_id.
I was able to override the default form and replace the dropdown box for selecting the student name with a multi-select box - which is what I want. That change however, was only cosmetic, as the underlying code only grabs the first selected name from that box, and creates a single record.
Can somebody suggest a good way to accomplish this in a way that doesn't require my deciphering and rewriting too much of the underlying ActiveScaffold code?
Update: I still haven't found a good answer to this problem.
I suppose you have defined your multi-select box adding :multiple => true to html parameters of select_tag. Then, in the controller, you need to access the list of names selected, what you can do like this:
params[:students].collect{|student| insert_student(student, params[:assignment_id]) }
With collect applied to an array or enum you can loop through each item of that array, and then do what you need with each student (in the example, to call a function for insert the students). Collect returns an array with the results of doing the code inside.
if your assingnments have has_many :students or has_and_belongs_to_many :students, then you can change the id of the multi-select box to assignment_student_ids[], and it should work.
I was referred to BatchCreate, an ActiveScaffold extension which looks like it might do the trick.

Resources