Setting a variable within a link_to, in rails 4 - ruby-on-rails

I am trying to set variables in a series of link_to links, so that each link is associated with a value.
On one page I have a loop which creates a list of links from values in my database:
<ul>
<% #alldata.each do |x| %>
<li><%= link_to "#{x.name}", charts_path %></li>
<% end %>
</ul>
The charts_path links to a view which displays a chartkick graph:
<%= line_chart #data.group("year").sum("magnitude") %>
which gets its data from a controller saying:
def graphdata(x)
#data = Model.all.where(name: x).select("magnitude, year")
end
def charts(?variable)
#data = graphdata(?variable)
end
I would like to alter my list loop to set ?variable to x.name. For example something like:
<li><%= link_to "#{x.name}", charts_path, ?variable = "#{x.name}" %></li>
So that I have a list of links, that route to different charts with data specific to that link.
I could define a specific view for every single name:
def chart1
#data = graphdata("name1")
end
def chart2
#data = graphdata("name2")
end
But that seems like very bad programming...
I'm sorry if this question is poor, I'm extremely new to programming.
Any assistance would be greatly appreciated!
Thank you

Try Using this Code.
<%= link_to "#{x.name}", charts_path(x.name) %>

If I understand correctly, you want to pass the name of x as a querystring variable. You can easily do this with the charts_path helper:
<%= link_to "#{x.name}", charts_path(variable: x.name) %>
charts_path accepts a hash that will be passed with the request

I encountered the similar state where I got my module worked with the following method
`<%= link_to n.subject, notifications_message_path(notification_id: n.id)%>`

Related

Ruby on Rails: Store array value in variable and use as string

