Rails Bootstrap modal pass in value without javascript? - ruby-on-rails

I have a Rails app with a Bootstrap modal.
Here is part of the code that launches the modal:
<a type="button" class="btn" href="#labor_modal" data-toggle="modal" data-woid= <%= workorder.id %>><i class="icon-time"></i></a>
Here's part of the code for the modal:
<div class="modal fade" id="labor_modal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>Add Labor</h3>
</div>
<div class="modal-body">
<%= simple_form_for(Event.new, validate: true, remote: true, html: {"data-type" => :json}) do |f| %>
<%= f.hidden_field :workorder_id, :value => data-woid.val() %>
I want to get the work order.id passed to the modal so it can be saved in the new record.
This code isn't working:
<%= f.hidden_field :workorder_id, :value => data-woid.val()
Any help would be appreciated !!
PS - I was hoping I could do this without jquery - but, if I need it so be it.

<%= %> is an ERb (embedded Ruby) tag. Inside should be Ruby code.
data-woid.val()
is not valid Ruby in the context which you use it.
ERb is processed before rendering HTML. At the time ERb is processed, Ruby is not aware of the DOM or rendered HTML elements or their attributes. There is no way to read HTML data attributes in Ruby via ERb. You must access them after the page is rendered and the DOM is built. Use JavaScript/jQuery for this.
I'm guessing that work_order.id will be used to set an association. Exposing this to the user is insecure; it is possible to change the value to anything before submitting. Associations should be set in the controller, specifically the create action before you call save.

Well the question said without javascript. My answer might not work in every scenario or answer the question perfectly, plus it is will not scale, but it uses no javascript!
So what I would do is create as many modals as I need according to the parameter. I would do that by assigning them different ids. This can be done dynamically on rails.
Then each link would open (reveal) its matching modal, and it would seem like a parameter was sent, because each modal would have the necessary information, set at render time.

Related

Is it okay to read date from database in the view template in Ruby on Rails?

