view a Document at one specific point in time? (dup, versioning?) - ruby-on-rails

Mongoid - 2.4.7
I need to store a copy of a Document at a particular point in time.
I'll know the exact point in time
they'll happen manually (defined like an expiration date)
and will only happen once or twice over life of the document.
What's the best way to do this?
Separate Model(s) - Create separate ExpiredWhatever Models and copy the records when they "expire"? That feels a little gross, especially considering the parent has embedded docs, which also has an embedded docs.
Versioning - The built in Mongoid Versioning could work, but I don't need a version stored on every update, only at 1 or 2 particular points in time. So I'd need to be able to manually set this.
(Also this Parent Document is actually embedded itself; however, that could change as I know Mongoid::Versioning doesn't work with embedded docs.)
So, what's the best way to view a Document (and its embedded docs) at a specific point in time?

You will have to manually do this. I would create another key in the parent document named or prior_version or snapshot_version and store the copy there.
You will need to test to see how mongoid handles that assignment and possibly perform a manual deep copy as you have many embedded fields/docs.
I think separate models is overkill and versioning won't work for this application (as you said, you only need one copy)

From the Mongoid docs on Versioning:
You may skip versioning at any point in time by wrapping the persistence call in a versionless block.
person.versionless do |doc|
doc.update_attributes(name: "Theodore")
end
It's a bit cumbersome, but you can have an if statement that switches from versioned to versionless when you want it to. Ie, save versionless most of the time, but when you set a flag, the if statement switches to the versioned save.

Related

Creating a no-database rails model that would serve as a view to index data in elasticsearch

I'm facing a complex problem which i haven't been able to resolve yet.
I'm using Rails 4(edge) with postgresql 9, ElasticSearch 0.20.6 and the gem Tire (0.5.7).
I have multiple table that are linked together. for instance:
Agency has many Clients
Clients has many Projects
Projects has many Files
My goal here is to be able to index Files in two ways:
First have an index that just allows easy and rapid search among all files. That i have succeeded into doing just by using tire. My index has a type "file" and it works like a charm.
The other index I would like to create would have some of the files information but also some of the clients and the agencie's properties. This is for an external tool that would be able to fetch the best files according to criteria like the project's category or the client's location...
As i'm using postgresql, i was thinking i could do a database view and index data from there. I'm not sure it's good to do it like that though cause the view would be pretty complex with multiple joins. Plus i'm afraid that any update would trigger a full-database re-indexing.
I was wondering if there was a way to do a pure-tire model and easily trigger the index update on any of it's linked tables.
For instance, i'll have indexed the data in a type named files_front. I would have a model FilesFront which has_one :file and each time i update a file or any parent, all the impacted files would see their values updated in ES.
I'm really not sure on how to do this, so any advice is welcome.
Having a separate, table-less or standalone model is a good solution. The problem here, I assume, is connecting the FileFront class to the rest of the system. Effectively, whenever you update the File or any associated Client etc. object, you need to update the FileFront object.
You could actually use the Model::Persistence to that. So for each File you'd have an associated FrontFile, which you would assemble as JSON in File and create/update in an after_save callback. The tricky part is ensuring changes to the parent objects are propagated to file, and vice-versa.

Modifying Rails: How do advanced users find out what needs to be changed?

I've been using Rails for a few months now, and I'm quite comfortable writing up a project & manipulating Rails to my needs, etc.
Recently I've been trying to get a little more advanced, so I've attempted to modify/add to the existing rails codebase: add new form helper methods, add a responds_to :pdf method, etc...and I've been having a lot of problems.
The difficulty is learning which code I need to modify; where that code is located, and how to ensure I don't miss related code in other files. I'm guessing there's a way people learn to do this, but at the moment I'm mostly just guessing-and-hoping.
I guess my question is, how do Rails folks go about learning where the code they need to modify is edited & the approach to editing it? It seems like it's just something you need to know from prior familiarity, but I'm guessing there has to be a simple method for understanding where (and what) to edit.
Any ideas appreciated...cheers
I highly recommend Jose Valim's Crafting Rails Applications
You go through advanced projects, building out the types of engines and customizations that will take you to the next level in your Rails development.
From the site:
This book will help you understand Rails 3’s inner workings, including
generators, template handlers, internationalization, routing, and
responders.
What you are asking for is how MVC works. Basicly you can say:
1.) Put logic to the model! The model is the pivot everything turns around.
2.) The Controller is a middleman between the model and the view. You dont put any logic here that isnt related to selecting data from the database that should be displayed in the view. If you use one selection logic more than once create a scope in the Model and use it in the Controller.
3.) The View is only there to display things! You dont put any logic here! All the logic comes from the model and the data comes from the controller. The only logic your using here are loops through arrays of data that should be displayed.
Then you have some things missing. If you have a task that is related to an external service like lets say a SOAP Service you write a class for that too! Just whithout using ActiveRecord::Base inheritance like its generated by the scaffolder. You can call this Class in other models. Dont put this to the controller or copy the code in every class that needs it! Stay DRY (Dont Repeat Yourself). Just write a class for it and include it in the other models!
Another thing thats a Database basic: Dont store data that could be calculated from other fields from the database! You can add methods that calculate the stuff you need but dont start with duplicates.

Un-bloating models in rails 3.1

