dynamically changing class in rails haml file - html

I have the following line of code in a haml file
%a#mypage{:href => hub_path(#user), :class => "#{path.match('(hub)') ? 'current': ''}"}
What this does is ensure the correct item on a navigation bar is highlighted. However, I need the same item to be highlighted if any one of several paths are matched.
So, above we have the path matched to hub. I need it to return true if the path is matched to hub, or item2, or item3.
No idea where to begin. I've tried putting in "||" into the class to see if I could just list them but this didn't work. Is there a way to do "includes" when specifying the match?
continued...
So I took the advice of the posters below but still couldnt' make it work
I'm at this point to test it
- path = request.fullpath
- if path.match(/\(performance_hub|objectives|deliverables\)/)
true
- else
fail
%br
= path
Even though the path is
/users/170/hub
it is still returning false. Where am I going wrong?

Try with regex instead of string
:class => "#{path.match(/\(hub|item2|item3\)/) ? 'current': ''
This will search for (hub) or (item2) or (item3)

The answer ended up being this
%a#mylink{:href => hub_path(#user), :class => "#{%w(hub objective deliverable).any?{|w| path.match(w)} ? 'current': ''}"}

Related

html slim link_to undefined method error

In my rails project, I ran rake routes and got the following output:
Prefix Verb URI Pattern Controller#Action
obelisk_callflow_nodes GET /obelisk/callflows/:callflow_id/nodes(.:format) obelisk/nodes#index
POST /obelisk/callflows/:callflow_id/nodes(.:format) obelisk/nodes#create
new_obelisk_callflow_node GET /obelisk/callflows/:callflow_id/nodes/new(.:format) obelisk/nodes#new
edit_obelisk_callflow_node GET /obelisk/callflows/:callflow_id/nodes/:id/edit(.:format) obelisk/nodes#edit
obelisk_callflow_node GET /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#show
PATCH /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#update
PUT /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#update
DELETE /obelisk/callflows/:callflow_id/nodes/:id(.:format) obelisk/nodes#destroy
obelisk_callflows GET /obelisk/callflows(.:format) obelisk/callflows#index
POST /obelisk/callflows(.:format) obelisk/callflows#create
new_obelisk_callflow GET /obelisk/callflows/new(.:format) obelisk/callflows#new
edit_obelisk_callflow GET /obelisk/callflows/:id/edit(.:format) obelisk/callflows#edit
obelisk_callflow GET /obelisk/callflows/:id(.:format) obelisk/callflows#show
PATCH /obelisk/callflows/:id(.:format) obelisk/callflows#update
PUT /obelisk/callflows/:id(.:format) obelisk/callflows#update
DELETE /obelisk/callflows/:id(.:format) obelisk/callflows#destroy
I have a html.slim file for showing all the callflows (i.e.obelisk/nodes#index). In this file, I want to add a button to show the nodes of each callflow (i.e. connect that button to obelisk_callflow_nodes GET /obelisk/callflows/:callflow_id/nodes)
I've tried = link_to 'Nodes', obelisk_callflow_nodes_path(callflow_id: c.id), method: :get, class: 'btn btn-primary' where c is a callflow object. I've checked that c is what I want because I have c.name rendering properly. However, I'm getting the following error:
undefined methodobelisk_callflow_nodes_path' for #<#:0x00007fb3d5abebc8>`
I've checked that I do have an index method for my Obelisk::NodesController
I changed the routes so that I no longer user namespace obelisk so the routes don't start with /obelisk/. This fixes the problem. I know it might not be the best solution but in this case it has worked for the purpose of my project.

Linking to an API

I am trying to access a weather API that shows the icon of current weather.
My current code is:
response = HTTParty.get('http://api.openweathermap.org/data/2.5/weather?id=5911606&appid=734d8f2204043326b51df724c5c917f4', format: :json)
body = JSON.parse(response.body)["weather"][0]
#icon=body["icon"]
In html i am using the icon like:
<%= link_to image_tag('http://openweathermap.org/img/w/' + #icon +".png", :size => '130x130', :style => 'margin-top:45px;'), root_path%>
Its working fine when i first starts the server, but as I clicked any other link its gives me the following error:
nil is not a valid asset source
Does anybody know how to fix this?
it seems you are getting an empty #icon object. you can check for for empty icon object with #icon.blank? like following
<%= link_to image_tag('http://openweathermap.org/img/w/' + #icon +".png", :size => '130x130', :style => 'margin-top:45px;'), root_path unless #icon.blank? %>
if you can also think if having a helper method to display a default icon if the #icon is retuning a blank value
That means when you open any other links, I presume it calls a different actions where your code for #icon is not getting called and it is nil.
if you want #icon to be available for all the actions. You have to probably do it in a before action where you call the method populating #icon

NameError - undefined local variable - Parsing array from ruby file to haml file

We are using a Mysql database and make use of haml files.
The issue we have now is when we dynamically create a table with data from our mysql database it gives us this error:
NameError - undefined local variable or method `allsites' for #<Sinatra::Application:0x00
00000128c980>:
/home/usr/testsinatra/views/sites.haml:16:in `block in singleton class'
/home/usr/testsinatra/views/sites.haml:-8:in `instance_eval'
/home/usr/testsinatra/views/sites.haml:-8:in `singleton class'
/home/usr/testsinatra/views/sites.haml:-10:in `__tilt_12132720'
The weird thing is that the table is actually created !
This is the part of the ruby file where we fill our array with mysql data.
get '/getsites' do
allsites = con2.query("SELECT * FROM tblSites", :as => :array)
haml :sitesOverzicht, :locals => {:allsites => allsites}
end
This is the part where we make our table dynamically:
%table{:border => "1px"}
%tbody
%h1 All Sites
-allsites.each do |id,name|
%tr
%td
= id
%td
= name
The other strange part is when the page loads, we don't get any error and the table is created when the page loads.
But when we create a new tablerow in another table from another array and store this data with Ajax, we get this error for this variable even if we don't do anything.
I've managed to find a fix for my own problem !
To make use of our local variable we had to use the "#" sign like this for our Query:
#allSites = con2.query("SELECT * FROM tblSites", :as => :array)
Afterwards we changed it also in our link to send it to the haml file:
haml :sitesOverzicht,:locals => {:allSites => #allSites}
Afterwards in our haml file we got the NoMethodException but we found out that we had to make use of the to_a.each function to make use of the "each" function we allready had like this:
-#allSites.to_a.each do |id,name|
%tr
%td
= id
%td
= name
With the to_a.each function you say that you will make use of an array as parameter. So the each function will loop over an array. If you use the each function without saying you are using an array, it will give a nill exception.
Your Answer maybe work but it's not really nice.
Because with # you define a Instance variable probably not what you want. But of course you can do that but then you can remove :locals => {:allSites => #allSites}
But in most cases it's better to use locals:
app.rb
get "/" do
allsites = {"1" => "name", "2" => "name 2", "3" => "name3"}
p allsites
haml :index, :locals => {:allsites => allsites}
end
views/index.haml
-allsites.each do |id,name|
%tr
%td
= id
%td
= name
works fine for me so this indicate that what ever your con2.query("SELECT * FROM tblSites", :as => :array) returns it's not exactly what you expected.

why pageObject based on Cheezy does not work?

I'm new to ruby (1.9.3)
I have intermediate experience with Selenium WebDriver plus C#. I want to move to Watir-Webdriver.
I'd be grateful to find out why the first block of IRB code works, but the second block simply loads the correct page, then does nothing. The page is active and responds to manual input.
The second block of code is based on the PageObject example here:
https://github.com/cheezy/page-object/wiki/Get-me-started-right-now%21
require 'watir-webdriver'
browser = Watir::Browser.start 'http://x.com/'
browser.select_list(:id, "ddlInterestType").select("Deferred")
browser.select_list(:id, "ddlCompanyName").select("XYZ")
browser.button(:value,"Enter Transactions").click
Second block
require 'watir-webdriver'
browser = Watir::Browser.new :firefox
browser.goto "http://x.com/"
deferredPage = DeferredPage.new(browser)
deferredPage.interestType.select = 'Deferred'
deferredPage.company.select = 'XYZ'
deferredPage.enterTransactions
class DeferredPage
include PageObject
select_list(:interestType, :id => 'ddlInterestType')
select_list(:company, :id => 'ddlCompanyName')
button(:enterTransactions, :id => 'btnEnterTransactions')
end
In your page-object code example, after loading the page, an exception is likely being thrown (which makes it seem like nothing happens). That code should throw an no method exception:
undefined method `select=' for "stuff":String
When you declare a select list there are three methods created:
your_select= - this is for setting the select list
your_select - this is for getting the select list value
your_select_element - this is for getting the page-object gem element
When you do deferredPage.interestType, it returns a string that is the value of the select list. Strings do not have a select= method, which is why you get the exception (and does nothing).
The two selections should be done without the .select:
deferredPage.interestType = 'Deferred'
deferredPage.company = 'XYZ'
As you can see the page-object API is slightly different than the watir API.
While googling for info on page objects, I found this page by Alister Scott. :
http://watirmelon.com/2012/06/04/roll-your-own-page-objects/
For an idiot++ such as me, I think I'll use his method until I know more about Watir-Webdriver. Based on #justinko's comment, I'll stick to one API for the present. I tried rolling my own, and it works fine:
require 'watir-webdriver'
browser = Watir::Browser.new :ie
class DeferredPage
def initialize( browser )
#browser = browser
end
def enterIntType(intType)
#browser.select_list(:id, "ddlInterestType").select(intType)
end
def clickEnter()
#browser.button(:value,"Enter Transactions").click
end
end
dp = DeferredPage.new(browser)
browser.goto "http://x.com"
dp.enterIntType( "Deferred" )
dp.clickEnter
Could you please let us know what error you are getting? I suspect the problem you are seeing is related to the way the Ruby interpreter reads the code. It reads the file from top to bottom and you are using the DeferredPage class before it is defined. What would happen if you changed your code to this:
require 'watir-webdriver'
require 'page-object'
browser = Watir::Browser.new :firefox
class DeferredPage
include PageObject
select_list(:interestType, :id => 'ddlInterestType')
select_list(:company, :id => 'ddlCompanyName')
button(:enterTransactions, :id => 'btnEnterTransactions')
end
deferredPage = DeferredPage.new(browser)
deferredPage.navigate_to "http://x.com/"
deferredPage.interestType = 'Deferred'
deferredPage.company = 'XYZ'
deferredPage.enterTransactions
In this case I am declaring the class prior to using it.
Another thing I might suggest is creating a higher level method to perform the data entry. For example, you could change your code to this:
require 'watir-webdriver'
require 'page-object'
browser = Watir::Browser.new :firefox
class DeferredPage
include PageObject
select_list(:interestType, :id => 'ddlInterestType')
select_list(:company, :id => 'ddlCompanyName')
button(:enterTransactions, :id => 'btnEnterTransactions')
def do_something(interest, company)
self.interestType = interest
self.company = company
enterTransactions
end
end
deferredPage = DeferredPage.new(browser)
deferredPage.navigate_to "http://x.com/"
deferredPage.do_someting('Deferred', 'XYZ')
This is cleaner - the access to the page is abstracted behind a method that should add some business value.
-Cheezy

What's the right way to define an anchor tag in rails?

It's obvious from the documentation (and google) how to generate a link with a segment e.g. podcast/5#comments. You just pass a value for :anchor to link_to.
My concern is about the much simpler task of generating the <a name="comments">Comments</a> tag i.e. the destination of the first link.
I've tried the following, and although they seemed to work, the markup was not what I expected:
link_to "Comments", :name => "comments"
link_to "Comments", :anchor => "comments"
I think I'm missing something obvious. Thanks.
You are getting confused by Ruby's syntactic sugar (which Rails uses profusely). Let me explain this briefly before answering your question.
When a ruby function takes a single parameter that is a hash:
def foo(options)
#options is a hash with parameters inside
end
You can 'forget' to put the parenthesis/brackets, and call it like this:
foo :param => value, :param2 => value
Ruby will fill out the blanks and understand that what you are trying to accomplish is this:
foo({:param => value, :param2 => value})
Now, to your question: link_to takes two optional hashes - one is called options and the other html_options. You can imagine it defined like this (this is an approximation, it is much more complex)
def link_to(name, options, html_options)
...
end
Now, if you invoke it this way:
link_to 'Comments', :name => 'Comments'
Ruby will get a little confused. It will try to "fill out the blanks" for you, but incorrectly:
link_to('Comments', {:name => 'Comments'}, {}) # incorrect
It will think that name => 'Comments' part belongs to options, not to html_options!
You have to help ruby by filling up the blanks yourself. Put all the parenthesis in place and it will behave as expected:
link_to('Comments', {}, {:name => 'Comments'}) # correct
You can actually remove the last set of brackets if you want:
link_to("Comments", {}, :name => "comments") # also correct
In order to use html_options, you must leave the first set of brackets, though. For example, you will need to do this for a link with confirmation message and name:
link_to("Comments", {:confirm => 'Sure?'}, :name => "comments")
Other rails helpers have a similar construction (i.e. form_for, collection_select) so you should learn this technique. In doubt, just add all the parenthesis.
If you want to go through rails, I suggest content_tag (docs).
Example:
content_tag(:a, 'Comments', :name => 'comments')
<%= link_to('new button', action: 'login' , class: "text-center") %>
created an anchor tag for login.html i.g
new button
and for
new button
use
<%= link_to('new button', controller: 'admin',
action: 'login' , class: "text-center") %>