RoR MongoDB Arrayfield usage - ruby-on-rails

i'm new to MongoDB and unsure how to use the Array-Field-Type.
So i created in my model
field :admins, type: Array
in this field i wanna store all user_ids that are "admins" of the model. But when I try to set this field, it doesnt save the Information in the Array it just simple creates an String with the ID. And due to my constrain that only Admins can edit my filter function
def check_if_admin
unless Agency.find(params[:id]).admins.include?(current_agent.id)
flash[:notice] = "Only possible as Admin."
redirect_to root_path
end
end
gets the error that
"can't convert Moped::BSON::ObjectId into String"
So I tried to initiate my field with in the create def as an array with ID:
#agency.admins = [current_agent.id]
That does the Trick for one user in the Array but how do I add IDs to this field?
When I go into my Edit Form:
<%= form_for(#agency) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :admins %><br />
<%= f.text_field :admins %> <br />
</div>
<div class="field">
<%= f.label :agents %><br />
<%= f.text_field :agents %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And Type in another User_ID by hand, I'm back to my error again.
Anyone knows how to get around that?
Thanks a ton for ur help!

This message means that at some point you stored a string where there should be an ObjectId. Ruby is trying to compare current_agent.id (an ObjectId) with params[:id] (a string).
It seems like you are not converting the input from the text_field in the form to an ObjectID before you push it onto the array.
Take the input from the admins field and make ObjectId's like this:
BSON::ObjectId.new(string_representing_admin_id)
I'm guessing the admins field is a comma separated array of admin _ids and that you are using some _id values that are easy to work with, like a username instead of a generated ObjectId as this would be very burdensome to work with.
In that case you would probably split and strip the input and then make an array of the ObjectIds using a map/select.
It would be much easier to use a select field that displayed usernames for something like this in rails right?
Anyway, show some sample documents from the collection if you need more help.

Related

How to determine button id in another view depending on a different view Rails

I'm making an app where some activities are listed in a table called Fakultety (polish language, sorry), and participants on in another table called Uczestnicy.
I have a submit form where you can submit yourself to an activity, but I'm stuck on passing values to a DB. Firstly, I don't know how to tell to the database on which activity you want to be assigned to (I tried to change the submit button id to an activity id and then passing it into a database but don't know how to do this id: "#{#fakultet.id}" not working) and later I want to count how many people are assigned to field participants in a database Fakultety, but I don't want to pass all the data, just ID of the users from table called Uczestnicy. How to do it? I mean just to pass the ids to another table, and how to tell the database on which activity I want to be assigned to?
This is my form view:
<h1>Zapisujesz sie na fakultet</h1>
<div class="form-group">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#participant, url: zapisy_path) do |f| %>
<p>Imię:</p>
<%= f.text_field :firstName, class: 'form-control' %>
<p>Nazwisko:</p>
<%= f.text_field :lastName, class: 'form-control' %>
<p>Grupa:</p>
<%= f.text_field :group, class: 'form-control' %>
<%= f.submit "Zapisz się", class: "btn btn-primary" id: "#{#fakultet.id}"%>
<% end %>
</div>
</div>
</div>
Does anybody understand me and can help me?
Rails provides form collection helpers that make it really easy to assign associations:
# I'm going to just do this in english
<%= form_for(#activity) do |f| %>
<%= f.collection_select(:participant_ids, Partipicant.all, :id, :name, prompt: true, multiple: :new) %>
# ...
<% end %>
Then whitelist the attribute as an array:
params.require(:activity).permit(:foo, :bar, participants_ids: [])
Thats all you actually need to assign childen to to a parent resource. This is done as a part of the normal create/update actions of the parent resource.
You don't actually need the form for the child records unless you actually want to be creating the record. In that case you can setup a nested resource or if you want to create/edit multiple nested records at the same time as the parent record you can use nested attributes.
First you should rename your models and tables, to English, it's a really bad pattern to use your language, in English it is easier to understand by other devs.
According to the problem, probably what you are looking for is hidden_field
<%= f.hidden_field :fakultet_id, :value => #fakultet.id %>
and if you want to query Fakultety that have user assigned, you can select Fakultety where participant_id is not nil
Fakultety.where.not(participant_id: nil)

Storing user input value in controller

I have a controller named Welcome with view called index.
In my index view i have created a small form as such.
<%= form_for :location do |f| %>
<%= f.label :Longitude %><br>
<%= f.text_field :integer %>
<br>
<br>
<%= f.label :Latitude %><br>
<%= f.text_field :integer %>
<p>
<%= f.submit %>
</p>
<% end %>
In this form the user can enter some integer value for longitude and latitude. Once the user enters value for longitude and latitude. They click submit. Upon submit i would like to store these values in my controller. So i am using the following method where i have two instance variables taking values from the form.
def index
#long = params[:longitude]
#lat = params[:latitude]
end
In my routes.rb I have
get 'welcome/index'
post 'welcome/index'
Please tell me where i went wrong. Also if someone can suggest a better way of doing this also i would appreciate it i am new to rails and i want to learn the correct way of doing things so i don't create bad habits early on.
The reason it's not working is because your fields are both named :integer, and since they share the same name, the browser will only send one value.
So, with your code, if you filled in the first field with 'a' and the second with 'b', your params would contain something like this:
{ location: { integer: "aaa" } }
Which obviously isn't what you want! If your HTML looked more like this (I've stripped the layout stuff to make things clearer):
<%= form_for :location do |f| %>
<%= f.label :longitude %>
<%= f.text_field :longitude %>
<%= f.label :latitude %>
<%= f.text_field :latitude %>
<%= f.submit %>
<% end %>
Then you could access the params in your controller params[:location][:longitude] and params[:location][:latitude]
A good idea to see the difference between the effect of your form vs this form would be to inspect the html. Take a look at the input name attributes, and label for attributes and see how they match up with the params Rails receives. Also, when you post the form, be sure to look in your server log to see the params! :)
After reading your question, I think you want to see how controllers, views and models work. For learning purpose you can generate scaffold and study the generated code.
For example, generate a model GeoLocation, related controller and views by this:
rails g scaffold GeoLocation longitude:string latitude:string
Now fire up rails server and browse http://localhost:3000/geo_locations/new and save your long, lat. I wrote this answer to give you some guidance.
You can follow these excellent books:
The book of Ruby
The Rails 4 Way

Ruby on rails cant get values from textfield to array

I need to get an array of strings from f.text_field and store it into a database.
<div>
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :tags %>
<%= f.text_field :tags%>
</div>
tags is an attribute and it is in an array. Name stores into the database correctly but nothing to tags.
How can i do this?
Thanks
You'll probably want to either parse that on the client side with JS to create an array that gets stored in a hidden field, or something similar. Alternatively, you should pass the raw text to the controller and parse it ruby. You should probably do the latter as you will probably want to sanitize the input.
There is a very good gem available for handling tagging. It's called acts-as-taggable and is found here https://github.com/mbleigh/acts-as-taggable-on

Rails form_for selection box, show all records but store ID

I have a software table, which has 4 fields; id, vendor, title and edition. I need a drop down box in my licenses form which will show every record like this: vendor - title - edition, but then only save the id of the chosen record to the database. I'm currently using a text box where the user can just enter the id of the software which will be saved to the database. here is my current form:
<%= form_for(#licenses) do |f| %>
<div class="well">
<%= f.label 'Software' %><br />
<%= f.text_field :software_id %>
<%= f.label 'Quantity' %><br />
<%= f.text_field :amount %>
<%= f.submit 'add'%>
</div>
<% end %>
I need to change the software text field into a drop down box, sorry if this is vague, i've not had anything to do with drop down boxes before.
Checkout collection_select for populating drop box
create a method in softwarer model like
def title_edition
"#{self.vendor.name}- #{self.title} - #{edition}"
end
#softwares = Software.all #In controller
and in view
<%= f.collection_select :software_id ,#softwares,:id,:title_edition %>
You would want collection_select with something like this:
f.collection_select(:software_id, Software.all, :id, :blah, :prompt => true)
Now the :blah is the tricky thing. In your Software model you will need to define a method that returns the concatenated string you would like; I called it :blah to draw your attention to it but it can be named anything. It would look like this:
def blah
"#{self.vendor}-#{self.title}-#{self.edition}"
end
That should return the string like you mentioned and when you call it in collection_select display it like you want it.

How to set up form for a hash in Rails?

I have some data associated with a model that is in a hash. The hash is generated in the controller: #hash.
What is the proper way to create a form for this data?
I came up with the following code for the view:
<% #hash.keys.each do |key| %>
<div class="field">
<%= f.label key %><br />
<%= text_field_tag "hash_" + key, #hash[key] %>
</div>
<% end %>
This generates the form, but it creates each hash item as a separate variable in the form. This doesn't seem to be the proper way to submit the data back. I would like to get the data back as a hash, and access it with params[:hash].
What is the best way to do this?
Working in Rails 3.07, Ruby 1.9.2.
Thanks.
EDIT: I should have made this clear. This code is inside of a form generated for a model. So, the form needs to submit all the fields for the model, plus the above hash.
Based on this article you should change the name in text_field_tag to
<% #hash.keys.each do |key| %>
<div class="field">
<%= f.label key %><br />
<%= text_field_tag "hash[" + key + "]", #hash[key] %>
</div>
<% end %>
My answer is not strictly on topic but I really recommend you to take a look at http://railscasts.com/episodes/219-active-model. You could use ActiveModel APIs to simulate a model object with Rails 3. Doing that you could simply do something like
<%= form_for(#object) %>
and leaving the populating of your object to Rails APIs.
When you use the helpers that end with _tag that's what happens.
Instead of text_field_tag ... use f.text_field ....
In order to get a hash like params => {:hash => {:field1 => "", :field2 => ""}} you have to pair up form_for with f.input_field_type instead of simply input_field_tag.
See the difference?

Resources