Rails 4 - current_page? with query parameter - ruby-on-rails

I've method in my application.rb
def current_page(path)
"active" if current_page?(path)
end
then in my view, lets say the request_uri is http://www.example.com/stories, i just can call
<%= link_to "All Stories", stories_path, :class => "#{current_page(stories_path)}" %>
BUT how about if the request_uri has something like http://www.example.com/stories?featured=true ? How do I call it in view?

Because current_page? method will compare passed-in path which doesn't have ? just with your current url deleting query params.
For example, if you're at http://www.example.com/stories?featured=true, and you have current_page(stories_path), you'll still compare http://www.example.com/stories(stories_path) with http://www.example.com/stories(your current url without featured=true).
I have a idea, but you'll have ? in the end of your normal url.You can change the code to <%= link_to "All Stories", stories_path + '?', :class => "#{current_page(stories_path + "?")}" %>
I'll update this if I come up with better methods.

Related

How can I trigger an action from a different controller for dynamic content?

Im having a dynamic header depending on the view and action of the controller and it works fine with the actions in "welcomes_controller". But Im not able to trigger a action from a different controller in this case posts_controller.
How can I trigger it correctly? Thanks in advance.
<% if params[:action] == 'index' %>
<%= image_tag("header_background.jpg", alt: "header background", :class => "header_background") %>
<% elsif params[:action] == 'trading' %>
<%= image_tag("trading_background.jpg", alt: "trading background", :class => "header_background") %>
<% elseif ... HOW TO TRIGGER A ACTION FROM A DIFFERENT CONTROLLER? %>
<% end %>
There are two helpers easily availalbe for this: controller_name and action_name. You can use a combo of these for conditional rendering.
That said, personally I feel this is a lot of clutter for the view - I can't help feeling this would be better set elsewhere. In a very simple sense, you could add the following in your controllers:
def index
#header_image = "header_background.jpg"
end
def trading
#header_image = "trading_background.jpg"
end
And then in the view:
image_tag(#header_image, alt: #header_image, :class => "header_background")
Alternatively, you could follow a convention for your images:
image_tag("#{controller_name}/#{action_name}.jpg", alt: action_name, :class => "header_background")
Then ensure your header images are stored in a folder named after the controller, named after the relevant action.
I'd strongly lean towards the latter.
Update: one final option would be to define a helper that handles this, something like, in you view:
= header_image_tag
And somewhere within your /helpers folder something akin to:
def header_image_tag
image_path = case controller_name
when "controller_one"
"header_background.jpg" if action_name == "index"
"trading_background.jpg" if action_name == "trading"
when "controller_two"
# ...
else
"default_image.jpg"
end
image_tag image_path, alt: # ...etc
end
I think the helper has access to controller_name and action_name, though if not you could pass these as args to header_image_tag, or pass the request as an arg and access request.controller_name and request.action_name.
Let me know what you think and how you get on.
For this I use this code. This should work for what you are trying to achieve.
<% if controller.action_name.to_s == "index" %>
Also keep in mind, if you need to be more granular with the specific controller you want to target you can also add the controller name to the check.
<% if controller.controller_name.to_s == "posts" && controller.action_name.to_s == "index" %>

How do i add an active class to a dynamic link?

I have a sidebar that holds a list of posts. I need the corresponding post on my sidebar to have an active class. What i have currently does not work so what is the best way to do this?
def is_active?(path)
current_page?(path) ? "active" : ""
end
<% #posts.each do |post| %>
<%= link_to post.title, post, class: is_active?(posts_path) %>
<% end %>
As I said in my comment, methods ending by ? should return a boolean value. If you decide to go against the convention this will make things harder for us.
I suggest you actually use an active_link_to like it is explained in that question.
However the main problem was that you didn't generate the URL properly for each post :
is_active?(posts_path)
The posts_path is the path to the index and not the individual post resource. You should use something like post_path(post)
You want to do something like this :
First your is_active? method, because it has a ? should return a boolean
def is_active?(path)
current_page?(path)
end
Then you can use it this way (you need to get the URL of the post using the post_path(post) helper)
<% #posts.each do |post| %>
<%= link_to post.title, post, class: ('active' if is_active?(post_path(post))) %>
<% end %>
EDIT : because is_active? does the same thing as current_page? you should simply replace the is_active? code by an alias declaration
alias :is_active? current_page?
I had to develop such a solution some years before. I implemented the following as helper methods to detect an active link. Be aware that this is not the best solution I think. I had to provide a full url. Fell free to edit the code to use a path or a parameter hash instead.
# Returns true or false if the page is displayed that belongs to the given url.
def link_selected?(url)
request_method = request.method.to_sym
begin
url_params = Revolution::Application.routes.recognize_path(
url, {:method=>request_method}
)
rescue Exception => e
{}
end
begin
request_params = Revolution::Application.routes.recognize_path(
request.url, {:method=>request_method}
)
rescue
{}
end
return true if url_params == request_params
return false
end
def is_active?(url)
return link_selected?(url) ? 'active' : nil
end

Ruby on Rails get URL and use it within an if statement

I have a ruby on rails application, and want to display an image on the index page depending on what the URL is. If the url is: localhost:3000/products/multi_find I do not want to show the image, if it is anything else I do want it to be shown.
Is their a way I can retrieve the url and store it in a variable to run an <& if statement like: if url != localhost:3000/products/multi_find &><%= image tag "test.png", :size => "15x18" %> <% end %>
Thank you in advance.
None of those solutions worked, this did:
<% if request.original_url == 'http://localhost:3000/products/multi_find' %>
<%= image tag "test.png", :size => "15x18" %>
<% end %>
In Rails you must think in terms of routing rules, not URLs. An URL is nothing else than the result of a routing directive.
Therefore, /products/multi_find can be expressed in terms of action, controller and parameters.
With that in mind, you can use the current_page? helper to check if the current URL matches the route you expect, if it does then ignore the image.
You can even use rails "action_name" and "controller_name" helper methods to get the job done.
Try this:
<% unless current_page?('/products/multi_find') %>
<%= image tag "test.png", :size => "15x18" %>
<% end %>

Searching for two arguments Ruby on Rails

I am working on a search with two text fields. It searches for two things (right now location and description) and only shows the entries (listings) that match both of them.
I would like the second text field to also search for title, so it should look for description and title. How would that work?
This is what I have right now
listing.rb
def self.locsearch(search_location, search_description)
return scoped unless search_location.present? || search_description.present?
where(['location LIKE? AND description LIKE?', "%#{search_location}%", "%#{search_description}%"])
end
home.html.erb
<%= form_tag findjobs_path, :controller => 'listings', :action => 'locsearch', method: :get do %>
<%= text_field_tag :location, params[:location] %>
<%= text_field_tag :descripiton, params[:descripiton] %>
<%= submit_tag "Search", name: nil %>
<% end %
listings_controller.rb
def index
#listings = #listings.locsearch(params[:location], params[:description])
end
Also, my locsearch method right now uses the or || condition. How would I implement the "and" condition? (If I change the || to && I get the error" undefined method or variable scroped)
Are you sure you want to use unless
unless is used only if you want to execute a specified code if the condition(s) is false.
And scoped is used along with a model.
Model.scoped
You can refer the Apidock or Github
You can write return scoped only if u have defined scoped as a local variable or a method.
You can also see scope for databases

Get url for current page, but with a different format

Using rails 2. I want a link to the current page (whatever it is) that keeps all of the params the same but changes the format to 'csv'. (setting the format can be done by having format=csv in the params or by putting .csv at the end of the path). Eg
posts/1
=> posts/1.csv OR posts/1?format=csv
posts?name=jim
=> posts.csv?name=jim OR posts?name=jim&format=csv
I tried this as a hacky attempt
request.url+"&format=csv"
and that works fine if there are params in the current url (case 2 above) but breaks if there aren't (case 1). I could come up with more hacky stuff along these lines, eg testing if the request has params, but i'm thinking there must be a nicer way.
cheers, max
EDIT - btw, it's not guaranteed that the current page could have a named route associated with it, in case that's relevant: we could have got there via the generic "/:controller/:action/:id" route.
<%= link_to "This page in CSV", {:format => :csv } %>
<%= link_to "This page in PDF", {:format => :pdf } %>
<%= link_to "This page in JPEG", {:format => :jpeg } %>
EDIT
Add helper
def current_url(new_params)
url_for :params => params.merge(new_params)
end
then use this
<%= link_to "This page in CSV", current_url(:format => :csv ) %>
EDIT 2
Or improve your hack:
def current_url(new_params)
params.merge!(new_params)
string = params.map{ |k,v| "#{k}=#{v}" }.join("&")
request.uri.split("?")[0] + "?" + string
end
EDIT
IMPORTANT! #floor - your approach above has a serious problem - it directly modifies params, so if you've got anything after a call to this method which uses params (such as will_paginate links for example) then that will get the modified version which you used to build your link. I changed it to call .dup on params and then modify the duplicated object rather than modifying params directly. – #Max Williams
You can use:
link_to "text of link", your_controller_path(format:'csv',params: request.query_parameters)
#floor's answer was great, I found it very useful.
Although the method can be improved by using the to_params method rather than contructing your own, like so:
def current_url(new_params)
params.merge!(new_params)
"#{request.uri}#{params.to_params}"
end

Resources