I'm trying keep a tab on a page to be selected by checking the controller.
I.e., any page that displays the Products controller should keep the Product tab selected.
I can't seem to find the right approach.
I was considering of making a helper method, but it seems a bit tricky to put the helper into my link_to helper. Here is my guess of how I can make it work:
<%= link_to "Products", products_path, current_controller?('products') ? :class => 'selected' %>
Anyone has a better idea?
And the problem wont just be in one place, you'll have many tabs and each tabs will have rules on which controllers+action combinations it would be active/selected for.
It's a common problems and some people have written "plugins" for the same too.
I suggest you write helpers. Make your own mini DSL. Decide for yourself what is easy and nice to look at:
<%= link_to_tab_for("Products", products_path, :controller => "sss", :action => "", :other_html_options => {})
Next step, implement this method in helpers/application.rb
def link_to_tab_for(name, path, options)
controller = options.delete(:controller)
action = options.delete(:controller)
klass = [].push(options[:class]).compact
if current_controller?(controller) && (action ? current_action?(action) : true)
klass.push("selected")
end
options[:class] = klass.empty ? "" : klass.join(" ")
link_to(name, path, options)
end
Have a gander at attempting the above method to your liking of course.
Related
I have two rails helper on my application helper:
def active_class(link_path)
current_page?(link_path) ? 'active' : ''
end
def active_class_white(link_path)
current_page?(link_path) ? 'active-white' : ''
end
One is for regular links the other one is for the submenus. Usually I place the link like this:
<%= link_to "Home", root_path(:anchor => 'home'), class: "nav-link #{active_class('/')}", :"data-id" => "home" %>
Now here's my problem. On my homepage I got this link where it will slide to a particular section of the site thus requires a character like #about. If I place:
<%= link_to "About", root_path(:anchor => 'about'), class: "nav-link #{active_class('/#about')}", :"data-id" => "about" %>
It's still putting the active class on the home text instead of the about (the homepage is a one page slider type).
Another thing is that for complicated url like the devise edit profile, I tried to put the ff:
<%= link_to "Edit Profile", edit_user_registration_path(current_user), class: "dropdown-item #{active_class_white('/users/edit/:id')}" %>
Placing /users/edit/:id doesn't work on this kind of URL: http://localhost:3000/users/edit.13
On this two kinds of URL my code doesn't work. Any idea how to make them work or turn this around?
Anchors are purely client-side and are not sent along with the request to the server. So, the only way to implement the first part of your question is through Javascript. You can listen for a click event on links then add the active class to the one that was clicked.
The second part of your question, where you pass in the :id segment key, can be solved by passing a route helper (along with an object) to current_page? instead of an explicit string...
class: <%= active_class(edit_user_registration_path(current_user)) %>
I'm trying to build an app that searches twitter for images. Before I get there, I need to jump over the intimidating hurdle of constructing a working search field that feeds a value into a function.
In my index.html.erb file that's controlled by the Pages controller, I have this code:
<%= form_tag root_path ({:controller => "pages", :action => "search", :method => "get", :class => "grabTweets" }) do %>
<%= text_field_tag :tweets, params[:tweets] %>
<% end %>
In my Pages controller I have:
def search
def grabTweets
#tweet = Twitter.search(params[:tweets] + "[pic] "+" path.com/p/", :rpp => 3, :result_type => "recent").map do |status|
#tweet = "#{status.text}" #class = string
#urls = URI::extract(#tweet, "http") #returns an array of strings
end
end
end
Two problems:
My search query isn't being passed into the grabTweets function as proven by the URL after the search is performed:
http://localhost:3000/?action=search&class=grabTweets&method=get (the search query was the word "bridge"
What's wrong with my code that the search query isn't performing correctly.
Should my code that's in the controller be placed in def home or def search, given that I want the search results to show up in the root_path and don't intend to change pages?
Thanks in advance for the help! I'm thoroughly stumped.
I think you need to read a book introducting Rails, as there seem to be many fundamentals you are missing.
You have an action for the page you are on (which you seem to call 'home') and an action for the search results. Your form needs to call the url for the search action. That would look like this:
<%= form_tag({:controller => "pages", :action => "search"}, {:method => "get", :class => "grabTweets"}) do %>
...
(See the API for more details on the form_tag method)
In that state, it will call the search action (which should not have another method called grabTweets nested inside it - that makes no sense) which will then render search.html.erb (presumably a page of search results).
In your routes file, you need a route for both home and search.
If you want the page to update without refreshing the page, then you need to use :remote => true on the form and handle the response using AJAX.
If you want the two pages to be the same, but with one containing results, then either move the search functionality into the home action and only call it if params[:tweets] is populated, or just have both actions render the same template.
I would recommend reading through the Rendering Guide and the Controllers Guide to learn more.
Here's what I have:
<%= link_to "Reload Div", {:controller => "my_controller", :action => "my_action"}, remote => true %>
I want to be able to click the link and have a div reload with different content generated by Ruby on Rails. How can I do this?
For simplicity... I simply want to be able to click the link and reload the div with a number one higher than the previous.
If you're using jQuery, this might be easier with UJS than by hacking something together yourself. Maybe something that does this:
$('a.reload').click(function() { $(this.parentNode).load(this.href); return false; });
If rails is incrementing the number, I'm not sure why you wouldn't just use link_to as you have specified in your question as you have everything set up correctly with your controller, action, and the remote attribute.
Here is your action:
def my_action
#counter = 1 #Insert whatever logic you need to increment the number.
end
Here is your view (my_action.js.erb):
$("#divtoreload").html("<%= #counter %>");
I've had a problem with the following issue in Rails and ASP.Net MVC. Often there are multiple widgets of functionality on a page, yet one controller action is supposed to render the page. Let me illustrate:
Let's say I have a normal e-commerce site, and the menu is made of categories, while the page is to display an group of products.
For the products, let's say I have an action on a controller that looks something like:
def product_list
#products = Products.find_by_category(:name => 'lawnmowers')
end
And I have a layout with something like
<div id="menu"><%= render :partial => 'menu' %></div>
<div id="content"><%= yield %></div>
The products have a view...
<%= render :partial => 'product', :collection => #products %>
(note I've ommited the product view as irrelevant)
And the menu has a partial...
<% Category.each {|c| %>
<%= render :partial => 'menu_node', :locals => { :category => c } %>
<% } %>
The line I have a problem with is the "Category.each.do" in the view. I'm fetching data in the view, as opposed to using variables that were set and bound in the controller. And it could easily be a more complex method call that produces the menu.
The solutions I've considered are:
-A view model base class that knows how to get various pieces of data. But you could end up with one of these for each conceptual "section" of the site.
-a local variable that populates at the top of each method (violates DRY)
-the same thing, but in a before_filter call
None of these seem very elegant to me. I can't help but look at this problem and think that a MVP presenter per view (not screen) is a more elegant solution.
ASP.Net MVC has render action (different from rails render :action), which does address this, but I'm not sure what I think of that solution.
Thoughts? Solution suggestions?
Added Note:
The answers provided so far are good suggestions. And they apply to the example I gave, where a menu is likely present in every layout, and is clearly secondary to the product data.
However, what if there is clearly no second class citizen? Portal type sites commonly have multiple unrelated widgets, in which each is important.
For example, What if this page was displaying weather trends, with widgets for temperature, humidity, and precipitation (and each is a different model and view type).
In rails we like to have a concept of thin-controllers, thick-models. So I think you're right to not want to have variables set in the controller.
Also, in order to enable a more-complex method later on, I recommend doing something like:
/app/controllers/application_controller.rb
before_filter :add_menu_nodes
def add_menu_nodes
#menu_nodes = Category.menu_nodes(current_user)
end
/app/views/layouts/application.html.erb
<%= render :partial=>:menu, :locals=>{:categories=>#menu_nodes} %>
/app/models/category.rb
def self.menu_nodes(current_user)
Category.all.order(:name)
end
That way in the future you could update Category.menu_nodes with a more complicated solution, based on the current user, if you need.
Forgive me if I butcher the Ruby (or misunderstand your question), but what's wrong with
class section_helper
def menu( section )
// ...
menuBuiltAbove
end
end
in the view
<%= section_helper.menu( 'section' ) %>
?
I have a slightly complex navigational system with numerous landing pages, multipage forms, and multiple ways of accessing the standard CRUD functions.
Objective: To maintain a variable such as (params[:target]) throughout the system such that each controller knows where to redirect a user based on the location and circumstances of the link_to.
How to implement this the best way?
Is there a better way to store navigation markers so any controller and method can access them for the current_user?
If using params[:target] is a good way to go (combined with if or case statements in the controller for the redirect), how do I add the target params to the form when adding or editing a record? For example, view says:
# customers/account.html.erb
<%= link_to "edit", :controller => "customers", :action => "edit", :id => #customer.id, :target => "account" %>
# customers/edit.html.erb
<%= submit_tag "Update", :class => "submit" %>
# how to send params[:target] along with this submit_tag so the update method knows where to redirect_to?
Thank you very much.
I think you could get the same result by setting a session[:target] each time is necessary. so you'll always know where to redirect from controllers without changing link_to params and leaving clean URLs.
hope this helps,
a.