I need to get a list of validation rules out of a Model in my Rails application. I have searched around and looked through the source of a few client-side validation gems, but am still scratching my head about how to do this. Is there an easy way to just pull a list of validation rules out of a Rails model?
My specific use case is creating an API where the entry form for new items will be auto-generated from the Model definition, and I need to be able to express which fields are required, max length, etc. I already have fields, types, and length from the columns method, but there does not seem to be any type of similar validations method that returns what I need (mainly, required fields as enforced with validates and validates_presence_of, etc.).
Check out the #validators and #validators_on methods:
http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html
You will have to write some custom code that operates on the returned objects and determines which attributes are required, i.e. which ones have validates_presence_of.
Related
Can fields in different but associated tables have the same names is Rails 4 and be distinct. For example, if I have a class Shipping and a class Receiving, where each has the field EnterTrackingNo, and they are associated via a one to one association on the field shipping_id, will there be any issues with this setup / the fields somehow overlap / interfere with one another?
Thanks
There will not be any issue as Rails will automatically add the table name to the SQL queries it builds when it needs to. You'll be able to access the attribute easily as either shipping.EnterTrackingNo, receiving.EnterTrackingNo, shipping.receiving.EnterTrackingNo, receiving.shipping.EnterTrackingNo, etc. and Rails knows which table you're talking about due to the way they're written.
Even when you search for an object, say you want to search for all Shippings with a Receiving item that has EnterTrackingNo == 3 you'd do
Shipping.includes(:receiving).where(receiving: { EnterTrackingNo: 3 })
The only thing to keep in mind is that if you use SQL fragments (writing a where as a String, for example) you MUST write it as table_name.attribute, otherwise you'll get a SQLException: ambiguous column name. For example:
Shipping.includes(:receiving).where("EnterTrackingNo = 3").references(:receivings)
would not work as Rails, and your DB, have no way of knowing WHICH EnterTrackingNo you're talking about. You'd have to write it as:
Shipping.includes(:receiving).where("receivings.EnterTrackingNo = 3").references(:receivings)
So they know you want the Receiving model's attribute.
You'll also notice I add references(:table_name) to the ones with SQL fragments. This is necesary as well since Rails can't tell it needs a join when you just give it a String.
guys! I'm trying to make right architecture decision:
I need to hide from user of my site some fields of other users by default. So not to bother with filtering the fields in views I want to not load those fields at all, like:
default_scope -> { select(column_names - FILTERED_PARAMS) }
the rest of fields should be loaded explicitly in special cases.
The problem is that once code refers to the missing fields nomethod error shows up. I tried to meta-program those fields but fruitless this far. It seems to me that this approach doesn't fit to the AR object life-cycle.
Have you ever implemented such functionality if so what pattern have you chosen?
From my experience the best decision would be not to filter these params on the query with select, but to filter what parameters are actually sent to the user. my_model.as_json (with given param filtering options) is a simple solution for that, but for more advanced uses I would advise Rabl gem
https://github.com/nesquena/rabl
That way you have more control over which params are returned even in very advanced cases in a model-view-controller manner.
Here's my challenge. I have a key/value set that I want to tie to a model. These are my specific requirements:
I want the hash to be stored as a serialized JSON object in the model's table instead of in a separate table
I want to be able to pre-define the valid keys within the model itself
I want to be able to set a strong type for each key and automatically perform validations. I don't want to have to write validation functions for each individual attribute unless it needs a validation out of the basic data type scope.
I would LOVE to be able to magically access the attributes inside a form generator (f.input :my_key) and have the form generator recognize that :my_key is of type :boolean and create a checkbox instead of a generic text input. The same for other data types.
There are a few different ways to solve this problem, and lots of opinions for both. I read over this answer from 5 years ago:
Best approach to save user preferences?
It seems that many/most of those plugins have been abandoned. Anything else come out in the last 5 years that matches my criteria?
Your question is a bit open-ended, but as far as I can see your needs, they should be met with using Hashie gem.
The data source I am working with is terrible. Some places where you would expect integers, you get "Three". In the phone number field, you may get "the phone # is xxx". Some fields are simply blank.
This is OK, as I'm parsing each field so "Three" will end up in my model as integer 3, phone numbers (and such) will be extracted via regex. Users of the service KNOW that the data is sketchy and incomplete, as it's an unfortunate fact of the way our data source is maintained and there's nothing we can do about it but step up our parsing game! As an aside, we are producing our own version of the data slowly as we parse more and more of the original data, but this poor source has to do for now.
So users select the data they wish to parse, and we do what we can, returning a partial/incorrect model. Now the final model that we want to store should be validated - there are certain fields that can't be null, certain strings must adhere to a format and so on.
The flow of the app is:
User tells the service which data to
parse.
Service goes off and grabs
the data, parses what it can and
returns a partial model with
whatever data it could retrieve.
We display the data to the user,
allowing them to make corrections
and to fill in any mandatory fields
for which no data was collected.
This user-corrected data is to be
saved, and therefore validated.
If validation fails, show data again
for user to make fixes, rinse &
repeat.
What is the best way to go about having a model which starts off being potentially completely invalid or containing no data, but which needs to be validated eventually? The two ways I've thought of (and partially implemented) are:
2 models - a Data model, which has validations etc, and an UnconfirmedData model, which has no validations. The original data is put into an UnconfirmedData model until the user has made their corrections, at which point it it put into a Data model and validation is attempted.
One model, with a "confirmed data" flag, with validation being performed manually rather than Rails' validation.
In practice I lean towards using 2 models, but I'm pretty new to Rails so I thought there me be a nicer way to do this, Rails has a habit of surprising me like that :)
Must you save your data in between requests? If so, I would use your two model format, but use Single Table Inheritance (STI) to keep things dry.
The first model, the one responsible for the parsing and the rendering and the doing-the-best-it-can, shouldn't have any validations or restrictions on saving it. It should however have the type column in the migration so you can use the inheritance goodness. If you don't know what I'm talking about, read up on the wealth of information on STI, a good place to start would be a definitive guide.
The second model would be the one you would use in the rest of the application, the strict model, the one which has all the validations. Every time a user submitted reworked and potentially valid data, your app would try and move your instance of the open model created from the params, to an instance of the second model, and see if it was valid. If it was, save it to the database, and the type attribute will change, and everything will be wonderful. If it isn't valid, save the first instance, and return the second instance to the user so the validation error messages can be used.
class ArticleData < ActiveRecord::Base
def parse_from_url(url)
# parses some stuff from the data source
end
end
class Article < ArticleData
validates_presence_of :title, :body
validates_length_of :title, :greater_than => 20
# ...
end
You'll need a pretty intense controller action to facilitate the above process, but it shouldn't be too difficult. In the rest of your application, make sure you run your queries on the Article model to only get back valid ones.
Hope this helps!
Using one model should be straightforward enough. You'll need an attribute/method to determine whether the validations should be performed. You can pass :if => to bypass/enable them:
validates_presence_of :title, :if => :should_validate
should_validate can be a simple boolean attribute that returns false when the model instance is "provisional", or a more complicated method if necessary.
I have a model called Contacts.
Contacts can have different status "bad, positive, wrong..."
These status may need to be changed over time, but across all contacts, they are the same options.
Should I model it this way:
Contacts.rb
belongs_to :status_contact
StatusContacts.rb
has_many :contacts
Then I manually populate the types of status in the table?
I then want to use Ajax to click a button corresponding to a value to update the value for Contacts.
It looks like you're trying to ensure that the values for your status are always going to restricted to a set of possible answers of your choosing. If that's all you're trying to do, there's no special need for a separate table. You can use the magic of ActiveRecord validations instead here.
First, create a string database column for Contact called :status.
Then you can use a validation to ensure that the values are limited to the ones you want. In Rails 3, you can do it like this:
validate :status, :inclusion => { :in => %w( bad positive wrong ) }
(If you're using Rails 2, use #validates_inclusion_of instead.)
In ActiveRecord, validations check that the object's values are valid before saving; it refuses to persist the object into the database until all validations pass.
Your naming strikes me as a little weird—ContactStatus sounds a little nicer to me—but I see this as being the general idea to achieve what you want.
No clear answer yet --- I think I need to use the table because it would allow the users to add and modify the types of status used across their application.