Rails doesn't need index method in controller defined? - ruby-on-rails

I noticed that an index view is routed correctly even if there isn't a controller method index.
As an example, the routes.rb has this route
AppName::Application.routes.draw do
get 'about' => "about#index"
end
My controller looks like this with no index method (def index end)
class AboutController < ApplicationController
end
and I have a view called index.html.erb in the views/about folder
What's happening here? Is this a case of rails magic where they automatically show the view even if there is no controller method? I couldn't find any documentation on this...

If you have the view file, it'll go ahead and render that implicitly, as documented here
See also, this SO thread on how Rails renders your view files and controller actions.

Related

How to change view by controller and action even if that is root path

I have a decorator that changes behaivior by controller and action like this:
class ShortPositionDecorator < ApplicationDecorator
delegate_all
def company_short_name
return if h.current_page?(action: 'positions', controller: 'users')
object.company.short_name
end
end
This is the route for it.
get 'positions', to: 'users#positions'
But when I use the route as a root path,
config/routes.rb
root 'users#positions'
I had to add a condition for root path.
def company_short_name
return if h.current_page?(action: 'positions', controller: 'users')
+ return if h.current_page?('/')
object.company.short_name
end
Is there a way to change view by action and controller even if the path is /?
If I use current_page?('/'), I must change several places for just changing the root path. I want to avoid that kind of mess.
You can use controller_name and action_name to get the current controller/action and create a custom helper:
def current_controller_action?(controller:,action:)
controller == controller_name && action == action_name
end
and use that instead of current_page?...a quick look at the source for current_page? shows that it calls url_for and passes in what you passed to it, so multiple routes in your routes file pointing at the same controller/action aren't going to work well with it.

How does rails homepage works?

Let's say I have a Rails Website or Application
I have controllers for pages and posts
I want to create on my homepage section where I can see all pages and below that section for the posts
What is the common way to do that with the routes.rb? since I have two controller I don't know how to create the homepage
To make your code more clear you can use separated controller for that. For example create HomepageController with action home and prepare all resources you need there:
class HomepageController < ApplicationController
def home
#pages = Page.where(....)
#posts = Post.where(....)
end
end
Create corresponding view file - views/homepage/home.html.erb
Then at the end of your routes.rb add:
root to: "homepage#home"

Routing Static Pages in Rails

I am having some difficulty figuring out how to route static pages in rails 4. I have created a controller called PagesController and so I also have a views folder called pages with the oakville.html.erb file in it.
My controller looks like this:
class PagesController < ApplicationController
def our_mission
end
end
My routes file looks like this:
get "oakville", :to => "pages#oakville"
I am assuming that I should be able to get to this page by going to localhost:3000/oakville ??
Yes, but you need to add a controller action for oakville
class PagesController < ApplicationController
def oakville
end
end
Also, you will need to create oakville.html.erb and put this into your views/pages directory
The methods in your controller are called actions, and for each static page that you want to be able to navigate to you will need a corresponding controller action. When a person (or link) navigates to yoursite/oakville your routes file needs to know which controller action to perform for the oakville branch of the url.
In the routes that you have shown, get "oakville", :to => "pages#oakville" you are asking the controller to render the oakville action. But there is no oakville action in your controller. Add one and problem solved:
class PagesController < ApplicationController
def our_mission
end
def oakville
end
end
The route you've shown and the action you've shown are completely unrelated.
If you want to route a url like http://www.example.com/oakville to an action called our_mission on the Pages controller, the route looks like this:
get 'oakville' => 'pages#our_mission'
What you've written indicates you expect an action called oakville to exist, and according to the code you've provided, it doesn't.

Theoretical: method_missing

I just started to learn Rails and I cannot understand that:
In my Post controller I do not have method show (not described), but I put in my controller that:
def method_missing(name, *args)
redirect_to posts_path
end
I think that if controller couldn't find action show - it would call method_missing and after that redirect to index method, but Rails tries to render view show.html.erb.
Why is method missing not catching? How can I use method_missing?
Rails does not require action to be present in controller if corresponding template exists. It just assumes empty action and renders template, that is why your method_missing isn't invoked.
If you don't need show action anyway - just remove show.html.erb and method_missing will work as expected.

Trouble using a 'before_filter' method and rendering partials

I am using Ruby on Rails 3 and I am trying to understand the behavior of the before_filter method in a controller.
In my controller I have
class UsersController < ApplicationController
before_filter :authorize
def show
...
end
end
If I browse, for example, the page http://<my_web_site>/user/1 (that loads the users/show.html.erb view file populated of data from the User with ID 1) the before_filter works as well. That is, the authorize method does what it must do.
If I render the users/show.html.erb view file as a template for another controller (example: the PostsController) this way
# This code is in the `post/show.html.erb` file
<%= render :template => "/users/show", :locals => { :user => #user } %>
the before_filter doesn't work. That is, the authorize method seams do not run.
Why?! There is a reason for that behavior or I am wrong somewhere?
UPDATE (after the #brad comment)
Are you rendering that view as a
partial template from within the users
controller? If not the before_filter
won't apply
If it is as #brad say in his comment, how can I make the before_filter to work rendering that view for another controller than UsersController?
Move authorize method to ApplicationController
Add before_filter to each controller where you want to check user authorization.
When you render a template or a view file/partial, it is not really treated as a request on your controller, hence the filters dont apply.
Firstly you should understand the routing in the Rails. When you type in the browser http://<my_web_site>/user/1 then it goes to route file, after this to proper controller's action, after that controller initiate the render view. And controller has these callbacks, when some action is initiated then these callbacks should act before or after controller's action. So in your case you're calling partial template without any controller's involving
before_filter applies to controller actions, not rendering actions.
One solution, then, is to abstract your authorization logic out into a helper that can be used when you're rendering your partial:
if authorized?
render :partial => 'users/show'
end
Another solution is to implement authorization at the model level, using something like the declarative_authorization gem (https://github.com/stffn/declarative_authorization)

Resources