I'm in the process of refactoring some code. I'm trying to use arrays in my view as part of a for loop that makes columns in a table.
I have defined the arrays in my controller:
subjects_controller.rb
def index
...
#CRFS_TO_VIEW = [Baseline, TreatmentCompletion]
#CRF_PATH = {Baseline => 'baseline_path', TreatmentCompletion => tc_path}
end
So my goal; as the function iterates over #CRFS_TO_VIEW, the correct path is selected from #CRF_PATH and appended to the link_to function.
indext.html.erb
<% #CRFS_TO_VIEW.each do |crf| %>
<% path = #CRF_PATH[crf] %>
<%= link_to "edit", path(crf.where(subject_id: sub.subject_id).first %>
<% end %>
I also tried :
<%= link_to "edit", #CRF_PATH[crf](crf.where(subject_id: sub.subject_id).first %>
Which didn't work. I feel I must be getting close, any help or insight would be greatly appreciated.
Thanks.
A few things:
a. You should save yourself some time and loop through the dictionary instead of the array:
<% #CRF_PATH.each do |crf, path| %>
...
<% end %>
b. You are getting a string from the loop - you can invoke the equivalent method with send:
<%= send(path, ...) %>
c. You can simplify your retrieval of the objects using:
crf.find_by(subject_id: sub.subject_id)
That said - this seems like a pretty bad way of doing things. I'd recommend instead adding a view helper:
def crf_path(crf)
case crf
when Baseline then baseline_path(crf)
...
end
With something like this you could use (notice changed the find_by to find_by! for safety as well):
<% #CRFS_TO_VIEW.each do |crf| %>
<%= link_to "edit", crf_path(crf.find_by!(subject_id: sub.subject_id) %>
<% end %>
Finally instance variables should NOT be named upper case. If you want to use a constant define it as a constant (otherwise use lower case names).

Ruby on Rails global categories block

I am new to ROR and I don't understand how can I make global template which I could put in any other template. For example I have categories module and would like to create sidebar navigation and put it at homepage template. I tried to do it this way, but categories controller method side_nav is never called. Is this good practice for this type of problem or should i do it different way?
categories/categories_controller.rb
def side_nav
#categories = Category.all
end
categories/_side_nav.html.erb
<ul class="list-unstyled">
<% categories.each do |category| %>
<li><%= link_to category.title, category.title.downcase %></li>
<% end %>
</ul>
homepage/index.html.erb
<%= render 'categories/side_nav' %>
You may look at layout/application file. It's global layout in your custom project by default. And you can provide your custom layouts in your contollers.
http://guides.rubyonrails.org/layouts_and_rendering.html

Rails - If / Else in view returning both branches

I've an 'if / else' running in my view, based on the current URL of the page, and currently the view is displaying what is should were the 'if' both true and false. It's a little tricky to explain, and I've no idea why this is happening - any explanations / solutions will be greatly appreciated!
Before the code, here's a little background:
I have recipes, each of which have one or more cuisines (via has-many-through relationships)
if the URL is, for example, /italian, I want it to display all recipes with the cuisine 'Italian'
otherwise, if the URL is invalid or doesn't have any recipes with matching cuisines, I want it to display a message stating this
(So far, so straightforward right?)
However, when the code runs, it's correctly printing the right recipes (i.e. French meals won't come up on the /italian url), BUT also printing the error message. Here's the code:
In the controller:
#url = request.path.split('/')[2] #returning 'italian', 'french', etc.
And the view:
<% Recipe.all.each do |recipe| %>
<% recipe.cuisines.each do |recipe_cuisine| %>
<% if recipe_cuisine.name.downcase == #url %>
<p><strong><%= recipe.name.humanize %></strong></p>
<ul>
<% recipe.ingredients.each do |recipe_ingredient| %>
<li><%= recipe_ingredient.name %></li>
<% end %>
</ul>
<p><%= recipe.method %></p>
<% else %>
<p>You've reached an invalid page, please return to <#%= link_to 'the homepage', root_url %></p>
<% end %>
<% end %>
<% end %>
To clarify, I've tested the 'recipe_cuisine.name.downcase == #url' line of code, and it's returning true when it should be, false when it shouldn't.
Does anyone know how to resolve this?
Thanks in advance, Steve.
Edit
Here are the routes that affect this:
Rails.application.routes.draw do
get 'recipes/:cuisine' => 'recipes#cuisine'
resources :recipes
end
You defined the following route:
get 'recipes/:cuisine' => 'recipes#cuisine'
This means when you hit /recipes, it uses the cuisine action of the recipes controller (thanks to 'recipes#cuisine').
You also defined an extra :cuisine after the recipes/, which means if you hit /recipes/italian, then you will have a GET param (named cuisine) available in your controller/view.
Here is how you can use it:
# recipes_controller.rb
def cuisine
#recipes = Recipe.all # (use `Recipe.scoped` if using Rails' version < 4)
if params[:cuisine].present?
#recipes = #recipes.includes(:cuisines).where(cuisines: { name: params[:cuisine] })
end
# other stuff
end
# cuisine.html.erb (view)
<% #recipes.each do |recipe| %>
<p><strong><%= recipe.name.humanize %></strong></p>
<ul>
<% recipe.ingredients.each do |recipe_ingredient| %>
<li><%= recipe_ingredient.name %></li>
<% end %>
</ul>
<p><%= recipe.method %></p>
<% end %>
But there is a flaw in this logic: What if I hit /recipes/frenchAndMexicanPlease ? The params[:cusine] will be equal to "frenchAndMexicanPlease", and your DB does not have any cuisine type named like this. In this case, it would display no recipe at all, since the query #recipes.includes(:cuisines).where(cuisines: { name: params[:cuisine] }) would not match any existing record.
I can obviously provide more explanations about the code and logic I used. Hope this helps!
How many cuisines are in the collection? If there are two, and one of them has a name that is equal to #url then you would see the first branch, while any that don't equal #url would show the second branch. You're evaluating that if statement for each cuisine.

Creating Links on Rails

I've just started using rails yesterday, so this is a kinda noob question
for example, a user is at www.example.com/name
and I want to make several links to www.example.com/name/:id
So I tried something like this:
<% #items.each do |item| %>
<%= link_to item.name, '/name' :id %>
<% end %>
I know, it was a complete guess on how I should write the code, but the restful code sends to a completely wrong link. How should I write this three lines?
Use the route helper:
<% #items.each do |item| %>
<%= link_to item.name, item_path(item) %>
<% end %>
ps: when you have a simple question like this one, take a look at this guide, you'll often find the answer.
Try
<%= link_to item.name, item_path(item) %>
item_path is a URL helper method which spits out the link to show a name.
URL helpers have the general form:
{action}_{class}_path({object or object_id})
If {action}_ is omitted, then the default action is assumed (normally show).

rails app helper hash driving menu list

I want the sites navigation menu to be populated by a hash in the application helper. I've got it looking right; but the path helpers are not being evaluated (meaning my link tag's href = "root_path" instead of "/").
In my application_helper:
$navPages = {
'Home' => "root_path",
'page2' => "page2_path"
}
and in some layout partial the erb is as follows:
<ul>
<% $navPages.each do |ntext,npath| %>
<li><%= link_to ntext, npath %></li>
<% end %>
</ul>
So this setup will get the list too look right; but the href's aren't being evaluated. The first list item link tag href = "root_path" instead of the evaluated version of the string "/".... I've tried a few things to no avail. This is some fundamental lack of understanding the hash value storage and how/when the ruby path helper is being evaluated. I've tried:
1. removing the quotes from the hash (returned an unknown variable/method error)
2. "#{npath}
3. "raw"
a few other things.
Any direction will be greatly appreciated.
Thanks!
<% $navPages.each do |ntext,npath| %>
<li><%= link_to ntext, self.send(npath.to_sym)%></li>
<% end %>

Resources