How to create nested files in welcome view rails - ruby-on-rails

I have 2 folders with some views that I want to display on the welcome/main index of my rails app.
Views
Main
Owner
info.html
I can route to the file but the controller for main has no direction on how to get there. I tried
class MainController < ApplicationController
def owner
def info
end
end
But I know this isn't right. What do I need to do?

There are 2 ways you can handle this,
Using namespaces,
# app/controllers/owner/main_controller.rb
module Owner
class MainController < ApplicationController
def info
end
end
end
# app/views/owner/main/info.html
<html>...</html>
Note the change in file structure of view
or with explicit render with name of view
class MainController < ApplicationController
def info
render 'main/owner/info' # Relative path from app/views
end
end

Related

render in routes RESTful routes

I'm not exactly sure if I have a clear understanding what rendering means in RESTful routes.
For example:
In my Pages controller,
class PagesController < ApplicationController
def home
render "home.html.erb"
end
end
on my routes.rb file
i have the following:
get "/" => "pages#home"
does render home.html.erb mean output the info on this page?
Thanks!
Yes. render does the work of rendering your application’s content for use by a browser when your action is invoked. You don't really need to explicitly specify the name of the view if your view name matches the action name and placed in the right folder in app/views
for eg, if you have your view in app/views/pages/ , your controller can just be
class PagesController < ApplicationController
def home
end
end
And even if you want to render a template which name is different than the action name (or localized in another place); you don't need to specify the file extension, only its name (path/name if outside the scope of the designated folder for the views of your controller)...
Ex, if you have a template app/views/pages/home_template.html.erb for your home action you could do
class PagesController < ApplicationController
def home
render 'home_template'
end
end

Insert on controller action into another controller action

I am trying to add a controller action into another controller actions because I have an index page that lists a bunch of files. On that same page, I have a file upload sheet and I would like to call the document#new controller#method with the Home#index controller method. I tried include, but it gave me a uninitialized constant HomeController::DocumentController error. Any help appreciated.
class HomeController < ApplicationController
def index
if user_signed_in?
#show folders shared by others
#being_shared_folders = [] #current_user.shared_folders_by_others
#show only root folders (which have no parent folders)
#folders = current_user.folders.roots
#show only root files which has no "folder_id"
#documents = current_user.documents.where("folder_id is NULL").order("name desc")
include DocumentController::new
else
redirect_to sign_up_index_path
end
end
end
class DocumentsController < ApplicationController
def new
#document = current_user.documents.build
if params[:folder_id] #if we want to upload a file inside another folder
#current_folder = current_user.folders.find(params[:folder_id])
#document.folder_id = #current_folder.id
end
end
end
You can store actions in a common module, and include that module into whatever controller needs it:
# lib/common_actions.rb
module CommonActions
def index
# whatever
end
end
# app.controllers/home_controller.rb
class HomeController < ApplicationController
include CommonActions
end
# app.controllers/documents_controller.rb
class DocumentsController < ApplicationController
include CommonActions
end

How to change index method in my controller to be more DRY

