I have a Rails 3 partial that lists all categories as a navigation menu - it's on most, but not all of my template pages...let's say about 75%. I'm trying to test the partial (in RSpec) right now, and I've just realised a few things:
At the moment, I'm calling Categories.all in the actual view. The difficulty is that, because that touches the database, my mocks/stubs in the view spec are ignored, and consequently the test fails.
I'm guessing the alternative is to assign the variable in the application controller, and then pass it as a local variable to the partial. Still, about 25% of my pages won't use the variable and I'm wondering if there's a more graceful way of doing things.
In short, I want view specs to pass without touching the test DB, but I'm not sure a global variable passed to my partial is the best way to do it...and I'm not declaring the variable in every (& only) those controllers who require it.
Any suggestions appreciated...
Why not create a helper method for all categories?
# in categories helper
def all_categories
#all_categories ||= Category.all
end
Or...
# application controller
helper_method :all_categories
def all_categories
...
You can then stub out this method in your specs and you won't be touching the DB
Related
I have a Rails app with the Content model. The Content model has numerous STI children models, such as Announcement, Story, FAQ, etc. I need to be able to query Solr via Sunspot for each of the children independently and as a group.
This is the present implementation of Sunspot search in the Content model. It sets defaults for hidden and published, so only active Content is returned by Solr and accepts a block to allow farther search params:
def self.search_for(&blk)
search = Sunspot.new_search(Content)
search.build(&blk)
search.build do
with :hidden, false
with(:published_at).less_than Time.now
end
search.execute
search
end
This method works perfectly for Content and will return results for Content and all the children Models. I am not particular thrilled with the name of the method, search_for, but can't think of anything better.
I need to be able to search by child Model, i.e. Announcement.search_for(). I do not want to have this method pasted into the ~10 child Models, since the defaults are going to change in the near future. What I would like is have each of the children models inherit this method, but search for the child's class, not Content (e.g. Announcement would search by Sunspot.new_search(Announcement)).
Is there are way to reflect the class of a class method or does this method have to be dynamically generated at runtime to pre-define the calling class?
Pretty easy, just pass the instance type rather than Content. Change first line of the function to:
search = Sunspot.new_search(self)
Where self will hold Content if you invoke the method by Content.search_for and Announcement if invoked by Announcement.search_for. That's it!
Is there a way to render a partial view with accompanying code in rails?
For instance: I want to be able to create a partial view which will show the top 5 foobars on my site. This partial needs accompanying code to retrieve some foobars from the database, rank them according to an algorithm, and then output the view with the top 5.
I want to be able to include this partial on any page I fancy, preferably just by using something like
<%= render :action => "top_five_foobars" %>
Is this doable? I'm used to asp.net mvc where you can create an action that runs some code and returns a partial, but it seems like in rails it returns simply the template...
If google get you here, you might be looking for cells
Cells are view components for Rails. They are mini-controllers with
their own MVC stack, can invoke logic and render views. They bring
back OOP to Rails' view layer and make writing reusable portlets for
your applications fun.
You need something like a shopping cart, which appears on almost
every page of your app.
You wouldn't use a partial and a helper, would you?
It might not be the cleanest way, but what I did is that I created a helper method in the Application Controller that retrieves the top 5 foobars. Then I call this method in the views. I also cached the part of the view that shows the results.
I have a Rails 3 controller which is not pluralized (IphoneUser) - it already has some controller methods, and a model generated.
However I'd like now rather than when it gets too late into the game, to pluralize it.
What's the best way to pluralize this controller without a nightmare of 1-by-1 guess and checks?
You should just need to rename the controller, it's class name, it's views folder, its helper and its functional tests. The only other option is to use the rails generator to destroy it rails destroy and then recreate it named properly. I'd just copy the controller methods and paste them into the new file. rails destroy won't affect your model.
I have a problem and I dont know how to solve it.
I have a user that log in a web site, and I identify them by session[:user_id] and user has a status page that is defined in user_controller and in status view.
So, I would like to make one page for admin, to see all the statuses from all users on one page, using already written controller and view.
Is that possible?
I could rewrite some of the code, so that I could call with params, like ?user_id=70 and then set session[:user_id]=params[:user_id], but it would be painful if I will have to rewrite whole statuses, beside i would have to maintain same code on 2 different places.
Thank you.
Dorijan
If you need more functionality in your controller, you can add more actions to it. You can also do that in a resourcefull way.
On the other hand it usually is best practice to keep controllers thin.
See: ActionController
In order to make your views reusable, you should use partials.
You could make a _user_status partial.html.erb and render a single partial for a user render all of them for an admin.
Checkout: Layouts and Rendering in Rails
I have two helper files. events_helper.rb and users_helper.rb.
Both of these helper files have a method called foobar. In events controller, index view. If I call foobar. Shouldn't it load the helper foobar thats in events_helper.rb?
Or is this not the way helpers work?
Seems like all helpers are available - so not sure which it would choose in your case, ideally the events controller one... and from your comment, it seems like its chosen the wrong one.
Could you give them distinct names?
Why are all Rails helpers available to all views, all the time? Is there a way to disable this?