how to use mongoid nested attributes on my model - ruby-on-rails

My app is a rails_admin with mongoid working well.
Now I'm trying to use nested attributes on edit form, but I don't know exactly how to do this.
My document is:
{
"_id" :ObjectId("..."),
"email" :"steve#steve.com",
"name" :"steve",
"facebook":{
"id":12345,
}
}
So, my model is:
class User
include Mongoid::Document
field :name
field :email
field :facebook
end
So, the problem is:
On the edit form it shows a text field with facebook json content: {"id":12345}
How can I use one text field for each sub attribute? I tried something like field :facebook.id but it doesn't work.
thanks!

Better is to make a custom field serialization of facebookHash, something similar to
class User
include Mongoid::Document
field :name
field :email
field :facebook, :type => facebookHash
end
If you did not have idea regarding custom field serialization, Have a look at Custom Fields in MongoId. Then you can easily create your fields partial on the basis of that model.

Related

How do I add a new column to Rails Mongodb?

I currently have the columns id, name, email, linkedin, company, contacted, recruiter, student and I want to add a new one called responded. I'm only finding answers on how to add new columns to all the existing instances in my db. So I did try this:
db.people.update({}, {$set: {"responded": false}}, false, true)
All my existing instances have a field :responded set to false by default. When I try to add a new person now I'm getting this error:
Mongoid::Errors::UnknownAttribute in PeopleController#create
message: Attempted to set a value for 'responded' which is not allowed on the model Person. summary: Without including Mongoid::Attributes::Dynamic in your model and the attribute does not already exist in the attributes hash, attempting to call Person#responded= for it is not allowed. This is also triggered by passing the attribute to any method that accepts an attributes hash, and is raised instead of getting a NoMethodError. resolution: You can include Mongoid::Attributes::Dynamic if you expect to be writing values for undefined fields often.
MongoDB does not have "columns", it does not have tables either. You have documents with fields.
I imagine you are using MongoID for your models, so you only need to define the field on your model
class Person
include Mongoid::Document
field :first_name, type: String
field :middle_name, type: String
field :last_name, type: String
field :responded, type: Boolean # something like this
end
https://docs.mongodb.com/mongoid/current/tutorials/mongoid-documents/#fields

Associating a temporary (non-DB) model to a simple_form

I have a simple_form, that doesn't really apply to a normal model. If I have the object just set to :thing it seems to work.
However, I want it to have some validation. In other questions, I've found that this means that I NEED to have a model... I'm not sure what needs to be in that model, however. So, I made I model, but I can't figure out how to hook them up.
class ClientEmail
include ActiveModel::Validations
validate :cannot_be_present
attr_accessor :to_domain
def cannot_be_present
newDomClients = Client.where("email like :foo", {:foo => "%#{to_domain}%"})
errors.add(:base, "There cannot be any emails already in the database with the target domain" ) if newDomClients.length > 0
end
end
and the simple_form is:
= simple_form_for(#client_email, url: { action: "update" }, html: {class: "search_form", method: :put }) do |f|
.input-row
= f.input :newDomain, :label => "New domain name", :required => true
(etc)
Initially, it said that #client_email was nil, so I initialized it (which seems unlikely to be necessary given Rails...) with:
- #client_email = ClientEmail.new
but that tells me that ClientEmail doesn't have a to_key method, so I'm clearly missing a bunch of infrastructure somewhere.
If you create a form with an object that belongs to a model you can't create fields that doesn't belongs to that model. You need to create form like this in order to do that:
= simple_form_for(:client_email, url......)
if you create form with symbol like this you can create any field in this form and send to controller that you want. params hash won't change too much and you can call your special fields like this:
params[:client_email][:your_field_name]
since this field doesn't belongs to a model its better to validate it in controller.
Hope it helps.
It appears that I needed:
include Virtus.model
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
I'm not sure exactly what Virtus is. it's probably possible without it, but it's a library I already have...

Rails: Custom attributes for a form created at run time by an Admin

I am new to Rails. Let's say there's an Admin of a web app who can set extra fields required when a user submits a form.
For example, in a bug tracking system, Admin can set a 'checkbox' and labeled "Promised to client?". So whenever anyone enters a bug, they should be submitting this information. This can also later be changed or even removed. All depends on Admin.
So I want Admin to have following options when they create Custom Fields for a Bug entry form...
'Field name' text input
'Field type' dropdown list with values of "checkbox", "text input", "textarea" etc
'Required' a checkbox if this is required for a Bug entry
If anyone has an example on how to do this and especially how to properly validate (server side, without JS) such custom fields, it would be awesome.
If it's important, I am using MySQL.
Install nested form gem - https://github.com/ryanb/nested_form
Add Bug and CustomField models:
model Bug
has_many :custom_fields
accepts_nested_attributes_for :custom_fields, allow_destroy: true
end
model CustomField
belongs_to :bug
validates :name, presence: true
enum field_type: ["checkbox", "text input", "textarea"]
end
Read nested_form Usage to add nested fields to bug form.

Setting a 'published_on' date field in a Rails model

This is my 2nd day playing with Ruby on Rails, so please be gentle :)
I have a very (hopefully) simple question: I want to set a publish date on my model, when it is indeed being created. I am using Mongoid, and it looks like this:
class Page
include Mongoid::Document
field :content, type: String
field :title, type: String
field :published_on, type: DateTime
end
Here is the question: should I set the published_on field from the create action, just before the call to #page.save? Or is there a better, more idiomatic way?
If I do it like that, meaning, calling #page.published_on = Date.now from within the controller's action, I get a warning:
Cannot find 'published_on=' for type 'Page'
If you put
class Page
include Mongoid::Document
include Mongoid::Timestamps
you get the rails automagic fields created_at and updated_at

ROR: View only form fields

Is there any way that you can mark a form field to be only accessible in the view?
I have some 'helper' fields that I use in conjunction with jQuery to build and order certain elements in the view. These fields don't need to be passed through to the controller and are not linked to the model at all.
I'm just wondering if there is some attribute I can use with the ROR form fields to mark them as obsolete.
Currently I am just using vanilla form fields.
Maybe FormTagHelper (doc) may help you. With this helper you can create html inputs outside of a form (this way the value of these input fields won't be sent to the controller).
HTML provides a 'disabled' attribute for all form elements which exclude them from submission. Use that, or do a pre-submit check using javascript which removes the attributes from the form submission.
To expand upon Archit Baweja's answer, disabled BUTTON, INPUT, OPTGROUP, OPTION, SELECT, and TEXTAREA tags are not submitted with the form. More information on disabled elements can be found here: http://www.w3.org/TR/html4/interact/forms.html#h-17.12
Additionally, if you have any security concerns of these inputs being mass assigned in the controller via "upodate_attributes(params), then you can guard against this end user assignment using attr_accessible. You may call this method and pass the parameter names you would like to white list, and allow to pass through when using update_attributes:
class AccountsController < ApplicationController
include ActiveModel::MassAssignmentSecurity
attr_accessible :first_name, :last_name
attr_accessible :first_name, :last_name, :plan_id, :as => :admin
def update
...
#account.update_attributes(account_params)
...
end
protected
def account_params
role = admin ? :admin : :default
sanitize_for_mass_assignment(params[:account], role)
end
end
More information on the MassAssignmentSecurity module can be found here: http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html

Resources