Just learning rails, developing first app and having trouble finding a straight answer to this question!
I want to keep my models as lean as possible and really only want to use them to represent objects that I might want to render in my views. Therefore, I want to remove some of the logic from one particular model and store it in a separate file. I have seen numerous guides (on this site and others) that suggest the following;
never "require" anything from inside a rails app
Store additional files in the lib folder - they used to be auto loaded in older rails releases but now you need to add an extra line in a config file to get this to happen (Example.
So I added the line, stuck the file in the lib folder, and it all worked fine. So on to the question;
I can't shake the feeling that the fact that I had to go and put some bespoke code into the config file means I'm doing this wrong (given convention over configuration). Why are people having to faff around editing configuration files to get rails to do something so basic?
Is that the best way or are there additional considerations that I'm just not seeing? Should I in fact be creating an "extras" directory rather than still sticking things in lib?
If anyone can point me in the direction of a definitive article on the matter I'd be much obliged!
There is nothing wrong with having non active record models in the model folder. If your domain is best modeled by a business logic layer and a persistence layer, then model it that way in your model folder with appropriate naming conventions. Personally I wouldn't be overly concerned with getting it perfect. Try something and see how you like it.. learn from your mistakes and keep getting better! Above all, enjoy the process.
what I do is this: keep the model logic in the model and keep the controllers as thin as possible
If there are things that should belong to your model but are somewhat distant to it (for example you have an Account model and you're working on some payments system which relates to the Account - for example you might want to call account.has_subscription?, you could use a gem called concerned_with which would split your model's main actions from others like the ones handling payments (this is just an example I recently had to take care of).

Building consumable uri/urls for a model (rails/datamapper/SOA)

Perhaps you can help me think this through to greater detail.
I need to build or make available a uri for a model instance that can be referenced or used by another application which may or may not be a rails application.
e.g.
I create a standard Post with content; I want to build a URL for that post another application can consume or reference by looking at the model in the database (or another less sticky fashion). Datamapper has a URI field, I want to build a canonical uri, store it there and have another application be able to access, announce, manipulate, etc.
Basically, I have several applications that may be in different places, that need to access the same model, to do differing things with the model. I need a way to make that happen clearly without putting them all in one monster application.
I've looked at Pubsubhub, RSS, etc. but haven't found any concrete examples of what I'm trying to do. Do I need to create an common API for the applications, etc?
DataMapper is very flexible about using existing databases.
Many people come to DataMapper because it can create and tear down the database structures without migrations. However, you do not have to work with it in that way.
I have had good success with using a large set of models owned by a central 'housekeeping' app and then declaring a small subset of the same models in separate 'interface' apps.
Some trial and error is required to figure out what works but it can certainly be done. I'd suggest putting your models in modules and including them across apps if possible.
A final point it sounds like you want URIs/URLs to be the primary interface. If that is the case I strongly suggest you look at Sinatra. It is entirely oriented around URLs (and I find Rails routes very obtuse).

Helpers in rails

I'm just starting out in Rails and there's a lot I still need to learn so I'm likely to be on Stackoverflow more often than normal asking beginner Rails / Ruby questions.
I'm just trying to figure out how Helpers work in Rails. From what I've seen so far, Helpers are intended to be used with Views and not so much with your Controllers.
However I would like to make a simple function that will validate the user input given in params (check if certain params are defined and optionally check if their value is valid).
Can anyone explain to me what would be the best way of implementing this? (Keeping in mind that I will want to use this in many different controllers so it should be globally available.)
I also noticed that by default Rails does not generate a lib folder in the main application folder. Are developers to place their libs outside the app folder in the main folder, or does Rails use libraries differently?
With regards to your validation issue, it depends on what you are validating.
If the data makes up objects from your problem domain, also known as models, then you should use the built in validators from ActiveModel. This is probably what you should do, but its hard to say without knowing the exact problem. See the Rails Guides on Validations. You can tell if this is the case by asking yourself if the data that needs validation will be stored after you get it. If so, its most definitely a model. An example of this kind of data would be the title and text fields of a blog post being sent to Rails from a browser form.
If the data is something tertiary to your models, or specific to presentation, then you should be fine using helpers. You noticed that helpers are used mostly in the views, and although this is true, theres nothing stopping you from using them in the controllers, you just have to declare that you will use them using the ActiveController#helper method. Inside the ApplicationController class, a lot of devs will put helper :all to just include all the helpers in all the controllers. Once the code has been required once, it doesn't really incur that big a performance hit.
Do note that almost all incoming data can be modeled using a model. A big school of thought in the Rails world subscribes to the Fat Model idea. People say that putting as much code as possible in the model and as little in the controller as possible separates concerns properly and leads to more maintainable code. This suggests that even if you don't think the incoming data is modelable (in the sense that you can create a model to represent it), you should try to make it a model and encapsulate the logic around validating it. However, you may find that making a helper function is faster, and either will work.
Your notion of validating user input is a good one. I get the feeling that as you are new to Rails you are used to doing these things yourself, but that doesn't quite apply here. In the Rails world, a lot of the common stuff like validations is handled by the framework. You don't have to check for presence in the params array, instead you call validates_presence_of on the model and let Rails spit the error out to the user. It makes things easier in the long run if you let the framework do what it is designed to.
With regards to your question about the lib folder, it doesn't really matter. You can put miscellaneous support files and libraries in the lib folder in the root directory and they will be available for use in your application (the files in the app folder). You can also choose to abstract your code into a plugin or a gem and include it that way, which a lot of people opt to do. My suggestion for this would be to read up on the notion of gems and plugins before diving in.
Want you want is probably a custom validator (in Rails3):
http://railscasts.com/episodes/211-validations-in-rails-3
You can either add libs in a lib folder you create, or add them to config/initializers in a file you add. Files in the initializers directory are automatically loaded by Rails.

Resources