Reputation: 1087
OK, this is working but I feel there is a better way to do this in Rails... I have a home page which, if you have not signed in, is not currently pulling in anything from any model or controller. It exists at /pages/home.html.erb
On that page, I want to grab the next party from my Parties model and tell the website visitor about that party. Easy enough, right?:
/app/controllers/parties_controller.rb
def nextparty
@party = Party.find(:first, :order => "begins_on")
end
Now, in my home page, I used this and it works fine:
/app/views/pages/home.html.erb
<% @PartyCont = PartiesController.new() %>
<% @party = @PartyCont.nextparty() %>
<h3>The next party is <%= @party.name %></h3>
I tried helper methods, partials, ApplicationHelper, but this was the only code that actually worked. Most of the other things I tried seemed to fail because the @Party class was not instantiated (typically the error indicated the class with a temporary name and "undefined method").
Hey, I'm happy that it works, but I feel like there is a better way in Rails. I've seen a few posts that use code like the above example and then say "But you really shouldn't ever need to do this!".
Is this just fine, or is there a more Rails-like way?
UPDATE: I think the problem is more than just elegance... I just realized that all RSPEC tests that hit the home page are failing with:
Failure/Error: get 'home'
ActionView::Template::Error:
undefined method `begins_on' for nil:NilClass
Thanks!
Upvotes: 0
Views: 84
Reputation: 1635
Your view should only show data that already was made available by your controller. You want to display a party resource, so the request should go to the parties controller. If I understand your use case correctly, than more specifically to the index method on the PartiesController.
There you should have the following code:
def index
@party = Party.find(:first, :order => "begins_on")
end
That instance method will be available in your corresponding view app/views/parties/index.html.erb
<h3>The next party is <%= @party.name %></h3>
To make this available as your homepage you will have to adjust your route as well: config/routes.rb
root :to => "parties#index"
Your view should contain as little logic as possible and mainly be concerned with how things look. Your controller should get data for the view ready and make sure to call the right method on the model. All the heavy business logic should be in your model.
I think you should work through a basic introductory Rails tutorial.
Upvotes: 0
Reputation: 3409
You want a controller behind every view and you don't want views crossing controller boundaries in order to present information. Consider having a welcome controller (or whatever you prefer to call it). It can have an index action:
def index
@party = Party.find(:first, :order => "begins_on")
end
In config/routes.rb, make it the root controller action:
root :to => "welcome#index"
Also, to DRY that up add a .nextparty class method to the Party model and call that from both of your controller actions instead of the find method.
Upvotes: 2