How do I pass a class attribute via a helper - ruby-on-rails

I have a PostsHelper, that helps me generate links:
module PostsHelper
def populate_update_link(link1, link2, parameter)
if current_user
public_send(link2, parameter)
else
public_send(link1)
end
end
end
I call it like this:
<%= link_to 'Update', populate_update_link('new_post_path', 'new_post_path', parent_id: #post) %>
What I would like to generate is a link like this though:
<%= link_to "(Update)", "#", class: "togglesidebar" %>
How do I send a class via public_send to the generated link?

According to the rails API, you can setup html options for a given link on the third parameter of link_to (ie http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to)
In your case you would need to define another method which return an array of options such as {id: "my_id", class: "my_class_1 my_class_2"} and call this method as the 3rd parameter of link_to.
def generate_html_options(param_1, param_2)
....
body
....
return hash of options
end
Intended to be use like this:
<%= link_to('Update', populate_update_link('new_post_path', 'new_post_path', parent_id: #post), generate_html_options(...)) %>

Related

Can i use variables in Rails link_to method?

Can i use variable for Rails link_to helper for making different link with variables?
For example,
<%= link_to users, users_path %>
I have link like this,
And i'd like to change this url with variable examples
So i changed url like this,
<%= link_to users, "#{examples}_path" %>
This not worked because of whole string change to url.
How can i change my link_to for use this with different variable for DRY codes?
What you're asking is really just how to perform dynamic method calls. In Ruby you can do it with send (and public_send):
<%= link_to users, send("#{examples}_path") %>
The difference between the two is that send will let you violate encapsulation and call private/protected methods.
You can also do it by calling call on the Method object:
<%= link_to users, method("#{examples}_path".to_sym).call %>
However you most likely don't even need this it in the first place. Just use the polymorphic routing helpers to create links from models:
# a link to show whatever resource happens to be
<%= link_to resource.name, resource %>
<%= link_to "Edit", edit_polymorphic_url(resource) %>
<%= link_to "New", new_polymorphic_url(resource_class) %>
<%= link_to "Frobnobize", polymorphic_url(resource, :frobnobize) %>
# a link to the index
<%= link_to resource_class.model_name.plural, resource_class %>
These all use a set of heuristics to figure out what the corresponing path helper is and then call it dynamically with send.
Or if you want to link to a specific controller or action just use the functionality provided by url_for:
# link to a specific controller action
<%= link_to "Baz", { controller: :foo, action: :bar } %>
# Will use the current controller
<%= link_to "Baz", { action: :bar } %>

Search form Couldn't find User with 'id'=

I need to create search form to search for all the cases pt_name of the user
I got this error
Couldn't find User with 'id'=
In cases controller
def index
#user =User.find(params[:id])
#cases=#user.cases
if params[:search]
#search_term = params[:search]
#cases= #user.cases.casesearch_by(#search_term)
end
end
in case model
class Case < ActiveRecord::Base
belongs_to :user
def self.casesearch_by(search_term)
where("LOWER(pt_name) LIKE :search_term OR LOWER(shade) LIKE :search_term",
search_term: "%#{search_term.downcase}%")
end
end
in cases index.html.erb
<%= form_for "",url: cases_path(#user.id), role: "search", method: :get ,class: "navbar-form navbar-right" do %>
<%= text_field_tag :search, #search_term,placeholder: "Search..." %>
<% end %>
The problem is the first line in your controller.
When the form is submitted it's going to cases_path(#user.id) - that's what you specified in your form.
If you're checking with rails routes you'll see that cases_path is actually going to "/cases" (I am assuming you did not overwrite it) and that there isn't any placeholder for an id (like it would be for the show action for example which goes to "/cases/:id".
Now you still specify #user.id in cases_path(#user.id) and then you try to find a user with the id from the params. But if you check your params once you arrived in the controller (with binding.pry or other tools), you will see there is no key :id in the params. You can also check the url it is going to, I believe it will look something like this: "/cases.1".
You can solve that by changing the path to
cases_path(user_id: #user.id)
This way you add a new key value pair to the params hash and then in your controller you need to change it accordingly:
#user =User.find(params[:user_id])
You can also add a hidden field into your form in order to pass along the user id:
<%= form_for "", url: cases_path, role: "search", method: :get, class: "navbar-form navbar-right" do %>
<%= text_field_tag :search, #search_term,placeholder: "Search..." %>
<%= hidden_field_tag :user_id, #user.id %>
<% end %>
And then retrieve it in the controller.
To check your params that you get in the controller action use a gem like pry byebug or just the keyword raise and then inspect the params variable.

Ruby on Rails - passing parameters in link_to with if conditions?

I want to pass a parameter (for example the param is called company=heise) on a link to, but only if the param really is present.
Lets say:
I visit somesite.com and click a link that would redirect me to mysite.com/?company=heise
On mysite i have a few link_to's and I want them to pass the parameter company=heise when it's present and since it is present now because I entered the site via mysite.com/?company=heise it should do the following:
<%= link_to "This is a link", this_link_path, class: tl(this_link_path) %>
should redirect me to mysite.com/this_link/?company=heise
If company=heise is set I want to display them in the URL and I furthermore want to not display it when it's not set.
Hope I made my question clear enough
Conditionally pass a hash, containing additional params for this_link_path url helper.
<%= link_to "This is a link", this_link_path( ({company: params[:company] } if params[:company]) ), class: tl(this_link_path) %>
To be more concise you can compact the hash.
<%= link_to "This is a link", this_link_path({company: params[:company]}.compact), class: tl(this_link_path) %>
If you know that you'll need it more often, wrap this_link_path call in a custom helper. Hash can contain additional params, including ones with fixed values.
def this_link_with_additional_params_path
this_link_path({company: params[:company], name: 'test'}.compact)
end
Then in view you can use:
<%= link_to "This is a link", this_link_with_additional_params_path, class: tl(this_link_path) %>
The idea here is to create a helper method to manage the params that you want to send to this link conditionally.
# some_helper.rb
def carried_over_params(params = {})
interesting_keys = %i(company)
params.slice(*interesting_keys).compact
end
Afterwards, you should use this in the view
<%= link_to "This is a link", this_link_path(carried_over_params(params).merge(test: 'value')), class: tl(this_link_path) %>

Add custom put method to generated controller

I have records_controller generated through the regular generator scaffold_controller. I would like to add custom method, lets call it share in order to pass there only one parameter with email address. If email exists in my database I would like to add associated within id to record.
I added share method to records_controller:
def share
logger.info record_params
logger.info params
# check email in db and add id
respond_to do |format|
format.js
end
end
form on show view:
<%= form_tag(controller: "records", action: "share", method: "put", remote: true) do %>
<%= label_tag(:user_email, "Share for:") %>
<%= text_field_tag(:user_email) %>
<%= submit_tag("Share") %>
<% end %>
and rule in routes:
put '/records/:id/share', to: 'records#share'
Form renders fine but when I press click I get error:
ActionController::RoutingError (No route matches [POST] "/records/2/share"):
According to the form_tag source code, the parameters you pass to the helper are all considered as url_for_options and return a wrong output like this:
<form action="/records/2/share?method=put&remote=true" method="post">
You need to specify which parameters are url_for_options and which are only options:
<%= form_tag({controller: "records", action: "share"}, method: 'put', remote: true) do %>

How to implements a button tag to form_for helper?

I need implements a helper that creates <button>...</button> tag, I need to do some similar to this:
<%= form_for(some_var) do |f| %>
<%= f.submit '+' %>
<% end %>
The helper should work like this:
<%= f.button '+' %>
# Returns
<button type="submit">+</button>
I saw https://github.com/rails/rails/blob/master/actionpack/lib/action_view/helpers/form_tag_helper.rb#L458 but this isn't implemented in Rails 3.0.7.
What I need to do to implements this helper in my application?
You can create a custom form helper that inherits from FormBuilder to use when creating forms. I created this button method to use with Twitter's Bootstrap.
Replace 'Bootstrap' with whatever fits. (Perhaps CuteAsAButtonBuilder?)
app/helpers/bootstrap_form_builder.rb
class BootstrapFormBuilder < ActionView::Helpers::FormBuilder
def button(label, options={})
# You can also set default options, like a class
default_class = options[:class] || 'btn'
#template.button_tag(label.to_s.humanize, :class => default_class)
end
end
Now you have two ways to use the builder.
1. DRY for ducks
Every time you build a form that uses the button, you need to specify the builder...
<%= form_for #duck, :builder => BootstrapFormBuilder do |form|%>
2. DRY for devs
Add the following
app/helpers/application_helper.rb
module ApplicationHelper
def bootstrap_form_for(name, *args, &block)
options = args.extract_options!
form_for(name, *(args << options.merge(:builder => BootstrapFormBuilder)), &block)
end
end
Just call the magic builder...
<%= bootstrap_form_for #person do |form| %>
<%= form.button 'Click Me' %>
<% end %>
I had implemented a similar helper method in one of my applications earlier. I needed the button tag with an image on the button and a class of its own. You can pass either a string which is the text that is displayed on the button or the object itself. It looks like this:
def submit_button(object)
image = "#{image_tag('/images/icons/tick.png', :alt => '')}"
if object.is_a?(String)
value = "#{image}#{object}"
else
name = object.class.to_s.titlecase
value = object.new_record? ? "#{image} Save #{name} Information" : "#{image} Update #{name} Information"
end
content_tag :button, :type => :submit, :class => 'button positive' do
content_tag(:image, '/images/icons/tick.png', :alt => '')
value
end
end
Then you call this in the form <%= submit_button #admission %>
It looks like this:

Resources