rails Initialize new object through associated search - ruby-on-rails

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!

Related

Rails. General advise on creating and updating a model instance

I'm a beginner at web programming. I want to make the user navigate different questions, each updating an instance of the model Item.
My plan was to create two links that create this instance, one adding the value "found" and the other the value "lost" to a "Category" parameter. I also wanted this link to redirect to an update form, which will be a search box and a submit button that will edit the parameter "Name" value.
So far, what I managed to do is in my home view:
<button type="button" class="btn btn-info mb-4 "><%= link_to "I lost something", new_item_path(category: "lost")%> </button>
Then on my Item controller,
def new
item = Item.new
item.category = params[:category]
item.user = current_user
item.save
end
This allowed me to create an instance and get the "lost" value for the :category parameter.
This is my .new view, where I was thinking of placing a search box and a submit button. Right now there is a form.
<%= simple_form_for(item) do |f| %>
<%= f.input :name %>
<%= f.submit %>
<% end %>
Now, I want to update the same instance with that form and I got completely lost. How do I make this submit button update the instance? Should I call an update action from my ItemsController with the SimpleForm? Anyone help on how to do that?
I hope my question is clear. Maybe there is a more convenient way to do this.
Any help is appreciated, with our without code
Edit: it seems using AJAX is a good way to go for what I want to do

Rails - Simple Forms - undefined method `model_name' for nil:NilClass

I am trying to make a form where you select tables that you want to export. I made a simple form with a list of tables that can be exported. My plan was to allow the user to toggle check boxes for the tables they want to export and as a result they would be able to download a zip file containing the tables.
Currently, when I try to go to the page with the form, I get an error:
undefined method 'model_name' for nil:NilClass
The majority of the usage of simple forms that I see online consists of using forms to create new items to save in their models. As a result, it seems that the line simple_form_for #example would mean that when the user clicks the submit button, there is a line in the controller such as #example = SomeClass.new". My understanding is that the user input of the form is saved in #example and can be used by the controller. However, as I am not creating a new item in the model, I just want to use the values from #example, I am not sure what to put in the controller to get rid of the error so that I can code the rest of the function in the controller.
Controller:
class FormController < ApplicationController
def index
#options = []
print(#options)
end
end
The form used:
<h2>Which tables do you want to export?</h2>
<div class="well">
<% tables_in_model = %w(Table1 Table2 Table3) %>
<%= simple_form_for #selected_options, :url => form_index_path, :method => :get do |f| %>
<%= f.input :options, as: :check_boxes, collection: tables_in_model %>
<%= f.button :submit, as: :Submit %>
<% end %>
</div>
As you said correctly in your question, simple_form should be used to render forms to the user when her actions are related to the creation or edition of ActiveRecord models.
For instance, when writing down code to enable a search feature, where your goal is to simply pass a bunch of user chosen params to a controller, you should not use it. I believe you are in a similar position with the feature you described.
Simple solution though: use rails form related DSL to get your form going!
Hope it's the answer you needed. Feel free to ask for more details if needed. Cheers!
i think you are using simple_form you need to specify like
#selected_options = SelectedOptionModel.new(params)
into your controller
then it passes into View.
if you don't have any model you can use form_tag
like this:
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
this will create html form like this:
<form accept-charset="UTF-8" action="/search" method="get">
<input name="utf8" type="hidden" value="✓" />
<label for="q">Search for:</label>
<input id="q" name="q" type="text" />
<input name="commit" type="submit" value="Search" />
</form>

Rails form using GET method regardless of what is specified

I have an HTML form intended to be used for password resetting. Its method is PATCH and it should be hitting the update method of the PasswordResetController. However, on submission, it is always make a GET request, regardless of the method specified. I can type method=ANYTHINGHERE and it always makes a GET request.
My form is simple:
<form class="group" action="<%= password_reset_url %>" method="PATCH">
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
<input type="password" class="password-login" name="new_password" placeholder="New Password">
<input type="password" class="password-login" name="new_password_verify" placeholder="New Password Confirmation">
<button class="login-button">Reset Password</button>
</form>
My routes seem to be in order:
password_reset_index POST /password_reset(.:format) password_reset#create
new_password_reset GET /password_reset/new(.:format) password_reset#new
edit_password_reset GET /password_reset/:id/edit(.:format) password_reset#edit
password_reset PATCH /password_reset/:id(.:format) password_reset#update
PUT /password_reset/:id(.:format) password_reset#update
defined as resources :password_reset, only: [:new, :create, :edit, :update]
And my controller:
class PasswordResetController < ApplicationController
new, edit, create....etc.
def update
user = ...
end
end
Create, new, and edit all work perfectly fine, but it's not even getting into the update method when submitting the form. I just get No route matches [GET] "/password_reset/longTokenString. Any ideas? I feel like I've exhausted my options here.
This is not a duplicate of this question as the token string is being properly generated. The token string is also used as the id in the /password_reset/:id/edit route, and is working fine there as well.
Thanks in advance.
According to the rails strategy here is the clear explanation if what is the difference between the PUT and PATCH methods.
If you are coming from a previous version of Rails, you may be wondering why the update action of a RESTful route is mapped to the HTTP verb PATCH instead of PUT. In the HTTP standards document RFC 57892, it outlines that a PUT request to a given resource is meant to completely replace it on the origin server. However, when updating a resource in Rails, rarely, if ever, do you replace an entire resource when performing an update. For example, when updating an Active Record model, Rails sets the attribute updated_at timestamp, not the requesting client.
To follow better HTTP semantics, Rails will be using the HTTP verb PATCH for updates. PATCH allows for both full and partial updates of a resource, and is more suited to how Rails updates resources.If you are upgrading an existing Rails application, the HTTP verb PUT will still map to the update action in
RESTful routes, but it’s recommended to use PATCH moving forward.
I am going to explain how the User Edit option works in rails.
app/controllers/users_controller.rb
def edit
#user = User.find(params[:id])
end
The corresponding user edit view
app/views/users/edit.html.erb
<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %>
Looking at the HTML source
<form accept-charset="UTF-8" action="/users/1" class="edit_user"
id="edit_user_1" method="post">
<input name="_method" type="hidden" value="patch" />
.
.
.
</form>
Note: Note here the hidden input field:
<input name="_method" type="hidden" value="patch" />
Form the Documentation:
method: (:get|:post|:patch|:put|:delete)
"In the options hash. If the verb is not GET or POST, which are natively supported by HTML forms, the form will be set to POST and a hidden input called _method will carry the intended verb for the server to interpret."
Reference: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
Hope so my explanation would be clear for understanding the concept. Happy Coding:)
According to the HTML standard, you can not add put as method for form. The only valid values for the method attribute are get and post. <form method="put"> is invalid HTML and will be treated like <form>, i.e. send a GET request.
You can also write form code by using rails form tag.
Some points to remember---
if you are making use of form_for tag,you dont have to worry about anything else because rails itself uses its Record identification to handle create(POST),new(GET) and update(UPDATE/PATCH) actions.
if you are not using form_for tag uniformly,which is your case,you must match the url exactly,So you need to pass the id too.
example:-
<form class="group" action="<%= password_reset_url(#your_model.id) %>" method="PATCH">
HOPE IT HELPS :)

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]%>

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

Resources