I'm a Rails beginner and I learn that I always must try to be more DRY.
I'm have a comment system associated to my content model, and I load my comment with ajax on page scroll.
In my view I have:
%section.article-comments{'data-url' => content_comments_path(#content)}
and in my routes.rb file I have the route
resources :contents, only: :index do
resources :comments, only: :index
end
My comment controller of course is
def index
#content = Content.find(params[:content_id])
#comments = #content.comments
render ...
end
Now I want to add comments also to videos and gallery.
So I need to add a route for every resource and I need a gallery_index and a video_index.
Content, video and gallery index method in comment controlelr are repeated, and I cannot understand how can I be more DRY.
All your controllers presumably inherit from ApplicationController:
class CommentsController < ApplicationController
If you find yourself with a lot of repetition in any of the controller methods you could define it in ApplicationController instead, with maybe some specific processing in each controller.
For example:
class ApplicationController < ActionController::Base
def index
...some common processing...
specific_index_processing
end
private
def specific_index_processing
# empty method; will be overridden by each controller as required
end
end
class CommentsController < ApplicationController
private
def specific_index_processing
...specific procesing for the comments index method...
end
end
And of course, if one of your controllers needs to be completely different from this common approach you can always just override the entire index method.

How to reuse the rendering actions from nested controllers in Rails?

I have a question regarding the reuse of code among controller actions. I think it is a fairly standard situation, so I am interested in what's the best practice in Rails.
Let's say I have a films resource with a corresponding FilmsController, which has a nested resource comments served by CommentsController. The nested resource can be rendered on its own using its index and show actions. However, it should also be possible to render the comments embedded in the corresponding film page.
Now, the question goes, what is the best way to reuse the code from CommentsController within FilmsController.show?
1) Force the CommentsController.index to render to a string and then pass it in a variable to the film view?
Or 2) call the CommentsController.index directly in the film view as a kind of "partial", executing the database queries from there?
Or 3) create a separate method in CommentsController responsible for the database handling, call it from both CommentsController.index and FilmsController.show, and use the corresponding view in both the places, too?
To me the options 1) and 2) seem a bit messy, while 3) is not modular and involves some repeating of code. Is there any better way to accomplish this?
Thanks a lot!
Now, the question goes, what is the best way to reuse the code from CommentsController within FilmsController.show?
You could move the shared controller logic into a inside your application controller (or a lib and require it appropriately), a la:
class ApplicationController < ActionController::Base
def foo
#foo = "foo"
end
end
Comments Controller:
class CommentsController < ApplicationController
before_filter :foo, :only => [:index]
def index
end
end
Films Controller:
class FilmsController < ApplicationController
before_filter :foo, :only => [:show]
def show
end
end
For repeated view logic you can move that to a common folder, say your_app/app/views/shared/_foo.html.erb and render that appropriately.
Another option is to place the relevant code into an external module:
lib/mymodule.rb
module MyModule
def foo
end
end
And then you can include the module inside your controller or anywhere you want access to your foo method.
class CommentsController < ApplicationController
include MyModule
def index
foo()
end
end

How to change the default path of view files in a Rails 3 controller?

I have a controller called ProjectsController. Its actions, by default, look for views inside app/views/projects. I'd like to change that path for all methods (index, show, new, edit etc...) in the controller.
For example:
class ProjectsController < ApplicationController
#I'd like to be able to do something like this
views_path 'views/mycustomfolder'
def index
#some code
end
def show
#some code
end
def new
#some code
end
def edit
#some code
end
end
Please note I am not changing each method with render but defining a default path for all of them. Is this possible? If so, how?
Thank you!
See ActionView::ViewPaths::ClassMethods#prepend_view_path.
class ProjectsController < ApplicationController
prepend_view_path 'app/views/mycustomfolder'
...
You can do this inside your controller:
def self.controller_path
"mycustomfolder"
end
If there's no built-in method for this, perhaps you can override render for that controller?
class MyController < ApplicationController
# actions ..
private
def render(*args)
options = args.extract_options!
options[:template] = "/mycustomfolder/#{params[:action]}"
super(*(args << options))
end
end
Not sure how well this works out in practice, or if it works at all.
You can add something like:
paths.app.views << "app/views/myspecialdir"
in the config/application.rb file to have rails look in another directory for view templates. The one caveat is that it'll still look for view files that match the controller. So if you have a controller named HomeController with the above config for the views it'll look for something named "app/views/myspecialdir/home/index.html.erb" to render.
If you want to change the default path for all your views at app level, you could do something like following -
class ApplicationController < ActionController::Base
before_action :set_views
private
def set_views
prepend_view_path "#{Rails.root.join('app', 'views', 'new_views')}"
end
end
And write all your views in the folder new_views following the same directory structure as original.
P.S. - This answer is inspired from #mmell's answer.
The accepted answer no longer works for me. After much wailing and gnashing of teeth, I've managed to find that if render is not called in the action, then the default_render method is called. In my case, I needed to override the default_render message in my controller as follows:
def default_render
render "path/to/views/#{action_name.to_s}"
end

Resources