Rails - moving code from view to controller - ruby-on-rails-3

This is a sort of a "best practice" question but even if its not a good practice, I'd still like to know the implications of doing this type of coding - in terms of usability, scalability
according to http://rails-bestpractices.com/posts/24-move-code-into-controller
you should not instantiate a variable from the view, but do it in the controller first
so instead of <% #posts = Post.find(:all) %>
it should be #posts = Post.find(:all) in the corresponding controller
when running rails best practice gem on my code I got that error on a line that looks like
<% #msgs_by_sender.keys.each do |uid| %>
<% #user = User.find(uid) %>
which basically uid is the a user_id taken from the array of a previously calculated array in the controller. Then once I get the uid I get the #user so it's easier to work with
My question is - since I know this code works and nothing exploded, I don't mind leaving it as it is. But are there any long term advantages to having instead this kind of line
#users = User.find(#msgs_by_sender.keys)

The original post you cited doesn't say "never instantiate a variable in a view", but what the best practice says is "not to include logic in the view". The purpose of the view is to display data. Logic should be in the controller or the model depending upon the type of logic it is. This is part of the MVC philosophy which, in the long run, helps keep your code more scalable and maintainable. The view may need to assign a local variable to help with details of the view, like choosing which class to use on a display element depending upon a data value. There is such thing as "view logic" which belongs in the view. If it's a little elaborate, the convention is to use a "helper" function which would go into the helpers folder.

Related

When does a method warrant being defined in the Model instead of Controller? (from Chap 10 of Rails Tutorial)

I am currently going through Hartl's Rails Tutorial, and through the first 10 chapters or so have gotten used to the convention of putting most of the actions/methods in the controller. Currently, as the book is going through and defining a feed method for the Microposts, the method is placed with the User.rb model instead. As I am relatively new to the world of rails (and programming in general), I was wondering what the rationale or convention followed for putting this method (copied below) in the Model?
The method placed in the User.rb model:
def feed
# This is preliminary. See "Following users" for the full implementation.
Micropost.where("user_id = ?", id)
end
There is actually quite some contention on what code to put where, but in general, there are some easy guidelines to follow.
Does the method have to know some detail about the underlying data structure? Put it in the model.
An easy way to determine this is when it uses ActiveRecord methods like find, where, or specific columns in the database. By keeping this logic in the model, that means if you need to change the underlying datastore, you only have to change the model.
Does the method have some say in how a page is going to be rendered? Put it in the controller.
Generally, controllers should be pretty thin, pushing data to views and saving form data back to models.
While (if I remember correctly) Hartl does not take about non-rails classes, don't be afraid to put 'business logic' outside of the rails structure. You can create a app/lib or app/services or app/x directory and put plain old ruby objects in there, which can then be called from your controllers and models to handle those things they are good at.
Aim to 'push' things 'up' into the model as much as possible, then they will be repeated less and available to more. Don't just use models for Active Record database tables.
You can often unit test models easier.
Another 'next' place to put stuff that is shared is in /lib

ViewModels or ViewBag?

I'm fairly new to MVC4, EF5 and ASP.Net, and I don't seem to be able to find a good answer anywhere.
Basically, Should everything be done through the viewmodel or is it Ok to also incorporate viewbag?
Say I have a method which populates a drop down list, and I am using a viewmodel to represent the output for the view.
Am I ok to use Viewbag.DropDown = PopulateDropdown(); or would it be better to incorporate
this into the ViewModel, by creating a property to hold the List<SelectListItem> created by PopulateDropdown(); ?
I know how handy ViewBag is, but I'm yet to see any solid reason as to not use it? If anyone could also offer me some more insight, that would be fantastic.
Basically, Should everything be done through the viewmodel or is it Ok
to also incorporate viewbag?
Everything should be done inside a view model. That's what a view model is. A class that you specifically define to meet the requirements of your view. Don't mix ViewBags with ViewModels. It is no longer clear for the view where is the information coming from. Either use only a view model (approach that I recommend) or only use ViewBags. But don't mix the 2.
So in your particular example you would have a property on your view model which is of type IENumerable<SelectListItem> and inside your view you will use the strongly typed version of the Html.DropDownListFor helper to bind to the model:
#Html.DropDownListFor(x => x.ProductId, Model.Products)
Obviously those are only my 2 cents. Other people will say that mixing ViewModels and ViewBags is fine and I respect their opinion.
Prefer ViewModels over the ViewBag wherever you can. Create Strongly typed views. It makes your code cleaner, less fragile, less error-prone, and easy to maintain.
ViewBags are just dictionaries of dynamically typed objects so you lose:
Compile time checking
The ability to refactor with confidence (you lose the support of the tools)
IDE support - such as the ability to navigate to all usages
Intellisense
For bonus points making extensive use of the ViewBag also misses the point of using the MVC pattern
I get the impression ViewBags were created to solve an edge-case problem in asp.net and people use them instead of creating view models as was originally intended in the design of the platform, to the detriment of their work.
with thanks to Why not to use ViewBag heavily?

