Link_to for static pages - ruby-on-rails

I have made a forum-based website, I want to add a few links to my footer like "more about badges" or "how to ask questions". Well, they are static pages so I really don't want to go through controller to go to those pages. For example, I'd like to view views/static_pages/badges.html.erb using link_to or other possible tag.
How can I go directly to some page in my views?

For static pages you should check out high_voltage gem. Once it's installed, it'll make a folder pages inside your view directory and it'll generate a named route method of page_path. For example, if you create a static page pages/static then you can refer it to by page_path('static') in your views.
EDIT:
If you don't want to use any gem then I'll suggest checking out this question

We do it like this:
#config/routes.rb
resources :pages, only: [:show] #-> sends params[:id] as /page_name
#app/controllers/pages_controller.rb
Class PagesController < ApplicationController
def show
render "pages/#{params[:id]}"
end
end
This will allow you to call the following:
= link_to pages_path("badges") # -> domain.com:3000/pages/badges

Related

rails overriding/scoping views for multi tenancy app

I'm wondering how I can scope my views. I want to have custom themes depending on the organization, I can use render directly on the show/index actions... and that works, but I would have to override a lot of actions on my application. I would prefer to do it on the controller level and tried doing it with prepend_view_path but it didn't except the variable as undefined.
class EditionsController < ApplicationController
helper_method :current_organization
prepend_view_path "app/views/#{current_organization.slug}/editions" #doesn't work
def show
#edition = Edition.find(params[:edition_id])
#page = #edition.pages.first
render template: "#{current_organization.slug}/editions/show" #works
end
Any ideas?
Also tried: (with same error)
append_view_path(File.join(Rails.root, "app/views/#{current_organization.slug}"))
custom themes depending on the organization
Surely it would make more sense to define custom layouts & CSS rather than entirely different view sets for each company?
--
I would personally do this:
#app/layouts/application.html.erb
<%= stylesheet_link_tag "application", controller_name ... %>
This will give me the ability to style the different pages as per the theme. Obviously a constriction on what you want, but I hope it shows how you could modularize your controllers etc
--
If you wanted to create different "themes" (IE having a completely different view structure per tenant), you'll want to use the prepend_view_path helper, as described here:
#app/controllers/application_controller.rb
Class ApplicationController < ActionController::Base
prepend_view_path("views/#{current_organization.slug}")
end
Try to remove editions in prepend_view_path
prepend_view_path "app/views/#{current_organization.slug}"
Make sure what the way was added. If it doesn't add before_filter

Removing controller name from Rails URL route

This is my first Rails project, I am trying to piece things together slowly.
When I'm trying to view the page I generated using rails g controller <controller> <page>, I find myself going to 0.0.0.0:3000/controller/page.html, How can I configure it so that my route file globally allows viewing the page via the page name, rather than controller/page, if no such way exists, then how can I route controller/page.html to /page.html
I've looked around, and haven't really found any explanation, maybe I'm looking in the wrong places?
In config/routes.rb:
get '/page' => 'controller#action'
If your controller is:
class UsersController < ApplicationController
def something
end
end
Then config/routes.rb would be:
get '/page' => 'users#something'
For static pages you could want to use public folder though, everything you put there is directly accessible, for example public/qqqqqq.html would be accessed in localhost:3000/qqqqqq.html
We've just achieved this by using the path argument in resources method:
#config/routes.rb
resources :controller, path: ""
For you specifically, you'll want to make something like this:
#config/routes.rb
resources :static_pages, path: "", only: [:index]
get :page
get :other_page
end
#app/controllers/your_controller.rb
def page
end
def other_page
end
This will give you routes without the controller name. You'll have to define this at the end of your routes (so other paths come first)
Obviously this will form part of a wider routes file, so if it doesn't work straight up, we can refactor!
It sounds like this is a static page, so you can do as juanpastas says, or another option is to create a folder under your app/views directory to hold these pages. Maybe something like
app/views/static_pages/the_page.html.erb
Then in your config/routes.rb you can add:
match '/your_page_name', to: 'static_pages#the_page', via: :get

Rendering on specific pages through application.html.erb file?

I have a search box that I only want to render on particular pages through the navigation section in my application.html.erb file.
How do I set exceptions? Is this done through the main application controller?
There are several ways to do this.
Most obvious way is to use an instance variable for flagging.
In your application.html.erb
<%= render 'search' if #search_box %>
And wherever you want to show the search, set the flag instance variable to true.
def show
#search_box = true
...
end
Edit
You might also want to utilize Rails' filters in your controllers if you want multiple actions to show search.
before_action :flag_search_box, :only => [:show, :new, :all_kinds_of_controller_actions_where_i_wanna_show_search]
...
private
def flag_search_box
#search_box = true
end
I might suggest to put the search box not in the application.html page but maybe in the separate html pages that you want it to render on. You could make the search a partial so that you could access it from the other pages with just one line of code.

