Grabbing all validation methods from a model in rails - ruby-on-rails

I am working on a project that will take custom validations on models and translate them into javascript to be run on the client side. We are currently passing in the model, and the validation method (as an UnboundMethod ).
JStranslator(model, Validator.instance_method(:validate))
What I want is to get all the UnboundMethods that get used for validating the model because our translator leverages the AST representation of the methods (using 'live-ast'), therefore the model_name.validators will not work (it returns an array I think). I need to get all custom defined validation methods that are defined inside the model itself as well as all validators the model uses.

Validations are stored as callbacks, so you may want to play around with those:
Model._validate_callbacks # do something
Resources:
https://github.com/rails/rails/blob/master/activemodel/lib/active_model/validations.rb
https://github.com/rails/rails/blob/master/activemodel/lib/active_model/callbacks.rb
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
Happy to help more if you get stuck.

Related

How to handle a single form to update multiple unrelated models?

I am working on a legacy Rails 3.2 application that has a lot of settings a user can manage. Settings are associated with 3 types of model in the system: User, Company and CompanyUser. In order to avoid having to write database migrations each time a new type of setting is added
I've essentially created a key/value store (1 row for each setting) that has a polymorphic association with each of the above mentioned models. A base Setting class handles all of the common functionality like setting the key, relationships etc. each type of setting extends the base class and can contain it's own validation and/or logic. For example:
class Settings::EmailSignature < Setting
validates :whatever
end
For any model that requires a setting I've implemented a has_setting helper method that sets up the association and provides some delegates to directly get and set the setting without needing to go via the associated model object, the User model might look like:
class User < ActiveRecord::Base
has_setting :email_signature
end
This side of the code is working well, however the problem I have is when I create the form for the settings. For the user it might make sense to have User, Company and CompanyUser settings mixed together in the same form. Using nested attributes doesn't feel like a good solution in this situation as the settings are not related and there is no common parent object. I've considered using a form object to handle mapping each setting to the correct object but that doesn't feel like a great option either as each setting would require knowing it's id, the associated records id and it's type. This would not be particularly easy to manage when building the form.
I'm about to go down the route of having each setting in it's own form and having the record save automatically as the user edits each item. This would mean only a single record is ever saved at a time and will make things much simpler at the controller layer and also provide a lot of flexibility in how settings a grouped. Before I go down this route I wanted to see if there are any other options for submitting a single form in a single transaction that I may have overlooked?
Please note, this application is written in Rails 3.2 and is not in a state in which it can be easily upgraded to Rails 4 right now so any solutions need to work with Rails 3.2.

Rails: Dealing with child objects on AngularJS

I'm very new to AngularJS and MVVM in general and was looking for the best way to deal with displaying a model that also needs to display a couple of fields from child model objects on the web UI.
At the moment following basic tutorials my model object in my AngularJS controller reflects exactly my Rails model, and so I can't access fields from my child objects and just see their IDs from the foreign key columns in the database.
I'm wondering what the best convention is for dealing with this situation?
do I create a tableless model in Rails that contains only the fields needed by the presentation layer. Me defining what the presentation layer needs in Rails seems like it defeats the point of using MVVM.
do I create something on the AngularJS side that queries for the child objects using those exposed foreign key IDs? If so, how do I optimise it to avoid performing a request for each of my 50 objects in the table.
Yeah! You should define your api to contain all the data needed for a request. You don't need to create a tabless model for that.
If for example a fetch the json for a Post, Author and Comments json representation also should be there, or at least some part of it.
You might want to take a look at https://github.com/rails-api/active_model_serializers or https://github.com/nesquena/rabl

Best way to access session from method_missing in model

