Nested child modification - ruby-on-rails

I'm working on this dynamic form to create multiple nested child form, just like in ryan bates railscast, but i want to specify the amount of nested child before input:
Here's the for controller in ryan's railscast :
def new
#invoice = Invoice.new
5.times { #invoice.items.build }
end
So i'm wondering if i can change nested child to dynamicly multiply based from an input form:
I've tried this code below, but it didn't work:
def new
count = params[:item_counts] ---> the value from a text_field_tag
count.times { #invoice.items.build }
end
Here's the view:
<div id="invoice">
<%= form_tag invoices_path, :method => "get" do %>
<%= label_tag :items, "Item amounts :" %><%= text_field_tag :item_counts %><br /><br />
<%= link_to 'Create New Invoice', new_invoice_path(invoice) %>
<% end %>
</div>
How to pass the value from :item_counts in the text_field_tag to the controller?

What do you mean by passing the value to the controller ? If you submit the form, all your params ( including params[:item_counts] ) will be passed to invoices#create, i.e. create action of invoices controller.
What exactly is the params passed to the posted new method ?

Related

Rails 5 simple search form just won't work

I have a navbar shared across all views by rendering it in application.html.erb with this form in it:
<form class="form-inline d-none d-lg-inline-flex">
<%= form_tag search_query_path, method: :get do |f| %>
<%= text_field_tag :query, params[:query], class: "form-control", placeholder: "Search" %>
<%= submit_tag "Search", name: nil %>
<% end %>
</form>
I want to search for similar titles in the Post model.
The methods are in the PostsController as follows:
def search_query
#results = Post.find_by_sql("SELECT * FROM posts WHERE title LIKE '%#{params[:query]}%'")
end
def search_query_params
params.require(:post).permit(:query)
end
private :search_query_params
The problem is: the search keeps getting processed by the current controller of the current view. If I'm the the index page (in the PagesController), the query takes place there, just reloading the url like this:
http://localhost:3000/?utf8=%E2%9C%93&query=test+title
I've tried everything and can't find where my logic is wrong.
These are the routes:
get '/search_query', to: 'posts#search_query', as: 'search_query'
form_tag generates a form element, so you are nesting a form inside a form here. Try deleting the outer form.

custom action submitting multiple forms in Rails

So I have this structure of application: a Game model which has many Allies and many Enemies.
I want to create a custom action for Game dedicated to create and submit enemies and allies.
So in the view I will have 2 fields_for that you can submit at the same time.
I have never created custom routes and actions or submitted 2 children forms in the same page.
Anyone know how I could do this ? Thanks
routes.rb
#this route shows the form
get 'create-players/:id', to 'game#new_players', as: :new_players
# this route recieves the form post submission
post 'create-players/:id', to 'game#create_players', as: :create_players
app/controllers/game_controller.rb:
def new_players
#game = Game.find(params[:id])
end
def create_players
#do whatever you want with the params passed from the form like
#allies = Ally.create(game_id: params[:id], name: params[:ally_fields][:name])
#enemies = Enemy.create(game_id: params[:id], name: params[:enemy_fields][:name])
#game = Game.find(params[:id])
end
app/views/game/new_players.html.erb:
<%= form_tag(create_players_paths, #game.id), method: 'POST') do %>
<% #...fields you have on models, perhaps %>
<% fields_for :ally_fields do |f|
<%= f.text_field :name, nil, placeholder: "Ally name", required: true
<% end % >
<% fields_for :enemy_fields do |f|
<%= f.text_field :name, nil, placeholder: "Enemy name", required: true
<% end % >
<%= submit_tag "create players", class: "submit" %>
<% end %>
app/views/game/create_players.html.erb:
<h1> Woah an allie and an enemy have been added to game <%= #game.id %></h1>
<p> Lets see some blood!</p>
Of course, you should enforce verifications on the input and before processing the post submission. Usually you'll want to use established relationships between objects, so that you can do on the view #model = Modelname.new then, form_for #object and have validations and error messages accessible in a much cleaner way.

Rails multi-record form only saves parameters for last record

I'm trying to offer teachers a form that will create multiple students at once. It seems that most people tackle this concept with nested attributes, but I'm having a hard time understanding how that would work when I'm only using a single model. This article made it seem possible to achieve this without nested attributes, but my results are not working the way the author suggests. The students array should include one hash for each section of the form. But when I submit the form and check the parameters, only one single hash exists in the array.
Adjusting her approach, I've got this controller:
students_controller.rb
def multi
#student_group = []
5.times do
#student_group << Student.new
end
end
(I'm using an action I've called "multi" because it's a different view than the regular "create" action, which only creates one student at a time. I've tried moving everything into the regular create action, but I get the same results.)
The view:
multi.html.erb
<%= form_tag students_path do %>
<% #student_group.each do |student| %>
<%= fields_for 'students[]', student do |s| %>
<div class="field">
<%= s.label :first_name %><br>
<%= s.text_field :first_name %>
</div>
<div class="field">
<%= s.label :last_name %><br>
<%= s.text_field :last_name %>
</div>
<% end %>
<% end %>
<div class="actions">
<%= submit_tag %>
</div>
<% end %>
The results:
(byebug) params
<ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"3Xpi4XeqXuPs9jQvevy+nvGB1HiProddZzWq6Ed7Oljr3TR2fhx9Js6fN/F9xYcpgfDckCBOC2CoN+MrlFU0Bg==", "students"=>{"first_name"=>"fff", "last_name"=>"ggg"}, "commit"=>"Save changes", "controller"=>"students", "action"=>"create"} permitted: false>
Only one has is included for a student named "fff ggg". There should be four other hashes with different students.
Thank you in advance for any insight.
fields_for is only used in conjunction with form_for. The for is referring to a model, which it expects you to use. Since you're trying to build a form with no model, you have to construct your own input field names.
Don't use fields_for but instead, render each input using the form tag helpers e.g.
<%= label_tag "students__first_name", "First Name" %>
<%= text_field_tag "students[][first_name]" %>
...and so on.
The key is that the field names have that [] in them to indicate that the students parameters will be an array of hashes. You almost got it by telling fields_for to be called students[] but fields_for ignored it because it needs a model to work correctly.

Rails form_tag not displaying the existing field value

I've a settings controller setup like this:
class Admin::SettingsController < ApplicationController
def index
#settings = Setting.all
end
def update
setting_params.each do |key, value|
Setting.where(key: key).first.update_attribute :value, value
end
redirect_to admin_settings_path, notice: "Settings saved."
end
private
def setting_params
params.require(:settings).permit(:site_title, :site_desc)
end
end
The index action has a view file in relevant path, its code is as follows:
<h1>Settings</h1>
<%= form_tag admin_settings_path, method: "put" do %>
<p>
<label>Site Title:</label>
<%= text_field_tag "settings[site_title]" %>
</p>
<p>
<label>Site Description:</label>
<%= text_field_tag "settings[site_desc]" %>
</p>
<p>
<%= submit_tag "Save settings" %>
</p>
<% end %>
Now, I'm able to save/update these fields data in relevant model and I can see the data through command Setting.all in rails console. But the issue is, after saving the record via form when I reload the settings index page the form is blank and it is not showing previously saved values in the fields.
What I'm doing wrong here?
You can do what has been mentioned in the previous answer i.e. using a form_for. However, this can also be accomplished by creating a Hash in both the controller actions that creates and processes this form.
In the action that creates this form, the values in the hash could be initialized to blanks/zeros depending upon the input tag and in the action that processes this form, the values in the hash could be assigned to the values obtained from the posted params[].
I ran into the similar issue with form_tag and I used the following code in my index action i.e. the action that renders the form initially:
#search = {name: "", ranking_group: 0}
Whereas, in the search action, I used the following code to fill up this hash:
#search = {name: params[:name], ranking_group: params[:ranking_group]}
Finally, in the view, I used the appropriate default value options with the input tags as below:
<%= text_field_tag :name, #search[:name] %>
<%= select_tag :ranking_group, options_for_select(AmenityEntities::Amenity.ranking_group_options, #search[:ranking_group]), include_blank: true %>
Hope this helps.
I think you need to use form_for(#variable) instead of just a form_tag because you need to persiste the object after save.
form_for works with resources, take a look here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html

Is there any way for the controler to get values from a form in your view before it is saved?

I assume the values must be passed back to the controller for use, but everything I have tried seems to only get values that have already saved in the db.
When a form is submitted, the controller will always have access to a hash called "params", which will contain all of the submitted data.
For example, if your form contains a textbox with a name "foo"
<input type="text" name="foo" />
the value can be retrieved in the controller using
fooValue = params[:foo]
You can use this to build a new instance of a model, containing the submitted values from the form as follows:
in your form:
<% form_for :person, #person, :url => { :action => "create" } do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= submit_tag 'Create' %>
<% end %>
then, in your controller:
#newPerson = Person.new(params[:person]; #this will pass the whole group of values within that person form to the "new" method

Resources