Rails dynamic routing to different instance variables of controller

First of all I'm newbie to rails
I have a controller like this one. The queries are working fine.
class StoreController < ApplicationController
def men_clothing
#men_clothing=Category.find_by_name("clothes").products.where(product_type: "men")
#men_clothing_tshirt=Category.find_by_name("clothes").sub_categories.find_by_name("t-shirt").products
end
Now I have a view for men_clothing in which I'm able to show all the products in #men_clothing instance variable by iterating over it.
But in my home page I have a links which I want to direct to #men_clothing_tshirt instance variable such that clicking on that link will show all the products of this instance variable.And if there is another link it should direct to a different instance variable.
How should I achieve this? Or suggest a alternative way to do this. Do explain how it works.
I know I can do that by making separate actions for each instance variable and making a view for it. But in that case I will have to make a lot of views.
Maybe you could try something similar to this link?
[:tshirt, :pant, :banana_hammock].each do |category|
get "mens_#{category}/:id", :controller => :mens, :action => :show, :type => category, :as => "mens_#{category}"
end
Then you'll get your paths that you're looking for, e.g. mens_tshirt_path, mens_pant_path, etc.
In your controller, you would change the action to change based on the incoming 'type'
class MenController < ApplicationController
before_filter :find_clothing_by_category
private
def find_clothing_by_category
#clothing = Clothes.where(category: params[:type].to_s)
end
end
your link is not redirecting to your instance, its redirecting to your action. so you have to define a new method for new link_to that, and define your #men_clothing_tshirt object in that method like this:
def your_method
#men_clothing_tshirt=Category.find_by_name("clothes").sub_categories.find_by_name("t-shirt").products
end
and in your link_to redirect to your_method:
link_to "Tshirt", your_method_path
Hope it will help.Thanks

What is the most effecient way to get and view commonly used data inside a Rails application?

I have three models all associated with eachother via has_many :through method.
ProgramCategory
ProgramSubcategory
Program
Inside my application, I need to use ProgramCategory.title, ProgramSubcategory.title and Program.title very often. Lets say, there'll be a dynamic sidebar menu and it will look like this:
|- Shows (ProgramCategory)
|- Action (ProgramSubcategory)
|- Lost (Program)
|- Games of Thrones (Program)
|- Dexter (Program)
Since I'm aware of power of application_controller, application_helper and partials; I feel lost about combining all of these together to find the most appropriate way.
Where and how should I call my models? Where should I build my methods to have access it through all of my controllers? Should I simply create a partial and render it at application layout?
I need some expert enlightment, please...
Thanks.
This navigation bar is not a core part of the data you are showing, it will be more or less the same for all pages. Thus, it does not belong to the controller.
Make it a helper method, and cache its results in the view:
app/helpers/sidebar_helper.rb
module SidebarHelper
def sidebar_data
# blahblah, use any tag helper (include it here if necessary)
# just remember to
end
end
app/controllers/your_controller.rb
class YourController < ApplicationController
helper :sidebar
# ...
(or put the helper method in your application helper to have it available everywhere)
app/views/application/_sidebar.html.haml
- cache do
# well, put here whatever you need to output the sidebar
# use the sidebar_data, which should return precooked data on
# which you can build your nested <ul>s.
# just indent it two spaces, so it's inside the "cache do" block
or app/views/application/_sidebar.html.erb
<% cache do %>
same as above, don't worry about indentation
<% end -%>
and include the partial where appropriate
<%= render 'sidebar' %>
If this sidebar shows in every view throughout your application, you can it to your application layout. Then add a before filter in your application controller to get the data, this will get executed for each action in every controller that inherits from application controller. You can also restrict it to specific actions, only :index, and :show (for each controller) for example.
class ApplicationController < ActionController::Base
before_filter :get_side_bar, :only => [:index, :show]
def get_side_bar
##sidebar = some code
end
end
Then you can use helper method (if needed) and render #sidebar in your application layout.
If you need to skip this action for some controllers you can do that as well, this one will skip application controller before filter for anything but index inside of the OtherController:
class OtherController < ApplicationController
skip_before_filter :get_side_bar, :except => [:index]
end

Resources