Rails 3: Mongoid validation issue - ruby-on-rails

Using Mongoid, I am trying to validate the :code input on the submission form to make sure they are using a proper code that is already stored in the database. There are about 2000+ codes so a helper method array collection wouldn't be feasable.
What is the best way to do this?
I was thinking of doing an inclusion validation, like this:
class Request
include Mongoid::Document
field :code, type: String
validates :code, :presence => true,
:inclusion => { :in => proc { Listing.all_codes } }
end
Then the model that has all the stored codes, like this:
class Listing
include Mongoid::Document
field :code, type: String
def self.all_codes
where(:code => exists?) # <--- this is broken
end
end
But I can't seem to get this to function the way I would like. Any feedback would be much appreciated.

Your Request model looks fine. But the Listing.all_codes needs to return an array of only codes. so:
class Listing
include Mongoid::Document
field :code, type: String
def self.all_codes
only(:code).map(&:code)
end
end

Related

rails app - mongoid does not insert a new field

I just started to create on app with rails-api and mongoDB (gem mongoid in rails).
I have created my model like this:
class User
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :language
accepts_nested_attributes_for :language
field :name, type: String
field :lastname, type: String
field :mail, type: String
field :passwd, type: String
field :auth_token, type: String
end
And i want to add another field in my model.
So at the end of my model i add this:
field :slug, type: String
But when i insert a new document, mongoid doesn't detect the new field and return null.
I try to do rake:migration but is useless with mongodb and i can't find the issue. Could you help me?
Best regards
Most probably you did not add that new field into your strong params whitelist.
Look into your controller and find a line that looks like this:
params.require(:user).permit(:name, ...)
Add slug there like this:
params.require(:user).permit(:name, ..., :slug)

Using geoNear with Rails / Mongoid

I'm having problems querying Geospatial indexes with MongoDB / Rails.
I'm using this gem - https://github.com/kristianmandrup/mongoid_geospatial
Here's my fairly basic model:
class Company
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Geospatial
field :name, type: String
field :location, type: Array, spatial: true
spatial_index :location
validates :location, location: true
end
Then, in my controller, I have this
##vendors = Vendor.where(:location.near => {:point => [-2.1294761000000335,57.0507625], :max => 5})
However, this isn't returning expected results (ie- it's returning things from all over the place, not just near that particular lon / lat)
Also, how would I go about doing a geoNear with this?
So that I can get back the distances from central point for each result?
Note
After writing this question, I've seen the gem has been updated, but I'm not sure if there's a better alternative..?
You don't need the mongoid_geospatial gem to do a geoNear query: mongoid already supports it (in version 3 at least).
Change your model to:
class Company
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :location, type: Array
index({location: "2d"})
validates :location, location: true
end
And run your query as:
#vendors = Vendor.geo_near([-2.1294761000000335,57.0507625]).max_distance(5)

undefined method 'delete' for String:Class when using Mongoid and creating records via console

I have a class that looks like this:
class SearchService
include Mongoid::Document
key :name, String
field :url, String
field :searchBaseUrl, String
validates_presence_of :name, :url, :searchBaseUrl
validates_uniqueness_of :name
end
The first issue here is that I was using validates_presence_of incorrectly or so it would seem. I commented the line out and I could create the class instance at the console with no problem. But when I tried to create the object with validates_presence_of in place I got an error:
NoMethodError: undefined method `delete' for String:Class
from D:/Ruby193/lib/ruby/gems/1.9.1/gems/mongoid-2.3.3/lib/mongoid/fields.rb:230:in `add_field'
from D:/Ruby193/lib/ruby/gems/1.9.1/gems/mongoid-2.3.3/lib/mongoid/fields.rb:145:in `field'
Is this error message meaningful? I'm having a hard time seeing the relationship between a missing method on the String class and me using validates_presence_of incorrectly. If I could pick only one thing about Ruby that bugs me it would have to be terrible error messages.
The rails docs say that validates_presence_of is for association. But the mongo db page says that it's used for required fields. Are the mongodb docs incorrect?
I'm trying to decide if this is an issue I should report to the mongoid team or if I'm just not understanding how the language works.
Update: OK now I'm getting a very similar error in a class that doesn't use validates_presence_of at all. So it's some other issue (even though commenting out that line fixed it initially).
Update2: This appears to me to be bug in mongoid. Changing this line:
field :name
to
field :name, String
will cause the error to show up. Seems that any field that is defined with a type will mess up mongoid. Or those aren't supposed to be there anymore? The mongodb docs (linked above) have code that looks like key :votes, Integer, :default => 0 so if it isn't valid the docs are wrong.
Rails 3.1.1, Ruby 1.9.3
You use incorrect syntax for field type definition. It should use options hash and key "type". Example from from documentation http://mongoid.org/
class Artist
include Mongoid::Document
field :name, type: String
embeds_many :instruments
end
You refer to MongoMapper examples, but use Mongoid ))
jcollum, the problem is coming from the fact that you are using mongoid but the examples on mongodb.org are using mongomapper.
Please be aware that these are different ODMs for rails and have slightly different syntax for defining fields.
Please see the documentation here for mongoid.
The format for the fields using mongoid:
class Person
include Mongoid::Document
field :first_name, type: String
field :middle_name, type: String
field :last_name, type: String
end
In Rails 3, you should be using the new style validations:
validates :name, :presence => true, :uniqueness => true
validates :url, :presence => true
validates :searchBaseUrl, :presence => true
Use with_options to make it DRYer
with_options :presence => true do |v|
v.validates :name, :uniqueness => true
v.validates :url
v.validates :searchBaseUrl
end

Retrieve validating field names

I am using Ruby on Rails 3 and I would like to retrieve validating field names. That is, I defined some validation for a class and I would like to retrieve what fields (their names) are candidate for validation on submitting a form.
I need that because I would like to "play" with class error attributes (<name_class>.errors).
How can I do?
You can access your model's validators method. This will return an array of validators on your model.
For example, if you had this:
class User < ActiveRecord::Base
validates :name, :presence => true
validates :email, :uniqueness => true
end
Then you could access the validators like this:
User.validators
# => [#<ActiveModel::Validations::PresenceValidator:0x123456 #attributes=[:name], #options={}>....]
User.validators.first.attributes
# => [:name]
User.validators.first.class
# => ActiveModel::Validations::PresenceValidator

How to validate a field only if another has been filled out?

How would I validate a field only if another has been filled out In Ruby on Rails 2.3.5?
class Model < ActiveRecord::Base
validates_presence_of :address, :if => :city?
end
:address and :city are both attributes of Model.
validates_presence_of accepts an if attribute that take one of three things, according to the documentation: a string, a method, or a proc.
if - Specifies a method, proc or string to call to determine if the validation
should occur (e.g. :if => :allow_validation, or
:if => Proc.new { |user| user.signup_step > 2 }).
The method, proc or string should return or evaluate to a true or false value.
I ended up needing to use a proc, as I wanted to make sure that a certain parameter was filled out before validating:
validates_presence_of :bar, :if => Proc.new { |foo| !foo.age.blank? }

Resources