I am developing a web application with Ruby on Rails/Jquery Mobile.
The SQLite 'Inventory' schema consists of existingfixture:string, replacementfixture:string, and quantity:integer. There are two other tables called oldlights and newlights. These simply contain the options for existingfixtures and replacementfixtures, respectively. Oldlights and newlights both have lightname:string and value:integer, where value is how many Watts the given light name uses.
I also want my program to display, the difference in watts from existing to replacement fixture. I want to be able to have another column saying how many Watts are saved anually, but I have no idea how to go about this. The values are associated in oldlights/newlights. However, I can't figure out how to access them and perform mathematical equations with them in a seperate column.
Code for Displaying values from database:
<fieldset class="ui-grid-c"><center>
<div class="ui-block-a"><%= inventory.existing %></div>
<div class="ui-block-b"><%= inventory.replacement %></div>
<div class="ui-block-c"><%= inventory.quantity %></div>
<div class="ui-block-d"><%= link_to 'Remove', [inventory.client, inventory],
:confirm => 'Are you sure?',
:method => :delete %></div></center>
</fieldset>
Code for adding inventory
<%= form_for([#client, #client.inventories.build]) do |f| %>
<fieldset class="ui-grid-c">
<div class="ui-block-a"><%= f.select :existing, Olight.all.collect{|p| [p.name]}, { :include_blank => true } %></div>
<div class="ui-block-b"><%= f.select :replacement, Nlight.all.collect{|p| [p.name]}, { :include_blank => true } %></div>
<div class="ui-block-c"><%= f.number_field :quantity, "data-mini" => "true" %></div>
<div class="ui-block-d"></div>
</fieldset>
<%= f.submit 'Add Inventory'%>
<% end %>
Sebastien is partly correct. (Parsing the fixture name won't work, since in the "1-4' 40W-T12-ESMB" naming, 40 isn't the wattage of the fixture, but that of a single 4 foot T-12 lamp, and the engineering isn't as simple as the wattage of a "3-4' 40W-T12-ESMB" fixture == 3 times the wattage of a "1-4' 40W-T12-ESMB" fixture. The aggregate fixture wattage depends on a number of other factors in addition to lamp wattage.)
You should read a this page! "Section 3 - Making Select Boxes with ease" for more information on how to setup your drop lists -- I like to construct using options_for_Select. I believe you want the form where the name is displayed, but the id of the old and new fixtures is what is stored in your database.
In your rails controller when you are saving an inventory combination (existing, replacement, and count), you use the old and new fixture ids to look up their wattages, do the math, then store the savings value. When the page is displayed, all the data should be present.
On a style note, I'd move the Olight/Nlight.all.collect code out of the page template and into the controller, setting up instance variables to be used by the view...
#existing = Olight.all.collect{|old| [old.name, old.id]}
#replacement = Nlight.all.collect(|new| [new.name, new.id]}
I thank you have to do many things :
First, you have to get Watts from the new one and the previous one. For that, 2 solutions :
You make a regexp to extract the watt from the name or you add a field on light where the user can specify watts.
Second, on "Add inventory" click, you send an ajax call to your server with extra parameters as "newWatts" and "oldWatts". On create action on server side, you compute the energy saved and you save it in your database.
Do you understand?
Related
I need to dynamically load a sidebar's content into a sidebar partial based on the presence of a directory name-spaced as the controller_name (if present) and the action_name (always used). They both are derived from the Rails hash and map to the .../views/sidebars/[controller_name]/[action_name] if there is a directory for the controller_name and to .../views/sidebars/[action_name] if there isn't an associated directory namespaced with the Controller's name.
/views
/sidebars
/static
/_about.html.erb
/_contact.html.erb
/...
/_styles.html.erb #outside of any controller structure
I am trying to use the following code to dynamically load the correct sidebar partial:
<%= "sidebars/#{controller_name}".to_s.present? ? yield("sidebars/#{controller_name}/#{action_name}" : yield("sidebars/#{action_name}") %>
This checks to see if there is a directory called by the controller_name and it renders the correct partial based on the structure indicated.
I am getting the following error:
Encountered a syntax error while rendering template: check <div id='sidebar_left'>
<p>Template: [_sidebar-left.html.erb]</p>
<%= render "sidebars/#{action_name}" %>
<%= "sidebars/#{controller_name}".to_s.present? ? yield("sidebars/#{controller_name}/#{action_name}" : yield("sidebars/#{action_name}") %>
UPDATE
Ok so it turns out that ternary operators don't always return the value, particularly if it is a computed string value. In this case, I was expecting the value to return as either sidebars/static/home or sidebars/styles. For some reason I can't explain, ternary operators don't work that way, even though I (thought!) I was returning a string value from the operation.
To get rid of the syntax error, I had to assign the operator to a variable name, in this case sb_name and then render it on the next line. This is the final code:
<% sb_name = "sidebars/#{controller_name}".to_s.present? ? "sidebars/#{controller_name}/#{action_name}" : "sidebars/#{action_name}" %>
<%= render sb_name %>
Now, while this resolved the syntax error, I am now getting a Missing partial sidebars/_about error in the view. The _styles file exists as /views/sidebars/_styles.html.erb, right where it should. Since there is not a folder name-spaced to the controller being called (in this case StylesController), it should be pulling up the file directly underneath the /sidebars/ directory. However, this is not the case.
I found some help on SO here. I wasn't checking the directory/file structure properly. The final syntax is this:
<% sb_name = File.directory?("app/views/sidebars/#{controller_name}") ? "/sidebars/#{controller_name}/#{action_name}" : "/sidebars/#{action_name}" %>
<%= render partial: "#{sb_name}" %>
I am trying to click links on a page and able to do only the first one. There are four more having similar code, but it says it cannot locate the other four.
This is the line of code that works:
#browser.div(class:'ms-vb itx').link(:text =>'Rapid Alignment').click
This is one of the four that does not work:
#browser.div(class:'ms-vb itx').link(:text =>'Design Develop Integrate and Test').click
HTML:
<div class="ms-vb itx" onmouseover="OnItem(this)" CTXName="ctx586" id="1" Field="LinkTitle" Perm="0xb008031061" EventType=""><a onfocus="OnLink(this)" href="asdm.nwie.net/_layouts/15/…; onclick="EditLink2(this,586);return false;" target="_self">Rapid Alignment</a></div>
<div class="ms-vb itx" onmouseover="OnItem(this)" CTXName="ctx586" id="3" Field="LinkTitle" Perm="0xb008031061" EventType=""><a onfocus="OnLink(this)" href="asdm.nwie.net/_layouts/15/…; onclick="EditLink2(this,586);return false;" target="_self">Design Develop Integrate and Test</a></div>
I think the issue is the use of #div which will return a single div
Try this instead
divs = #browser.divs(class:'ms-vb itx')
Then
divs.each do |d|
d.link.click
end
#divs returns a DivCollection which includes Enumerable so all Enumerable methods will work as well including things like select e.g.
divs.select { |d| d.link(:text =>'Rapid Alignment') }
You'll have to specify which <div> you are targeting. There are two or possibly more <div> tags with the same class attribute.
Given this HTML snippet:
<div class="ms-vb itx" onmouseover="OnItem(this)" CTXName="ctx586" id="1" Field="LinkTitle" Perm="0xb008031061" EventType=""><a onfocus="OnLink(this)" href="asdm.nwie.net/_layouts/15/…" onclick="EditLink2(this,586);return false;" target="_self">Rapid Alignment</a></div>
<div class="ms-vb itx" onmouseover="OnItem(this)" CTXName="ctx586" id="3" Field="LinkTitle" Perm="0xb008031061" EventType=""><a onfocus="OnLink(this)" href="asdm.nwie.net/_layouts/15/…" onclick="EditLink2(this,586);return false;" target="_self">Design Develop Integrate and Test</a></div>
You need to target the appropriate <div> by supplying the index in the locator:
p b.div(:class => 'ms-vb itx').link(:text => 'Rapid Alignment').exists?
#=> true
p b.div(:class => 'ms-vb itx').link(:text => 'Design Develop Integrate and Test').exists?
#=> false
p b.div(:class => 'ms-vb itx', :index => 1).link(:text => 'Design Develop Integrate and Test').exists?
#=> true
But locating elements by index can be fragile if and when UI elements change. You should consider locating using the id attributes, which--according to spec--are unique.
This fails because div is same so it tries to locate the same div everytime and starts to search the given link, So it fails second time when you tries to locate the different link.
Actually you do not need of div to locate that link, you simply write this code it will work
b.link(:text=>'Rapid Alignment',:visible=>true).click
b.link(:text=>'Design Develop Integrate and Test',:visible=>true).click
That link text itself is the identification to that link, So you do not need of any division, directly write b.link(), it's enough.
The context is I'm using watir-webdriver and I need to locate if an image appears prior to a particular item in a list.
More specifically, there is a section of the site that has articles uploaded to them. Those articles appear in a list. The structure looks like this:
<div id="article-resources"
<ul class="components">
...
<li>
<div class="component">
<img src="some/path/article.png">
<div class="replies">
<label>Replies</label>
</div>
<div class="subject">
Saving the Day
</div>
</div>
</li>
...
</ul>
</div>
Each article appears as a separate li item. (The ellipses above are just meant to indicate I can have lots of liste items.)
What I want our automation to do is find out if the article has been appropriately given the image article.png. The trick is I need to make sure the actual article -- in the above case, "Saving the Day" -- has the image next to it. I can't just check for the image because there will be multiples.
So I figured I had to use xpath to solve this. Using Firefox to help look at the xpath gave me this:
id("article-resources")/x:ul/x:li[2]/x:div/x:img
That does me no good, though, because the key discriminator seems to be the li[2], but I can't count on this article always being the second in the list.
So I tried this:
article_image = '//div[#class="component"]/a[contains(.,"Saving the Day")]/../img'
#browser.image(:xpath => article_image).exist?.should be_true
The output I get is:
expected: true value
got: false (RSpec::Expectations::ExpectationNotMetError)
So it's not finding the image which likely means I'm doing something wrong since I'm certain the test is on the correct page.
My thinking was I could use the above to get any link (a) tags in the div area referenced as class "component". Check if the link has the text and then "back up" one level to see if an image is there.
I'm not even checking the exact image, which I probably should be. I'm just checking if there's an image at all.
So I guess my questions are:
What am I doing wrong with my XPath?
Is this even the best way to solve this problem?
Using Watir
There are a couple of approaches possible.
One way would be find the link, go up to the component div and then check for the image:
browser.link(:text => 'Saving the Day').parent.parent.image.present?
or
browser.div(:class => 'subject', :text => 'Saving the Day').parent.image.present?
Another approach, which is a little more robust to changes, is to find the component div that contains the link:
browser.divs(:class => 'component').find { |component|
component.div(:class => 'subject', :text => 'Saving the Day').exists?
}.image.present?
Using XPath
The above could of course be done through xpath as well.
Here is your corrected xpath:
article_image = '//div[#class="component"]//a[contains(.,"Saving the Day")]/../../img'
puts browser.image(:xpath => article_image).present?
Or alternatively:
article_image = '//a[contains(.,"Saving the Day")]/../../img'
browser.image(:xpath => article_image).present?
Again, there is also the top down approach:
article_image = '//div[#class="component"][//a[contains(.,"Saving the Day")]]/img'
browser.image(:xpath => article_image).present?
You can read more about these approaches and other options in the book Watirways.
I need to specify a minimum width for a select box input on a form using form_for(#project).
I have <%= f.select(:category, "", html_options{:size => 30} ) %>, but I'm getting a SyntaxError in the ActionController.
Any ideas?
The select helper takes four parameters. If you want to add an attribute to the HTML tag it generates, that's provided in the fourth parameter. You'll want to do something like this:
<%= f.select(:category, "", {}, {:size => 30}) %>
The html_options name you see in the Rails API is simply the internal parameter name used by Rails to apply those hash values to the tag it generates. You simply need to provide it a hash.
Also, the size of a select box doesn't set the width or minimum width, it describes the number of elements to make visible vertically (See this jsFiddle for an example). So you may actually be looking for something more like this:
<%= f.select(:category, "", {}, {:style => "min-width: 100px;"}) %>
I have markup stored in a database, which I am pulling out and placing onto a page.
below is a basic sample of what I have, without any db calls for ease of example;
The controller:
ViewData["testMarkup"] = "I was here <%= DateTime.Now.Year %>";
The View:
<%= ViewData["testMarkup"] %>
now this out puts: I was here
and no date, this is because it is ignoring the <%= %> part, is there anyway I can output the above said string and woudl include the year?
Many thanks,
Just do the following:
ViewData["testMarkup"] = "I was here " + DateTime.Now.Year.ToString();
Or am I missing something? Code blocks, such as <%= DateTime.Now.Year %> are only valid when they are part of the markup:
<div>The year is <%= DateTime.Now.Year %></div>
The markup in the database is being treated as a string, not as code in your view language, so it is simply writing it out as text, c# and all.
Two alternate methods:
1 - Use a templating system, such as
ViewData["testMarkup"] = "I was here #YEAR#";
and have a method that replaces your tokens (e.g. #YEAR#) with their values at render time, e.g.,
<%= ReplaceTokens((string)ViewData["testMarkup"]) %>
Where ReplaceTokens looks like:
public static ReplaceTokens(string s)
{
return s.Replace("#YEAR#", DateTime.Now.Year)
}
2 - Store your markup in a partial view, and save the name of the partial view in the database if necessary.
I do believe Phil Haack has the answer to my issue. http://haacked.com/archive/2009/04/22/scripted-db-views.aspx
I will have to check this out and see what happens