I have a Game model and GamesController. Currently my index page shows first 10 records from the database for the purpose of the application. However, i want to make another page where all of the games are being shown.
My question is, what's the Rails way™ of achieving this purpose? Is it possible to have the index action of my GamesController to make requests based on what URL i want to render? (Something like http:localhost:3000/all)
Rails 3.1 - How do I organize multiple index actions for the same model?
was the closest to my issue, but the question tackles problem from rails 3.1 dating back to 2012.
You can really only have one index action per controller, but there are a couple of ways you can achieve this.
First, simply create a new action and have a separate page. Think of an appropriate name for it and create the controller, route, and view. You can keep the amount of code to a minimum by having much of the view code in a partial and use that in both views.
The other way to do this, if you really only want one action, is to pass a parameter to the index controller and query the database based on that parameter. For instance:
link_to 'link text', game_index_path(:g => 'all')
will create a url like: http://domain.com/game/index?g='all' and in the controller you can do this:
def index
which_games = params[:g] # should be all in this case
#games = Game.where(:criteria => which_games)
end
You can use this same method to implement sorting and filtering and all sorts of things.
Related
I am working on Todo app now and I have troubles. After sign in, I am on persons profile(first controller), on it I have button for new project(projects controller-2d controller) and after pressing it, appears button for new tasks(task controller-3d controller). How I can put all of this 3 controller's views on one page. Here an example of what I mean(approximately):http://todo.kzotov.ru/
You can put anything you want in the view. You could eager load the projects and tasks and put it all on the profile page. You also don't have to map controllers and views to models, so if the PersonsController or whatever is not what you're looking for, maybe do something more specific like ProfilesController and host all this functionality there.
MVC
You'll be best reading up on the MVC programming pattern -
The bottom line is that if you send a request to your application, it will only hit one controller#action. Your multiple "controllers" should not be something to consider - you should only look at the single controller action you're accessing at that specific time.
To be more specific about this, let me detail how it all works...
OOP
Ruby (on top of which Rails is a framework), is object orientated.
This is not just a fancy phrase - it's a real pattern of programming, which allows you to focus the flow of your application around the data / objects you want to create. The objects in Rails are derived from your Models - collating & organizing the respective data for your controllers
In order to understand how Rails works - you need to appreciate that everything you do is based on objects. Your routes, actions & data all work together to provide the end-user experience we know from Rails. How that happens is down to you.
Specifically, you want to look what what you're accessing
You don't want to load multiple controllers - you want to build several models and show those. This gives you the ability to show the HTML elements / files you want:
Recommendation
I would make sure you can put all your activity on your single view, which will then mean you have to determine your controller's data in order to provide you with the data you need to show:
#app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
def index
#your index
end
end
#app/views/profile/index.html.erb
<%= link_to "task", task_path %>
What you'll probably want to do is create a separate route / method to give them the ability to pull back ajax data when the initial button was clicked. I can detail this if you need it, but what I've given you should be ample food for thought
Im using bootstrap & rails and have a user model and post model..users create posts (collections)..
with bootstrap in the navbar i want the user to be able to click a dropdown which displays the name's of their posts..i did this on one controller with a private method and a before_action but i don't want to do this for all the controllers and it didn't work for the application controller...
is there a better way to do this??
I was doing this
def list
#user = User.find_by_username(params[:id])
#collections = #user.collections
end
and a
before_action :list
at the top of the controller
What's the most semantic way to accomplish this??
If you could move both to your application controller, then it would be available to any controller. More generally, I'm not sure if this is the best approach to solve your problem.
These tips might also be useful.
Are you using devise? Or some other authentication plugin? If so you're likely going to have a current_user helper. This would allow you to simply do #collections = current_user.collections
To the extent possible, I recommend using more descriptive names for your actions and parameters. def fetch_list_collections might be a better name or instead of passing a param named id, perhaps your param should be named username. These naming conventions become extremely important both for others who might look at your code as well as for yourself if you return to it and are trying to remember what you wrote N months ago.
Your list action is generating a N+1 queries. Meaning that you're hitting the database multiple times when you should do so just once. See the rails guide on this. You might also look at ways to avoid this w/ devise. Devise is pretty well documented and I'll bet there is something in the wiki discussing this.
You may want to consider limiting when you call this action - at a minimum - a post request to an update action? What about before they've logged in? current_user might be nil and you'd have an error attempting to call a collections method on nil.
Take your time learning this stuff. You don't have to learn it all at once, but I thought the above might be helpful.
I got it to work with this in the application controller
before_action :list
private
def list
#collections = current_user.collections
end
thanks #arieljuod
i am new to RoR and I am a little confused on this topic. Is the scope of variables in the controller only accessible in it's corresponding view?
for instance say I generated a Post scaffold (with blog_text and title). I also generated a controller called static with a home page view/controller resource. Is there any way I can access/print all of the posts from within my home page view? would i have to do something in my static#home function? I cant jsut do Post.all correct?
The controllers are tied to their corresponding views. But you need to use an instance variable (a variable with '#' in the front e.g. #variable) if you want to be able to use the variable in your views. Also, it doesn't matter what model/view/controller you're in when you request data from your db. So in response to your question, yes you can just do something like
#posts = Post.all
in any controller and then access the posts in your views. This is pretty basic stuff, you should study the guide a bit more.
I am using Ruby on Rails 3.2.2 and I would choose the right way to proceed when I have to index "filtered" records rendering the same views.
That is, I have articles that are created by an user and those that are not created by that user, and both can be indexed by that user. Since I have to display those records "filtering" articles that are created or not by the user, I thought that a way to handle this situation is the following (in the ArticlesController class and by rendering the same view):
def index
#articles =
case params[:filter]
when nil
Article.all
when "created_by_me"
Article.created_by(#current_user)
end
...
end
Is the above the "right" way to proceed? Or, maybe, I should implement a new controller action like, for example, index_my? Or, maybe, something else?
It is much better to add a filter param to index than build several different index actions. It also allows you the flexibility to add more filters without having to add even more duplicate index actions.
So I am creating a ruby on rails application and in my view I have a list of link_to with each being a different console
In my database table I have a field called console.
What I want to do is when a user clicks on a link e.g. Playstation 3, it will return back all records that have Playstation 3 listed in that table column.
I was wondering how I would go about doing this, I have tried searching on the internet but have not found anything similar.
It is for a project that I don't have long to complete. I was owndering what I would state in the link to's in the view and what I would put in the games_controller.
Any help would be much appreciated.
The basic gist is to have a controller action which will return the list of games filtering by console. For example,
# GamesController.rb
def index
#games = Game.find_by_console(params[:console])
end
Then you can create a link for any particular console as such:
link_to 'XBOX', games_path(:console => 'XBOX')
This should result in a GET request to the URL /games?console=XBOX
If you've got a pre-defined set of consoles, you might look into making them into constants inside a Consoles module to avoid having to hardcode them everywhere.
UPDATE:
Since you are trying to implement both searching and filtering in the same chain, you need to make sure that find_by_console isn't called if it's not present.
# GamesController.rb
def index
#games = Game.search(params[:search])
#games = #games.find_by_console(params[:console]) unless params[:console].blank?
end