I am revisiting the basics of MVC and Ruby on Rails. I am looking at my code and found that I have used this select tag in my Edit User Profile view.
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<%= f.label :country_id, "From*" %>
</div>
<div class="panel-body">
<%= f.select :country_id, Country.order(:name).collect {|p| [ p.name, p.id ] }, {}, { :class => 'form-control' } %>
</div>
</div>
</div>
I am accessing the Country table in the view. I am pretty sure this should not be done but somehow it works. Why does it work? What is the correct way to do it?
Thanks.
There's no reason why what you have won't work. Remember, a view template is an "embedded ruby" file. It has Ruby embedded in an HTML template. When the view is "rendered" by the controller, all of the code inside it gets executed and whatever output is generated by its Ruby code becomes part of the HTMl document. In this case, the output generated by the Ruby code is a bunch of HTML tags and Country names and IDs.
To avoid having this logic in the view, you would put it in the controller and save it to an instance variable (i.e. something like #select_vals) and then reference that variable in the view template.
It works because Rails provides a lot of 'magic' under the hood; this functionality, at a guess, is probably part of the ActionView library (I haven't checked).
One of the fundamental principles of the MVC model is that you don't do this in the view. This logic should be done in the controller.
The correct way ->
in Controller method:
#country_vals = Country.order(:name).pluck(:name, :id)
No need to use collect().
In your view:
<%= f.select :country_id, #country_vals, {}, { :class => 'form-control' } %>

Rails, 1 form, two buttons. Search and New

I think I'm trying to do something similar to this question but in rails. I would like to have a search form of sorts, but instead of two separate forms I want to use one text input and have two submit buttons, one which initiates a search and the other begins creating a new work order using the parameter from the form. I have already implemented the second half, but can't seem to find an obvious way to do it. This rails cast seems to start to get at what I want, but it seems like the rails helpers are getting in the way more than anything. Is there any way to do this without javascript? Also it seems like I'm mixing raw html with rails erb, so I suspect that can be improved as well. Unless it turns out rails simply can't do what I want then does that mean I need to resort to straight up HTML or even javascript? My only hesitation to use javascript/jquery is that I am currently very weak with them and wouldn't even know where to put the js files or what to name them.
<%= form_tag new_work_order_path, :method => "get", class: "navbar-form navbar-left" do %>
<div class="form-group">
<%= text_field_tag :client_number, params[:client_number], class: "form-control", placeholder: "Enter client number"%>
</div>
<button type="sumbit" class="btn btn-default">New Work Order</button>
<% end %>
Give each button a value attribute.
<%= form_tag new_work_order_path, :method => "get", class: "navbar-form navbar-left" do %>
<div class="form-group">
<%= text_field_tag :client_number, params[:client_number], class: "form-control", placeholder: "Enter client number"%>
</div>
<button type="submit" class="btn btn-default" value="new">
New Work Order
</button>
<button type="submit" class="btn btn-default" value="search">
Search
</button>
<% end %>
Then in your controller method check the params[:commit]:
if params[:commit] == "new"
# create the new WorkOrder
else
# do the search for existing WorkOrders
end
You may want to use a different controller method name since it will be handling both search and new instead of just new.
You should have two different actions for every method(new and search), this for REST good practices.
And for this, you could use other rails form way and set the action for every button like <%= button_to 'Call Action', action_path, method: [POST|GET]%>

rails Initialize new object through associated search

In my rails application I would like to be able to search for a client from the nav bar and have it automatically provide the WorkOrderController with the associated client. The goal is to automatically generate some of the work order information before the user gets to the new view. I was hoping to do this by making the new work order path nested under clients, but I'm not sure where to turn the form submission into a find to return the client for use in the work order controller. Clearly I am missing a method somewhere, but I'm not sure where to put it and what exactly it is I need it to do.
As far as I can tell what I need to do is somehow have the form submit to some method, which would then redirect to the new work order page with the :client_id in the params.
Am I totally off base here or am I missing something relatively small? An hour and a half of searching didn't turn up much as most guides talk about the form_for functionality. This doesn't appear to be a full on search either.
#routes.rb
....
resources :client do
get 'schedule', to: 'work_order#client_schedule'
get 'archive', to: 'work_order#client_archive'
resources :work_order, only: [:new]
end
.....
#application.html.erb
.....
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter client number">
</div>
<button type="sumbit" class="btn btn-default">New Work Order</button>
</form>
.....
#WorkOrderController.rb
....
def new
client = Client.find(params[:client_id])
#workorder = WorkOrder.new(client: client)
end
....
EDIT:
I made the following change and now when I attempt to load the page I get an error saying I am missing the client_id parameter, though I thought that is what I'm looking for in the first place
<%= form_tag new_client_work_order_path, :method => "get", class: "navbar-form navbar-left" do %>
<div class="form-group">
<%= text_field_tag :search, params[:search], class: "form-control", placeholder: "Enter client number"%>
</div>
<button type="sumbit" class="btn btn-default">New Work Order</button>
<% end %>
EDIT 2:
Was able to achieve my desired result by doing the following:
In work_order_controller.rb
....
def new
client = Client.find_by(clientnumber: params[:client_number])
#workorder = WorkOrder.new(client: client)
end
....
I switched the routes so that the new route was not nested under client and then changed the form to be:
<%= form_tag new_work_order_path, :method => "get", class: "navbar-form navbar-left" do %>
<div class="form-group">
<%= text_field_tag :client_number, params[:client_number], class: "form-control", placeholder: "Enter client number"%>
</div>
<button type="sumbit" class="btn btn-default">New Work Order</button>
<% end %>
I get the impression that I've created some other problem I don't yet see though, but I could just be paranoid
Scanning your code quickly, I don't see anything missing and while there's a number of ways to get this done, I think you're on the (a) right track.
Building things like this in Rails involves getting quite a number of components all working together at the same time, so in this case I'd focus on each step in turn (chronologically) to verify that it works as expected. Specifically I'd:
Watch the Rails console when I click that "New Work Order" button to verify that the client_id parameter is "seen" by the controller. (On closer inspection, according to your HTML, I don't see how this form would pass this parameter... or how the form would submit in the first place. Where's the form's action attribute?)
Use puts statements in the controller #new action to verify that the client object is initialized properly and that #workorder.client_id is the expected value.
Add output to the #new view template that prints out the #workorder.client_id to verify that the ID is carried over to the view. I don't see this view template in the above code snippets so I don't know what you expect to show up.
And so forth. Just breaking the problem into smaller steps so they're easier to figure out what's happening. Good luck!

Nested fields not submitting Rails 4

I',m trying to achieve a simple nested model form in Rails 4. This is probably something very simple, but just can't figure it out.
So I have an edit view, in which I create the nested fields:
<%= f.fields_for :bankaccounts do |bankaccount| %>
<%= render 'bankaccount_fields', :f => bankaccount %>
<% end %>
These work fine and even the link:
<%= link_to_add_association 'add', f, :bankaccounts , :class => "link"%>
works fine. The fields appear as they should when clicked.
The real problem is, that when I submit the form. It doesn't send the parameters back to web server which have been inputted into these added fields. (Can't see them anywhere in the webrick console) The form only submits the old bankaccount parameters as it should:
"bankaccounts_attributes"=>{"0"=>{"iban"=>"121221", "swift"=>"121212", "id"=>"3"}, "1"=>{"iban"=>"33333", "swift"=>"33333", "id"=>"9"}, "2"=>{"iban"=>"121212", "swift"=>"211212", "id"=>"10"}
Above attributes should contain four bank accounts.
FWIW: Turbolinks is also disabled.
EDIT: Here's the code from bankaccount_fields partial:
<div id="tilit">
<div class="area-form">
<div class="col">
<div class="box-row">
<label for="iban" class="label">Iban</label>
<div class="input-row no-italic">
<%= f.text_field :iban, :id => "iban", :class => "input-text" %>
</div>
</div>
</div>
<div class="col">
<div class="box-row">
<label for="swift" class="label">Swift</label>
<div class="input-row no-italic">
<%= f.text_field :swift, :id => "swift", :class => "input-text" %>
</div>
</div>
</div>
</div>
pic of inspect element
EDIT: Debugger outputs reg. parameters:
(rdb:2) #_params
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"181xsndllcPmpvpMaDi70IXh8SpaSYxs0eiSo19qwfI=", "producer"=>{"name"=>"Anne", "RH_nro"=>"", "ytunnus"=>"", "prepaymentpercentage"=>"", "streetaddress"=>"", "zip"=>"", "city"=>"", "www"=>"", "bankaccounts_attributes"=>{"0"=>{"iban"=>"13123123", "swift"=>"121212", "id"=>"3"}, "1"=>{"iban"=>"33333", "swift"=>"33333", "id"=>"9"}, "2"=>{"iban"=>"121212", "swift"=>"211212", "id"=>"10"}}}, "commit"=>"TALLENNA", "action"=>"update", "controller"=>"producers", "id"=>"54"}
Should contain one more bankaccount_attributes record, but only contains the ones which are not dynamically added.
I've been scratching my head for hours now, so any help would be greatly appreciated.
Also sorry if the question is formed badly, this is my first :)
I have found the problem to my application, If don't know if anyone find this useful anymore or not.
I am guessing you have written your form_for inside a HTML table(that's what I did). If so the browser generates a inconsistent DOM. If you generate form inputs dynamically it wont put it inside the form unless you are selecting it through form selector. So the solution is put the form outside the HTML table.
What are your strong params & controller like?
They should be like this for nested attributes:
def params
params.require(:form_for_variable).permit(bankaccounts_attributes: [:iban, :swift])
end
Also, you'll need to include accepts_nested_attributes_for :bankaccounts in the model you're submitting the form to

Rails form updating itself as it's filled out?

I'm trying to make a dynamic form, where the names of some forms at the bottom are based off the values of some forms at the top. For example...
At the top of the page there would be two dropdown menus. At the bottom of the page, there would be two radiobuttons. The name of the first radiobutton would have the name of the first dropdown menu choice, and the second radiobutton would have the name of the second dropdown menu choice.
This is what I have so far:
<%= simple_form_for(#game) do |f| %>
<%= f.error_notification %>
<center>
<div class="form-inputs">
<%= choices = options_for_select( Team.all.map { |team| team[:name] } ) %>
<p>Team 1:</p>
<%= f.select :first_team_name, choices %>
<p>Team 2:</p>
<%= f.select :second_team_name, choices %>
<p>Who you think will win</p>
<%= f.text_field :user_guess %>
</br>
<%= f.submit "Simulate!", class: "btn btn-large btn-primary"%>
</div>
</center>
<% end %>
The text field would be replaced by those radiobuttons instead of a text field.
How do I access the value of the dropdown menus before submitting the form?
For a more comprehensive answer, I'd recommend watching the railscasts episode on this topic, but you'd need a pro (read: paid) subscription.
Since you're not doing anything super complex, you could do it quick & dirty with some javascript:
$(function(){
$('select').change(function(){
html = ''
$('select').each(function(){
html += $(this).val() + '<input type="checkbox" name="game[user_guess]" val="' + $(this).val() +'"/>'
})
$('div.user_guess').html(html)
})
})
If you're pasting the code directly in, you'll need to add a div in your view as well:
<p>Who you think will win</p>
<div class="user_guess"></div>
Don't feel good building HTML with javascript? You can make the change() handler make an ajax call that will load server-generated HTML, which can be made with proper form helpers and such. But for such a simple task it seems like overkill.
(Also, be aware that if the team names can be user defined, this javascript may open you to script injection attacks, so sanitize as needed.)
note that if you want the form to change upon user interaction without the user actually having to submit the form before it changes (rebuilding the page and reloading the view), you have to use javascript. I think. There might be funky things you can do with CSS but that would be really obnoxious to implement.

Resources