In teaching myself Sinatra I wanted to make a web app that monitored devices via ICMP and displayed the results in browser.
I have a config page where the user decides how many devices he wants to monitor and what the IP and description of those devices are. I want the form to be dynamic so I can iterate through the variables easily. I don't want to have to anticipate how many devices the user wants to track. I want something like this.
<form name="config" action="/config" method="post">
#of devices to check: <select name="numofdevices">
<% case $devices.to_i
when 1 %>
<option value=1 SELECTED>1</option>
<option value=2>2</option>
<option value=3>3</option>
<% when 2 %>
<option value=1>1</option>
<option value=2 SELECTED>2</option>
<option value=3>3</option>
<% when 3 %>
<option value=1>1</option>
<option value=2>2</option>
<option value=3 SELECTED>3</option>
<% end %>
</select> <br />
<% $devices.times do |devicenum| %>
Ip Address: <input type="text" name='<%= devicenum %>[ip]'> Description: <input type="text" name='<%= devicenum %>[desc]'><br />
<% end %>
Obviously this won't work though because the hash symbol comes in the form of a string. I would have to access a variable via
deviceOne = params[:"1"]
I could not iterate through this
$numofdevices.times do |num|
devices[num] = params[:num.to_s]
end
Mainly I want to throw all of these devices into an easily accessible array. I don't want to have to prepare for the number of devices the user might track ahead of time. I want the code to count the number of devices they selected and populate an array accordingly.
Ultimately I want to access a device like so. In an array of hashes.
$devices[0][:ip]
Then I could iterate through each devices easily.
$devices.each do |device|
puts "IP: #{device[:ip]}, Desc: #{device[:desc]}"
end
SOmething like this came to mind
$numofdevices.times do |devicenum|
devices[devicenum] = params[:devicenum]
end
I know for sure I am doing something wrong and that my knowledge of how ruby Hashes/arrays work must be limited. I was hoping there was a better way of doing this rather then the following.
<form name="config" action="/config" method="post">
#of devices to check: <select name="numofdevices">
<% case $devices.to_i
when 1 %>
<option value=1 SELECTED>1</option>
<option value=2>2</option>
<option value=3>3</option>
<% when 2 %>
<option value=1>1</option>
<option value=2 SELECTED>2</option>
<option value=3>3</option>
<% when 3 %>
<option value=1>1</option>
<option value=2>2</option>
<option value=3 SELECTED>3</option>
<% end %>
</select> <br />
<% case $devices.to_i
when 1 %>
Ip Address: <input type="text" name='firstd[ip]'> Description: <input type="text" name='firstd[desc]'><br />
<% when 2 %>
Ip Address: <input type="text" name='firstd[ip]'> Description: <input type="text" name='firstd[desc]'><br />
Ip Address: <input type="text" name='secondd[ip]'> Description: <input type="text" name='secondd[desc]'><br />
<% when 3 %>
Ip Address: <input type="text" name='firstd[ip]'> Description: <input type="text" name='firstd[desc]'><br />
Ip Address: <input type="text" name='secondd[ip]'> Description: <input type="text" name='secondd[desc]'><br />
Ip Address: <input type="text" name='thirdd[ip]'> Description: <input type="text" name='thirdd[desc]'><br />
<% when 4 %>
Ip Address: <input type="text" name='firstd[ip]'> Description: <input type="text" name='firstd[desc]'><br />
Ip Address: <input type="text" name='secondd[ip]'> Description: <input type="text" name='secondd[desc]'><br />
Ip Address: <input type="text" name='thirdd[ip]'> Description: <input type="text" name='thirdd[desc]'><br />
Ip Address: <input type="text" name='fourthd[ip]'> Description: <input type="text" name='fourthd[desc]'><br />
<% end %>
I would then have to pre-create device variables ready to accept data should the user decide to use that many devices. MY route looks like this.
post '/config' do
#title = "Config"
$devices = params[:numofdevices].to_i
$firstdevice = params[:firstd]
$seconddevice = params[:secondd]
$thirddevice = params[:thirdd]
$fourthdevice = params[:fourthd]
erb :config
end
I am certain I am doing this wrong. If I want to track a large number of devices this becomes repetitive and cumbersome. I'm a learning newb. Can anyone out there point me in the right direction? :)
[EDIT]
I'm going to try the following in my post '/config'
params.keys.each do |key|
#objects.push(params[key])
end
[EDIT EDIT]
Here is the best I have been able to come up with.
In my config erb
<% $numofdevices.times do |id| %>
Ip Address: <input type="text" name='<%= id %>[ip]'> Description: <input type="text" name='<%= id %>[desc]'><br />
<% end %>
In my post 'config'
params.keys.each do |key|
$devices.push(params[key]) if params[key].include?("ip")
end
Now I don't have to worry what the symbols get named or how they are named. :p
Still if anyone has any other ways of doing this that would be even better I'd appreciate the input! :)
Here is the best I have been able to come up with.
In my config erb
<% $numofdevices.times do |id| %>
Ip Address: <input type="text" name='<%= id %>[ip]'> Description: <input type="text" name='<%= id %>[desc]'><br />
<% end %>
In my post 'config'
params.keys.each do |key|
$devices.push(params[key]) if params[key].include?("ip")
end
No I don't have to worry what the symbols get named or how they are named. :p
Still if anyone has any other ways of doing this that would be even better I'd appreciate the input! :)
Related
I'm trying to iterate through an array of which each entry will create an input field in a form made in ERB. I've set up a #loopcount integer that gets increased for every new entry in this array. I would like to use that increasing integer in fieldnames:
Item <input name="s_fieldname_<%= #loopcount %>" id="s_fieldname_<%= #loopcount %>" type="text" value="<%= field[0] %>" size="12"><br/>
Because of being inside the double quotations, that #loopcount is not taking. I'm guessing this is an escaping issue of some sort. %% did not work.
Edit: Add syntax
<% #fields.each do |field| %>
<span class="red"><%= field[0] %></span> - <%= field[1] %><br>
<strong>fieldname</strong> <input name="s_fieldname_#{#loopcount}" type="text" value="<%= field[0] %>" size="12"><br/>
<strong>show</strong> <input name="s_show_#{#loopcount}" type="checkbox" checked><br/>
<strong>required</strong> <input name="s_required_#{#loopcount}" type="checkbox"><br/>
<strong>description</strong> <input name="s_description_#{#loopcount}" type="text" value="" size="60"><br/>
<% #loopcount += 1 %>
<% end %>
Any ideas how I can achieve this? Cheers
Well, I don't know how this happened, but the first syntax now works upon replacement.
...name="s_fieldname_<%= #loopcount %>" type="text" value="<%= field[0] %>"...
I'm using Chrome for this, but Safari was also showing the same syntax result.
I want to change the value of a Ruby local parameter in my .erb file when a user clicks on a bit of text. (I am using Ruby with Sinatra, not Rails). The code looks like this:
<div class="modal-body">
<!-- Get ERB to work here -->
<p><i>No account? Register here</i></p> <!-- Should change new_user to true if clicked -->
<form class="input-group" style="margin: 0 auto" method="POST" action="/nanotwitter/v1.0/users/session">
<input class="form-control" type="text" name="username" placeholder="Username">
<br><br>
<input class="form-control" type="password" name="password" placeholder="Password">
<% if new_user %>
<br><br>
<input class="form-control" type="password" name="password2" placeholder="Repeat password">
<% end %>
<br><br>
<div class="input-group" style="margin: 0 auto">
<button type="button" class="btn btn-default form-control" style="width: 50%" data-dismiss="modal">Close</button>
<button class="btn btn-primary form-control" style="width: 50%" type="submit">
<% if new_user %>
Register
<% else %>
Log In
<% end %>
</button>
</div>
</form>
</div>
So obviously the Ruby code in the onlick attribute evaluates immediately, and I want it to only execute when the user clicks. I've searched this site and the internet, and I'm still not sure what the correct/standard implementation for this would be.
First, ruby dont interact with user events. Javascript does.
Second, what is new_user ? Simple variable? You want to use it to, say, swap forms for sign up\ sign in ? Or you want user to really register through this method?
If the case is to show sign in\ sign up form to user based oh his choice (new\registered), you should do it with only javascript.
In general, you should prepare markup for two different forms (register\login) and hide them according to some javascript variable, which user can choose.
I'm using MVC 2. When I do this:
<%: Html.HiddenFor(model => model.SourceType) %>
I get this in the view:
<input id="SourceType" type="hidden" value="" name="SourceType">
I confirmed that the model has the correct value before returning the view in the controller. The value is correctly set to 11.
I started trying different things to see if I could get any different result and found that if I repeat the textbox like this:
<%: Html.HiddenFor(model => model.SourceType) %>
<%: Html.HiddenFor(model => model.SourceType) %>
Results in this:
<input id="SourceType" type="hidden" value="" name="SourceType">
<input id="SourceType" type="hidden" value="11" name="SourceType">
Can anyone think of a reason why the view is rendering the first textbox with a blank value while the second contains the correct value?
EDIT: I thought this might be caused by javascript so I removed all scripts from the page, but the value is still blank the first time and correct when repeated.
EDIT: Based on jle's link I tried this:
<input type="hidden" value="<%= Html.AttributeEncode(Model.SourceType) %>" id="SourceType" name="SourceType" />
<input id="SourceType" type="hidden" value="11" name="SourceType">
<input id="SourceType" type="hidden" value="11" name="SourceType">
And got this:
<input id="SourceType" type="hidden" name="SourceType" value="">
<input id="SourceType" type="hidden" value="11" name="SourceType">
<input id="SourceType" type="hidden" value="11" name="SourceType">
Also, based on the link I tried this in the controller just before returning the view:
ModelState.Clear();
Result is still the same. The first value to be rendered is blank.
EDIT: Here is the controller code:
Source source = SourceService.NewSource();
return View("Source", Mapper.Map(source, new SourceViewModel()));
EDIT: Problem seems isolated to the use of HiddenFor helper.
I did this:
<%: Model.SourceType %>
<%: Html.HiddenFor(model => model.SourceType) %>
<%: Html.HiddenFor(model => model.SourceType) %>
And got this:
11
<input id="SourceType" type="hidden" value="" name="SourceType">
<input id="SourceType" type="hidden" value="11" name="SourceType">
EDIT: Following jle's input I tried this but still no luck:
<input id="SourceType" type="hidden" value="<%: Model.SourceType %>" name="SourceType">
<%: Html.HiddenFor(model => model.SourceType) %>
<%: Html.HiddenFor(model => model.SourceType) %>
This results in this:
<input id="SourceType" type="hidden" name="SourceType" value="">
<input id="SourceType" type="hidden" value="11" name="SourceType">
<input id="SourceType" type="hidden" value="11" name="SourceType">
EDIT: If I exclude the name when not using the helper and used type="text" instead of type="hidden". This renders the value, but doesn't post because it is missing the name (I think).
This:
<input id="SourceType" type="text" value="<%: Model.SourceType %>" style="visibility: hidden;"/>
Results in this which doesn't bind to the model when posted? How can adding the name affect the value?
<input id="SourceType" type="text" style="visibility: hidden;" value="11">
EDIT: If anyone can think of something to try I'd love to hear it. I've resorted to an ugly work around involving the addition of a stand in property on the view model. This allows me to set the stand in property value in the controller which renders as expected on the page. On post then I have to manually map the property back the SourceType property. Ugh...
Try adding ModelState.Remove("SourceType"); in the controller:
ModelState.Remove("SourceType");
Source source = SourceService.NewSource();
return View("Source", Mapper.Map(source, new SourceViewModel()));
If there is already a value in the ModelState that corresponds to your value, it will use that first. Alternatively, I would double check that the value is mapping correctly to the ViewModel. When you say you checked this, did you check the model itself or just the Source property?
Edit:
Try <input id="SourceType" type="hidden" value="<%: Model.SourceType %>" name="SourceType">
Make sure you don't have an empty querystring parameter by the same property name. HiddenFor appears to prefer what's in the querystring over what's in the model.
I'm trying to generate a form with an html.erb file, that looks something like this:
<form class="edit-booking" method="post" action="/users/<%= current_user.id %>/accounts/1/bookings/new" data-remote="true">
<header><h1>Edit booking</h1></header>
<input class="booking-name" name="booking[name]" placeholder="Name of the user" type="text" />
<fieldset class="booking-list">
<h2>Booking details</h2>
<ul>
<li>
<input name="booking[name]" type="text" value="Unit name" disabled/>
<input name="booking[check_in]" type="date" value="" />
<input name="booking[check_out]" type="date" value="" />
</li>
</ul>
</fieldset>
<input name="submit" type="submit" value="Save" />
</form>
an I have this ruby code:
<%= form_for [current_user] do |f| %>
<header>
<h1>Edit booking</h1>
</header>
<%= field_set_tag 'Booking details' do %>
<%= f.fields_for :bookings do |booking_form| %>
<%= booking_form.text_field :name, placeholder: "Name" %>
<%= booking_form.text_field :check_in, placeholder: "Check-in" %>
<%= booking_form.text_field :check_out, placeholder: "Check-out" %>
<% end %>
<% end %>
<%= f.submit "Save" %>
<% end %>
But what happens is, it doesn't render anything on the browser even though in the chrome dev tool it shows a form tag.
EDIT:
The html generated is as following:
<form accept-charset="UTF-8" action="/users/1/accounts/1" class="edit_account" id="edit_account_1" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"><input name="_method" type="hidden" value="patch"><input name="authenticity_token" type="hidden" value="fzA+hkk3o+itJOI0UDj9F01DuI+A5+zgQ1EVGlwrPww="></div>
<header>
<h1>Edit booking</h1>
</header>
<fieldset><legend>Booking details</legend>
<input id="account_bookings_name" name="account[bookings][name]" placeholder="Name" type="text">
<input id="account_bookings_check_in" name="account[bookings][check_in]" placeholder="Check-in" type="text">
<input id="account_bookings_check_out" name="account[bookings][check_out]" placeholder="Check-out" type="text">
</fieldset>
<input name="commit" type="submit" value="Save">
</form>
My Account model:
class Account < ActiveRecord::Base
belongs_to :user
has_many :products
has_many :bookings
accepts_nested_attributes_for :bookings
accepts_nested_attributes_for :products
end
In your model add:
#Account model
accepts_nested_attributes_for :bookings
Also, should your current_user be an account?
I am using the below ASPX coding "Not Razor" in MVC3 and get the unwanted code "System.Web.Mvc.Html.MvcForm " while run in the view page.
<%= Html.BeginForm("ChartFeatures","Chart") %>
<div>
<h3>EXPORT CHART</h3><br />
Enter file name:<input type="text" id="FileName" name="FileName" value=""/>
Type:
<select name="Type">
<option value="Bmp">Bmp</option>
<option value="Gif">Gif</option>
</select><br />
<input type="submit"value="Export"id="submit"/>
</div>
anyone could help me please.
Thanks,
Bharathi.
Wrap you form content in using and remove =:
<% using(Html.BeginForm("ChartFeatures","Chart")) { %>
your form content here
<% } %>