I'm building a data entry intensive RIA using backbone.js. My first plan was to have "Save" and "Cancel" buttons on my UI and to only save my models in big chunks whenever the user hits save. Hitting cancel would simply reload the model from the server. This way, users don't need to worry about making irreversible mistakes.
I'm however now realizing that implementing undo/redo would probably not be so difficult given how easy it is to "watch" for changes on models and have a view correctly update itself when reverting model values. If I had undo/redo, I'd then choose to have my models save to the server instantly.
Is one of the two approaches favoured by backbone? What's a good way to implement the undo/redo using backbone's style of MVC?
You've been waiting a while for this answer, maybe you've answered it already. I do not have code, but a couple of concepts struck me off the top of my head.
From a high level, I would have a base model that was undoable -- or maybe you could use some form of mixin to give a model the ability to be undoable. The implementation of the undo would use the command pattern to form a multi-level undo 'stack'.
If I were implementing this, I think I might equip an undoable model with a backbone.js collection of command models. These command models would encapsulate the changes to the undoable model and would be created in conjunction with a change event from the model. To undo a change to the undoable model, you would pop the top command off and have it apply its undo to the undoable model. A server refresh would wipe away the collection of commands.
The one complication to all of this is how to manage through the changes that occur due to an undo -- these themselves should not generate an undo command to the top of the stack.
Hope this helps.
Related
This question is purely conceptual, it does not include any code.
I am building an app with a single User model. I would like to give users the freedom to choose from 3 different site styles. These styles will affect other components of the UX, including a Message model and messages controller.
I am thinking the best way to go about this is to give each user a "style" column, and based on which site style they choose, either save the value as a string or an integer into the users table.
I have concocted a way to use the same Message model and messages controller, and the same actions inside the messages controller, for all three of the different types of users. Within each of the actions of my messages controller, I would basically start off by querying for which "style" attribute the current user has in their corresponding database row. Based on the three possible "styles", I could then use an if-else or a switch statement to complete the right thing inside of the controller action, depending on the current user's style, including rendering a "style"-specific template rather than the default view template.
Is there a better way to go about accomplishing this? Is it completely discouraged altogether? Am I better off just creating 3 different messages controllers, would that be more RoR conventional and less damaging to the performance of the app?
How catastrophic would it be for the performance of my app if I were to follow this approach with the actions of my messages controller and maybe even two more controllers?
Thanks in advance for any insight anyone can give me :)
I've done very similar things with little-to-no performance impact. As long as the changes are purely HTML/CSS/JavaScript this can be easily accomplished with a working knowledge of the Rails Asset Pipeline and a single column in the database. You'll end up hitting more if-statements in your views, but those handful of boolean expressions will have a negligible effect.
Just make very sure that your alternate view styles don't affect your Controller or the Models themselves (save any methods and validations pertaining to your new column in the User table).
Be sure to dish out unique scripts and stylesheets based upon which style the user has selected (it would be woefully inefficient to load a single stylesheet and dynamically change classes to use certain elements, for instance. Instead you'd want to choose which stylesheet to include based upon the user's selected style, and do the same for scripts).
If you have any specific questions about implementing this, feel free to inquire further. In the mean time this will prove to be an important read, if you are not already familiar with the material.
I started with a simple controller which would allow a user to create a single instance by selecting a user from a collection select. Initially this was fine but the users ended up needing to perform this action twenty or more times.
To ease the burden on the users I want to change this from selecting from a drop-down to selecting multiple items using check boxes. This turned my simple controller into a complicated function that required a transaction to ensure all or none of the records were created and ended up breaking things in the view such as reporting errors.
What is the best design pattern for this using Rails? Basically I'm looking a good way to do a batch create that still works with the traditional Rails MVC. This must be something that has been encountered numerous times before but I can't seem to find a solution that doesn't require some hacks.
To clean up your controller, you can use Service Object pattern.
https://netguru.co/blog/service-objects-in-rails-will-help
Probably you can split your logic into multiple classes.
This may be a really stupid question, but I do not have it clear in my mind as to how it is best to manage this so want to put it down here and see what is common practice.
Coming from .net my web applications are never 1 project which is everything, I tend to at least have a data layer project which deals with persisting entities to the database and making these models represent said entity in a DB friendly manner. Then I have my UI project which has its own models which are a representation of the entity for the UI, which may have validation based information and will most likely be a more cut down model only exposing what is needed.
So the main point I am trying to get out here is that although we may have a User entity, the models to represent that may be slightly different in the UI and Data layers...
Now fast forwarding to rails, you create your project and it comes with database connectivity (which I believe can be swapped out to any flavour you want), and validation and a whole manner of other frameworks and functionality. This then seems to imply that I no longer need 2 projects, just 1 as its all included within here and all done for me, so all I need to worry about are making my models.
This is the part where I am a little confused, as lets say I am using ActiveRecord I will need to make my model and inherit from ActiveRecord::Base, then I will need to setup how this model connects to other models etc, so I have my model's data concerns sorted, now I need to setup my UI concerns, about validation and string lengths etc... now where do these go... I am assuming on the same model, but then a model isnt just a simple representation of data, its a blob of stuff containing concerns for databases and views and who knows what else.
It just seems a little odd to put everything within this one place. I know in .net there are plenty of examples where with large object graph representations in the DB the data models are VERY different to UI models, so is it wise to couple them into one model this way, or is Ruby and its frameworks so flexible in this area that you do not have these same problems? If so is there some example or article which can solidify in my mind how you sidestep the normal problems that cause you to separate your concerns to have maintainable code...
=== Edit ===
Just to try and clear up any confusion, in my post when I say my view models and view concerns, I do not mean presentation concerns. I am sorry if it came across that way. What I mean is that I may have (in a normal .net example) a UserStorage model, which has concerns about persisting a User entity. I then in the ui layer have a view which displays many users and one that displays single users in more detail. You may have 2 differing models here a UserSummary model and a UserDetails model, both partially represent a User entity, but are customised for the actual view in question, as you may get to a situation where UserDetails also becomes a composition of a User and a Company entity, which would mean there are 2 storage based classes feeding into 1 view based class.
Within the examples and guides it makes out like you should have 1 view model which deals with these concerns, as well as storage concerns, and in this case it just seems like if I were in the situation where I had a view model that was a composition of a User and Company it would seem odd for this view layer class to worry about its storage, as its never stored as itself, it is stored as 2 separate models in the database/datastore.
This is the REAL problem I am trying to get at here, it seems to be tightly coupling your view to your storage concerns which I am used to being 2 different things which should never be mixed... like putting your main course and pudding on the same plate...
In vanilla Rails, there is no such thing as a "view model".
The models handle all business logic, including query and persistence, association, and validation. You seem to be dismissing validation as a concern of the view, but this is actually a core concern for the integrity of your models: it does belong there.
That's not to say that validation shouldn't happen in the view (client-side) too, but the model has your core business rules and is the place where the validation rules are ultimately checked.
You will want your models to hold most of the logic of your application. This means things like checking if a user is valid or active, finding related records, etc. Pretty much anything that isn't presentational belongs in the model.
In the view, Rails provides helper methods for formatting. These come from modules that are included in the view instance. Helper methods have access to the instance variables of the view (your models) and are used to present them.
In some situations, passing naked models into the view makes it hard to keep things modular and organized. Some people prefer using Presenters to wrap the models before passing them to the view. It can help to organize your code, but it's also an extra layer. Presenters are not standard in Rails, but it's trivial to add this pattern using plain ruby objects or a library like draper if it makes sense for your application.
EDIT: Oh look, a most excellent blog post on just this very topic came up today, from the most excellent Thoughtbot.
In a nutshell:
if it's about the data (storage, integrity, etc.) it goes in the model
if it's about processing/calculating the data (e.g. finding all pending orders) it goes in the model
if it's about presenting the data (pending orders should have a red cancel button) it goes in the view
Since you seem to be an experienced developer, you'd probably benefit from this book http://www.manning.com/katz/ Its geared towards developers that are new to Rails (but not to web programming).
Alternatively, there is a free online tutorial also http://ruby.railstutorial.org/
And of course, the Rails guides are always a good source of information: http://guides.rubyonrails.org/
Not one mention of MVC in your question, you should look into the Model View Controller pattern.
You should also look into how migrations work.
I have a Rails 3.1 "blog" type app and my Post#index has become a sort of overview (or dashboard or sorts) into the whole system. The main content is pulled from the Post model but a sidebar contains info from an Event model, there are other snippets from a News model, etc…
Post#index is a busy action that has to populate many instance variable before /view/posts/index.html.haml gets a call to render and then the many layouts and partials go to work.
Being as some of these other areas are self-contained, so to speak, I'm wondering if there's a better "Rails way" to approach this? Perhaps I should be looking at encapsulating the Event sidebar (which is effectively Event#index) into some kind of entity that can be re-used perhaps in other views? And, if so, how?
What are the options?
You might checkout
http://cells.rubyforge.org/
I would look into widgetizing it. A framework that I looked into in the past was: http://apotomo.de/ This provides a nice clean way to widget"ize" as well as callback functionality (Ajax) for specific widgets.
I have an application, built using MVC, that produces a view which delivers summary information across a number of models. Further to that, some calculations are performed across the different sets of data.
There's no clear single model (that maps to a table at least) that seems to make sense as the starting point for this, so the various summaries are pulled from the contributing models in the controller, passed into the view and the calculations are performed there.
But that seems, well, dirty. But controllers are supposed to be lightweight, aren't they? And business logic shouldn't be in views, as I have it as present.
So where should this information be assembled? A new model, that doesn't map to a table? A library function/module? Or something else?
(Although I see this as mostly of an architectural/pattern question, I'm working in Rails, FWIW.)
Edit: Good answers all round, and a lot of consensus, which is reassuring. I "accepted" the answer I did to keep the link to Railscasts at the top. I'm behind in my Railscast viewing - something I shall make strenuous attempts to rectify!
As Brian said, you can create another model that marshals out the work that needs doing. There is a great Railscast on how to do this type of thing.
HTH
Controllers don't have to map to specific models or views. Your model doesn't have to map one-to-one to a database table. That's sort of the idea of the framework. Separation of concerns that can all be tested in isolation.
Why not create a model that doesn't inherit ActiveRecord::Base and execute the logic there (think the Cart class in Agile...With Rails).
Controllers don't have to be that lightweight.
However if you have some calculations that only rely on the model/s then you probably just need some sort of model wrapper for the models to perform the calculation. You can then place that into the API for the view so the view gets the end result.
You don't want the logic to be in the view. However you are free to create a database view. Except, rather than create it on the database side, create it as a new model. This will enable you to perform your calculations and your actual logic there, in one place. The pain of trying to keep your views in sync vs. the one time "pain" of creating the new model... I vote for a new model.