I know that model should not be aware of session data but I have a need to access a small bit of state information in the method_missing that is defined on a model. Methods caught by method_missing are invoked by form helpers, i.e.:
client_medias/new.haml:
f.text_field :new_display_name
client_media.rb:
has_many :custom_properties, :as => :extensible
Here 'new_display_name' is a custom property key defined through a polymorphic association. I need to know the context (in my case provided by current_app method accessible in the controller) to get the collection of distinct custom property keys which I am mapping to the dynamic method definitions in method_missing.
Any ideas? I looked into Thread.current and am inclined to use it at this moment.
we have a similar problem, where we are handling multiple mandants in a single application. in our case, the context is the mandant, that is identified through the toplevel-domain the user loads the site from.
our approach is to use the logic within I18n to provide a "singleton" that we can access within every part of our application, like it's done with I18n.locale which uses Thread.current too.
we then set up the singleton in our application controller as a before filter, so that every other part of the application can use it within the same response.
as a starting point have a look at sven fuchs implementation https://github.com/svenfuchs/i18n/blob/master/lib/i18n.rb

Rails 2.3.5: How does one add an error when it doesn't make sense to put it in a validation?

I recently was trying to add errors.add_to_base code in the middle of some model logic and was wondering why it wasn't showing up in my view that was iterating over all errors. I then ran across this e-mail which explains why: http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/e045ec1dead1ff06?pli=1
The question is then, how does one add errors with add_to_base if it doesn't make sense to put them into a validate method? I have some complex logic. The model needs to talk to a has_many relationship which has its own relationships that go through a myriad of conditionals to figure out if a request makes sense. It's nothing that can be tied to a validate method easily.
The one thing that I can do is create an instance variable and push all errors as strings to it while I iterate through my complex logic. After that I can run validate against the array and push those errors to the base object. Seems kind of lame though and not the Rails way of doing things.
Is the bottom line in the Rails community that complex logic, even when the logic spans multiple models, has to be in one particular models validate method? How is it handled when the validation is entirely complex and can span multiple models?
I don't understand why it doesn't make sense to put it into validations. For sure this what you want to do should be in a model, so you have to put it in some method inside the model. Then just add:
validate :my_method
and that's all. Of course if my_method gets too complicated, then split it in some logical sub methods.
If you have many related objects then you should put all validations that belongs to that objects in that objects models and when you try to save "parent" object, "child" objects will be also validated with their validations.

How do I handle data which must be persisted in a database, but isn't a proper model, in Ruby on Rails?

Imagine a web application written in Ruby on Rails. Part of the state of that application is represented in a piece of data which doesn't fit the description of a model. This state descriptor needs to be persisted in the same database as the models.
Where it differs from a model is that there needs to be only one instance of its class and it doesn't have relationships with other classes.
Has anyone come across anything like this?
From your description I think the rails-settings plugin should do what you need.
From the Readme:
"Settings is a plugin that makes managing a table of global key, value pairs easy. Think of it like a global Hash stored in you database, that uses simple ActiveRecord like methods for manipulation. Keep track of any global setting that you dont want to hard code into your rails app. You can store any kind of object. Strings, numbers, arrays, or any object."
http://github.com/Squeegy/rails-settings/tree/master
If it's data, and it's in the database, it's part of the model.
This isn't really a RoR problem; it's a general OO design problem.
If it were me, I'd probably find a way to conceptualize the data as a model and then just make it a singleton with a factory method and a private constructor.
Alternatively, you could think of this as a form of logging. In that case, you'd just have a Logger class (also a singleton) that reads/writes the database directly and is invoked at the beginning and end of each request.
In Rails, if data is in the database it's in a model. In this case the model may be called "Configuration", but it is still mapped to an ActiveRecord class in your Rails system.
If this data is truly static, you may not need the database at all.
You could use (as an example) a variable in your application controller:
class ApplicationController < ActionController::Base
helper :all
#data = "YOUR DATA HERE"
end
There are a number of approaches that can be used to instantiate data for use in a Rails application.
I'm not sure I understand why you say it can't fit in a Rails model.
If it's just a complex data structure, just save a bunch of Ruby code in a text field in the database :-)
If for example you have a complex nested hash you want to save, assign the following to your 'data' text field:
ComplexThing.data = complex_hash.inspect
When you want to read it back, simply
complex_hash = eval ComplexThing.data
Let me point out 2 more things about this solution:
If your data structure is not standard Ruby classes, a simple inspect may not do it. If you see #<MyClass:0x4066e3c> anywhere, something's not being serialized properly.
This is a naive implementation. You may want to check out real marshalling solutions if you risk having unicode data or if you really are saving a lot of custom-made classes.

Resources