Rails 5 - use collection_radio_buttons to open a partial with nested models? - radio-button

(my first SO question, so please be kind!)
Each Schedule has only one System;
Each System has many Applications;
Each Application has many Users and Documents.
What I want to do to create a Schedule entry:
Generate a form that first shows multiple System names that can be clicked. When a System is clicked, it opens a partial that lists Applications associated with that System. Then, when clicking particular Applications, yet another partial opens that contains Users and Documents associated with that particular Application.
When editing this entry later, I want to be able to see everything I had entered before, with the correct System, Application(s), User(s), and Document(s) already pre-selected.
My question here is how to make a form element for choosing a System that will open another partial -- and, later, will be pre-selected when I view and/or edit the entry.
What kinda works right now is a <%= link_to %>, styled with Bootstrap, which opens its associated Applications partial when it's clicked. However, I'm not able to save the System from it, and I can't figure out whether it can display as already-selected later, such as in an Edit form.
We're trying to use radio buttons instead (because you can't pre-select a link_to, right?), so I've been throwing pasta at the wall with f.collection_radio_buttons, or iterating over f.radio_button, or a tag of <input type="radio">. However, I can't figure out how to make a radio button open a partial.
Since first posting this question, I've narrowed down to using f.radio_button within a loop. It shows as correctly "checked" when viewed while Editing the entry later, but it still doesn't open the partial.
Here's a snippet from /_schedule_form.html.erb:
<%= form_for #schedule do |f| %>
<% System.all.each do |a| %>
<!-- This link_to makes the Applications partial appear, but that's all it does -->
<%= link_to a.system_nm, system_applications_path(:system_id => a.id,
:schedule_id => params['id']), :title => 'Click to choose system',
:class -> 'btn btn-default btn-flat active', data: {:remote => true,
'data-target' => '#applicationList'} %>
</a> <!-- closes the link_to tag, I believe -->
<% end %>
<div id="applicationList">
<!-- the Applications partial renders here -->
</div>
<% end %>
Here's the system_applications.js.erb file that opens the _system_applications.html.erb partial:
$("#applicationList").html("<%= escape_javascript(render
'system_applications', locals: {applications: #applications,
schedule_applications_array: #schedule_applications_array})%>");
Here's an update with possible clue:
I'm now using this embedded Ruby code:
<% System.all.each do |rt| %>
<label>
<%= f.radio_button :system_id, rt.id, data:{:remote => true, 'data-target' =>
'#applicationList'}, href: system_applications_path(:system_id => rt.id,
:schedule_id => params['id']), class: 'remote-input', onclick:
"#applicationsList" %>
</label>
<% end %>
And, when I click on that radio button, I'm getting a JS error in the browser console Uncaught SyntaxError: Invalid or Unexpected Token which points to the rendered HTML, and specifically the > at the end of the line:
<input data-remote="true" data-data-target="#applicationList" href="/schedules/system_applications/24?schedule_id=122" class="remote-input" onclick="#applicationList" type="radio" value="24" checked="checked" name="schedule[system_id]" id="schedule_system_id_24" />
Just to make it more complicated:
When creating a NEW entry, and when I hover over one of the link_to buttons, I get a clean-looking path like /schedules/system_applications/24, and that's what gets sent to the server when clicked (which then reads the params as {"system_id"=>"24"}. But hovering over the f.radio_button labels shows no path, and clicking it sends "/schedules/new?schedule%5Bsystem_id%5D=24" with the params {"schedule"=>{"system_id"=>"24"}}. This triggers a 500 (Internal Server Error) (which makes sense, because there's no path for that URL). Do the params need to be the same? If so, how am I screwing it up?
Also, clicking the radio button sends the request to SchedulesController#new, while clicking the link_to sends it to SchedulesController#system_applications. I don't understand how I'm telling the radio button to send it to #new.
Where I'm stuck now is, the f.radio_button renders as "checked", which is correct; but it doesn't open the partial. The link_to version opens the partial, but I don't think it can render as "checked" later on.
Let me know if I'm asking clearly enough, too.

I think we made it work. One key change was to use url instead of href to use the system_applications_path to the controller, as shown here:
<% #systems.each do |a|
<label class="btn btn-sm btn-default">
<%= f.radio_button :system_id, a.id, :data => {url:system_applications_path(:system_id
=> a.id, :schedule_id => params['id']), 'data-target' => '#applicationList'+a.id.to_s,
:remote => true} %>
<%= a.system_nm %>
</label>
<% end %>
Now, when I click the radio button, it opens the correct partial, and it shows as selected later when I go to edit the entry. The Bootstrap styling (btn btn-sm btn-default) helps to show how much clickable area there is, but it's not required for basic functionality.
I suppose some of that [in]famous Rails Magic has radio_buttons treating href: differently than url. But it's "magic" only because I don't understand it (yet -- growth mindset!). What's the explanation behind it?

Related

simple_form error messages do not go away

I'm using simple_form with twitter bootstrap on Rails.
Everything works great, except when showing live validations in a form-inline class. My code for the form is:
<%= simple_form_for #message,
url: mailing_list_path,
html: { class: "form-inline" },
method: :post,
validate: true do |f| %>
<%= f.input_field :email_address, label: false %>
<%= f.submit "Submit" %>
<% end %>
This shows the error message properly (e.g. "is invalid"), but if I click off the input and then back on again, it adds another message (e.g. it would say "is invalid is invalid"). For example, two sequential invalid entries and then a blank entry would give:
Is there any way to have simple_form remove the existing error message before adding a new one?
EDIT:
I solved this using some ghetto js, but would still like to know if the functionality I mentioned above is built in. The divs are still there, they're just hidden instead of all showing together. Would be great to have them actually removed by the form validation...
$('input.email-address-input').on 'keyup', () ->
$(this).parent('form').siblings('.help-inline').hide()

How do I update a list of partials rendered with a collection after a form submission of a newly created object in ruby on rails

This is a portion of my groups view. I have a list of partials that I render with a collection of objects:
<div id="container">
<ul>
<li id="form"></li>
<li id="partials">
<%= render :partial => 'groups/partial-list-row', :collection => #allpartials, :as => :f %>
</li>
</ul>
</div>
In the list item with id "form" there is a ruby on rails form that is a form_for #newpartial which is defined in the Partial controller as #newpartial = Partial.new(). I have successfully used jquery to toggle the show and hide of the two list items on a "New Partial" button click, and upon completing a finished form, a new partial object is definitely created. What I'm looking for here is the collection of partials that reappears after the form submission includes the newly created partial object. What is the best way to do this? My form which sits inside the list item with id "form" looks like this:
<%= form_for #newpartial, :html => {:multipart => true, :class => 'custom'}, remote: true do |f| %>
<% if #newpartial.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#newpartial.errors.count, 'error') %> prohibited this partial from being saved:</h2>
<ul>
<% #newpartial.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= render :partial => 'partials/form-partial', :locals => { :f => f } %>
<div class="actions">
<%= f.submit 'Launch', :class => 'large success button radius new_browser_tab' %>
<a class="cancel_campaign_new">Cancel</a>
</div>
<% end %>
I also have successfully created a function that is bounded to the "ajax:success" event of this form after the DOM is fully loaded. I just don't know if this is a right approach, and if it is, I don't know what the body of this event handler should consist of. I have created other questions relating to this same issue (I haven't found a solution to this for quite some time now). Here are the questions if you want additional context:
SO question 1
SO question 2
What I was failing to realize is that applying the remote: true on the form indicates that the controller's action method will respond with the models "action".js.erb file. After creating that file and performing the jquery I had always intended, I was able to fix a few kinks and got that part working.
The difference between putting the jquery to render the new partial in your client side javascript and your "action".js.erb file is that the "action".js.erb file is able to make the required request to the server, whereas your client side javascript is not.
Can someone read this and let me know if the above statements are accurate? I'd really like to provide an answer that is accurate as possible for anyone that comes across this...
There are some really good tutorials at CodeSchool.com which has some free courses to take that include video lectures, slides, and exercises that I used to finally give me enough guidance on this. Also worth mentioning that if you intend to learn this stuff quickly and plan on spending a lot of time developing your web development abilities, paying the 20 dollars a month for access to all the courses is well worth it (you can cancel at any time, so learn what you need to learn and move on!).

Active Admin Search/Filter widget on Custom Page

I want to have a search widget/filter feature on a custom page using active admin to provide a look-up feature. Using the action_items I have my own action and form that renders the search page. On the search page the 'filters' that I need to show include text fields of the 'Parent' resource and a drop down list of the Parent's Parent. The association is as follows
Class MyChildResource
belongs_to :myParentResource
Class MyParentResource
attr_accessible :name, :close_to_place, :date
has_many :myChildResources
belongs_to :myGrandParentResource
class MyGrandParentResource
has_many :myParentResources
In the active admin Resource
ActiveAdmin.register MyChildResource do
action_item :only=>:index do
link_to("Look Up Availability", search_admin_myChildResources_path)
end
collection_action :search do
# do something here similar to the 'filter' feature like filter on myparentresource.date as date
filter on myGrandParentResource as drop down
filter on myParentResource.close_to_place as string
end
end
Do I have to write my own custom meta_search features? I would be fine even if I have to write own search queries, based on the input that the user gives, but my problem is that how do I display the drop down values from the parent's parent model and/or leverage the power of active admin filters.
I read something similar in this question,How to add a filter to Active Admin dashboard? , but it's a hack and it definitely does not answer the question of displaying a list
I haven't found any DRY way of doing this, so I've ended up creating my own search form which uses the active admin css for the 'sidebar' and 'panel' as mentioned in the link above and for each element of drop down, text field , date and buttons. So I get a widget which looks like the sidebar.
For the search result, I am running my own queries and searching based on the user input.
The Search Form looks like this:
Search For <br>
<div id="search_filter_partial" class="panel_contents">
<%= form_tag(search_path,:remote=>true,:class=>"filter_form", :name=>"search_filters") do %>
<div class="filter_form_field filter_string">
<%= label_tag(:author, "Author",:class=>" label") %>
<%= text_field_tag (:author) %>
</div>
<div class="filter_form_field filter_select">
<%= label_tag(:book, "Book",:class=>" label") %>
<%= select("book","book_id", #books.map {|u| [u.name,u.id]}) %>
</div>
<div class="filter_form_field filter_string">
<%= label_tag(:published_date, "Published Date",:class=>"label")%>
<%= date_select :book,:published_date %>
</div>
<div class="buttons">
<%= submit_tag('Find It', :onclick => "validateForm();") %>
<a class="clear_filters_btn" href="#">Clear</a>
<input id="order" type="hidden" value="id_desc" name="order">
<input id="scope" type="hidden" name="scope">
</div>
<%end%></div>
Doesn't look too good, but that's the best I have been able to come up with since I want to stay consistent with the look and feel of Active Admin

Rendered partial not receiving params

I'm trying to implement an 'edit' link that brings up a form to change a displayed attribute on a page.
My layout has:
<div id="company_info">
<%= yield :company_info %>
</div>
<div id="edit_company_info">
</div>
My view has:
<%= content_for :company_info do %>
<%= render 'company_info' %>
<%= link_to "Edit", 'company_info_form', :class => 'btn btn-mini', :method => :get, :remote => true %>
My controller has:
def company_info_form
#company = Company.get(params[:id])
respond_to do |format|
format.js
end
end
My company_info_form.js.erb file has:
$('#edit_company_info').html("<%= escape_javascript(render "company_info_form") %>");
Upon clicking the link, my server shows:
Started GET "/companies/company_info_form" for 127.0.0.1 at 2012-03-12 20:19:13 -0700
Processing by CompaniesController#show as JS
Parameters: {"id"=>"company_info_form"}
Completed 500 Internal Server Error in 1ms
RuntimeError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id):
app/controllers/companies_controller.rb:9:in `show'
So I think this is a routing issue-- but I have no idea how to fix it. How do I get the company_id param that is on my current page to be recognized by the partial I'm loading as well?
I'm on /companies/1, but the link is to companies/company_info_form, losing the "company_id = 1" param.
Yes, the issue is with your routes and with your link as you have pointed out.
The first issue can be ascertained as it says Processing by CompaniesController#show as JS. So, its actually going to companies#show where it tries to find a company based on id. But, since no correct id is passed, it errors out.
The second issue is because your link is to companies/company_info_form, as you pointed out, since you have used 'company_info_form' as the path in your link for edit. And you haven't passed current company to the link either.
Since you haven't posted your routes file, which you should have, since you have identified a potential problem with routes , I'll present my own.
In your routes :
resources :companies do
member do
get 'company_info_form'
end
end
That will provide you with
company_info_form_company GET /companies/:id/company_info_form(.:format) companies#company_info_form
Then you can provide the link as :
<%= link_to "Edit", company_info_form_company_path(#company) %>

Cucumber click only working when #javascript is used?

I know there's a simple fix for this but for the life of me I can't remember what it is.
My feature file is as following:
Scenario: Editing locations
When I edit "Western Australia"
And fill in "Name" with "Tasmania"
And I press "Save"
Then I should see a form success message
And I've defined the 'Edit' step as the following:
When /^I edit "([^"]*)"$/ do |name|
within(:xpath, "//tr[./td[contains(text(), '#{name}')]]") do
find(:css, "a img[alt=Edit]").click
end
end
The HTML for the index page it works on is as follows:
<tr>
<td>Western Australia</td>
<td>WA</td>
<td>
<img alt="Edit" src="/images/icons/pencil.png" title="Edit" />
</td>
</tr>
And then the form HTML:
<%= semantic_form_for [:admin, #location] do |f| %>
<%= f.inputs do %>
<%= f.input :name %>
<%= f.input :abbreviation %>
<% end %>
<%= f.submit "Save" %></li>
<% end %>
As it is, it doesn't work - I get the following error:
And fill in "Name" with "Tasmania" # features/step_definitions/web_steps.rb:39
cannot fill in, no text field, text area or password field with id, name, or label 'Name' found (Capybara::ElementNotFound)
But the form element 'name' is clearly there on the page.
If I add 'Then show me the page' before the 'Fill in' then capybara saves the index page, leading me to think it isn't getting to the edit form at all.
... Yet if I add the '#javascript' tag to the feature, it works perfectly, even though there is no Javascript on this page.
I've solved this once before, but for the life of me I can't work out how...
Well I managed to solve the problem - the issue was with my CSS selector that was clicking the 'Edit' link. I don't know why it didn't work as-was, but I changed the find(:css, "a img[alt=Edit]").click to read click_link('Edit') and it worked perfectly.
Source: http://groups.google.com/group/ruby-capybara/browse_thread/thread/9c997395306d40e2/
For starters, you need to actually "visit" the edit page using the Capybara visit method within your When block. Also, I don't believe you want to use fill_in for inserting text into your tags (at least according to the error message it is only for text fields/areas).