Ruby on Rails, Split Model into Two Controllers/Forms, but update action calling parent

I have a model that for edit/update actions only is logically split into two forms. The model is Venue. I created app/controllers/venues_controller.rb. The two sub-forms are Details and Policies, so I created app/controllers/venues/details_controller.rb and app/controllers/venues/policies_controller.rb, as well as their corresponding views. The child controllers do inherit from VenuesController. I added the venues namespace to my routes, so it now looks like:
resources :venues
namespace :venues do
:details, :policies
end
The routes work correctly, the correct views load, the "edit" action on the sub-controllers is called correctly. However, in the sub-views, I'm using the RESTful form_for(#venue), so when the form is POSTed (PUT) it is going to venue_path, not venue_details_path.
I looked at the docs for form_for and can't figure out a way to keep my sub-forms restful. You can add a token for a namespace a la form_for([:namespace, #model]), but in my case, the model name is the namespace, so it's inverted.
I really don't want to split the model itself, since that has other implications that would be harder to address.
So far, I see two solutions, both of which I don't like:
1. Let both views POST to VenuesController#update and deal with any differences there (more lame controller code)
2. Use form_tag and _tag helpers (more lame view code)
Am I missing something obvious? Is there something different I can do in the routes, or is there another way to call form_for?
I've scanned some posts about Presenter and Conductor patterns but they don't seem to fit this problem. I've read a few stackoverflow threads about whether creating two controllers for one model koscher (it is), but nothing about this specific issue.
Ah, found it. form_for(#venue, :url => venues_detail_path(#venue)). Gotta love Rails.

cakephp how to refer to the model with a variable in the controller

I want to refer to $this->Model-> ... in the controller. But I want to make the functions generic, so how can I use do that dynamically? I tried $this->$modelname but of course that didn't work.
The CRUD functions will be generic to all models and thus all controllers, with overriding in a couple of cases.
EXAMPLE: Two controllers, one for each model -- Letter and Email. There is letter controller and email controller. Each has CRUD functions. The views are essentially identical, except the models track different information for each (e.g., Letter with send_method). The only thing that varies between them is the fields. I have automated that part, but the controllers are essentially the same thing as one another except for a few minor variations. I want to have a parent class and have it use the model name of the particular model, so I don't have to keep making changes to every controller every time I make a change. But in some instances I need to refer to $this->Model-> ... and I don't know how to do that.
Commplete rewrite based on clarification of OP
At the top of letters_controller.php add:
$this->defaultModel = 'Letter';
And in emails_controller.php add:
$this->defaultModel = 'Email';
In either controller, to reference the model, call
$this->{$this->defaultModel}->function();
Sounds like you're trying to re-invent the wheel: have you checked out the CakePHP Scaffolding section?

Pass object to before_filter to perform additional logic before create

I need perform some extra logic on an object before it is saved to the database. I would assume that using a before_filter would be the correct way to accomplish this, but I'm not sure how to pass the object to be saved into my before_filter method.
This is my first ever post here so go easy on me!
Theres a before_save method, in Rails 3 at least, that can be called in the model.
in Posts model
before_save :add_url_and_ID
def add_url_and_ID
#extra logic
self[:url] = whatever.com
self[:member_id] = member.id
end
I'm probably way off but its my first go!
That all sounds like model code to me. To get the most out of Rails (or any MVC framework) follow the 'Fat Models, Skinny Controllers' rule of thumb. It can be taken too far, but I think in this case it's pretty clear. If there are errors with the helper functions you mention, shouldn't the save action fail with appropriate error messages?
There's lots of good posts on SO on this subject. Here's one
If this doesn't give you enough to work with I'd suggest posting some code.