Action form_for -> show - ruby-on-rails

URL : /evaluations
I have made a form to select a specific item (a period)
class EvaluationsController < ApplicationController
def index
#periods = Period.all
end
My form :
<% form_for XXXXX do %>
<%= collection_select(:period, :period_id, #periods, :id, :fullname) %>
<%= submit_tag("Valider") %>
<% end %>
I would like the form to go to /evaluations/3 when submited (if the selected period is 3).
When I go manually to /evaluations/3 it works like a charm but I really don't know how to write the form_for to go the right url by submitting the form.

Simple way
Submit period ID to process data, and then redirect to action, which handles
evaluations/:id with :id as parameters.
redirect_to <youraction>(:period => #id)
This should do the trick.
Not so simple way
If you want to change something dynamically on your page after data was submitted - call method and respond with javascript
respond_to do |format|
format.js
end
In javascript response you can put whatever you want - simple redirects or script, which will change page dynamically. It's up to you.
Hope it helps.

you need to use some javascript to update the action of the form
$('#period_period_id').change(function() {
$('form').attr('action', '/evaluations/' + this.value);
})

Related

Ruby on Rails - Session variable on form submit

I have an application which requires visitors to fill out a form and then it redirects to a second page. The client does not want to require visitors sign up to view this page, only to fill out the form.
The way I am attempting to do this is by creating a session variable when the page is visited and then checking to see if the variable exists before the next page is accessible. Is it possible to delay the creation of the session variable until the submit action is processed? If so what would that look like?
Also, can anyone think of a better way to do this? Sorry, this is probably a dumb question.
The session cookie would be declared after the first submit.
I presume the first submit will load up a controller#action in which you'll then redirect to the next page. Just set the session in there:
#app/views/forms/1.html.erb
<%= form_tag form_1_submit_path do %>
...
<% end %>
This will allow you to do the following:
#app/controllers/forms_controller.rb
class FormsController < ApplicationController
def form_1_submit
session[:value] = params[:value]
redirect_to form_2
end
end
Thus you'll have session[:value] all set and ready to use on the next form:
#app/views/forms/2.html.erb
<%= form_tag .... do %>
<%= text_field_tag :test, value: session[:value] %>
<% end %>

I want to use one controller and html.erb files for my dynamic table. How I will do it in Ruby On Rails?

I stored all the tablename I've created to Menu table. And every time I add the table in Menu, it will automatically create a link under Menu list
see below.
I want each table in Menu to have a Listing, New, Edit, and Delete.
see below.
I have a controller prj_menus_controller, I will just pass the id of the table from Menu table.
here is the code for index and new in my controller.
Class PrjMenusController < ApplicationController
def index
#prj_menus = Menu.find(params[:id]).tablename.singularize.classify.constantize.all
end
def new
#prj_menu = Menu.find(params[:id]).tablename.singularize.classify.constantize.new
end
def create
#prj_menu = Menu.find(params[:id]).tablename.singularize.classify.constantize.new(prj_menu_params)
if #prj_menu.save
redirect_to :action => 'index'
else
render :new
end
end
private
def prj_menu_params
params.require("HERE IS MY PROBLEM").permit(:name)
end
end
and in my
new.html.erb
<%= simple_form_for (#prj_menu),:url => prj_menus_path, :method => :post do |f| %>
<%= f.input :name %>
<%= f.submit 'Save', class: 'btn btn-primary' %>
<%= link_to "Cancel", :back, {:class=>"btn btn-default"} %>
<% end %>
I can get the list in my index.html.erb, it is working. My problem is that I don't know how to get all params when I click the submit in new.html.erb. I got this hash
{"sample1_table"=>{"name"=>"test 6"}, "commit"=>"Save","controller"=>"prj_menus", "action"=>"create"}
It is correct but I don't know what to put in my controller. I tried this params.require(["#{#prj_menu}"]).permit(:name), it creates new record but params[:name] does not save.
I am still a noob to Ruby On Rails and I don't know what to search for this.
I think you are mostly confused on what parameter whitelisting does and how parameters are passed from the form to the controller.
I does not really matter if the name of the form hash matches the name of the database table. It just does in most cases since that makes the most sense. It's simply representative of the REST interface of your app.
Let's say you have a action which creates Pets:
POST /pets
And in our form we have a bunch of inputs like so:
<input name="pet[name]">
Rails will map create a params[:pet] hash { name: 'Spot' }. But we want to save the pets as an Animal.
class PetsController < ApplicationController
def new
#pet = Animal.new()
end
def create
#pet = Animal.new(pet_params)
if #pet.save
# ...
end
def pet_params
params.require(:pet).permit(:name)
end
end
Animal does not care what the params key is, it just gets a hash. But we also need to tell simple_form what parameter key we want to use since it looks at the model_name attribute.
simple_form_for(#pet, as: :pet)
Gives us pet[name] instead of animal[name].
I don't get why you are so adamant about making things so difficult for yourself though unless you are creating a database administration tool in the vein of PHP_MyAdmin. And even that case you don't even want to be altering the schema of the app database at runtime.
You are going to run into huge problems when it comes to creating effective queries for getting all the menus.

Error while using controller to read text file

I got error when using controller to read text file:
#my_page.html.erb
<input id="test_input" >
#controller.rb
def my_page
File.open($directory+'\test.TXT', 'r') do |f1|
$line = f1.readlines
f1.close
end
respond_to do |format|
format.js
end
end
#my_page.js.erb
el = document.getElementById(test_input);
el.innerHTML='<%=$line$>';
It load blank page without input and I don't know why, Please correct me if I'm wrong.
I think I understand what you are doing. Here is what you can do.
#controller.rb
def my_page
#text= File.open('your_file.txt').read
end
#my_page.html.erb
<input id="test_input" value="<%= #text %>" />
When you refresh your page, the text should show up on your page. No need to use Javascript now. You should use it when you are requesting the resource using AJAX.
If you would like to update the value of the text box, you need to add a new action in your controller and update your routes.rb accordingly. Also, it's always a good idea to use form helpers that Rails provide to utilize security feature (CSFR token), as shown below. If you have a model for the text field, you can use a form_for helper. You can read about them in
http://guides.rubyonrails.org/form_helpers.html
Here is the code, nonetheless.
#my_page.html.erb
<%= form_tag save_text_path do %>
<%= text_field_tag :test_input, #text %>
<%= submit_tag "Update" %>
<% end %>
# in your controller
def save_text
updated_text = params[:test_input]
# do something with the text
end
# in your routes.rb
post "save_text" => "your_controller_name#save_text", as: "save_text"

How to update rails page content using AJAX when select changes?

I have a #course form that belongs_to a lesson, and each lesson has_many gradable_items. The lesson_id is selected via a drop menu. When the user changes the lesson select, the nested inputs representing each gradable_item must be updated. This is doable with a page refresh and passing the lesson_id as url param...so, that that lessons gradable_items exist as nested inputs, where they can then be graded (and saved as graded_items). But, seems AJAX is perfect for this.
The code below is not working...and I'm wondering what I'm missing.
course_lesson_id - the select menu where the lesson is chosen
"/gradable_items_input?lesson=#{el.val()}" - the url to the gradable_items_inputs.js.erb template that ajax should inject into the view where the function call was originated.
gradable_items_container - is where AJAX should inject the code returned from the template
The alert() triggers as expected, and the class is added but not removed...since I never get success.
What I am expecting to occur is this:
The select menu is changed, this triggers the function. The function grabs the id of the selected item in the lesson_id menu and then goes to the gradable_items_inputs url using the lesson_id as a url param. When this template is accessed it queries the db in the Course controller using the gradable_items_inputs action. This query uses url param for the lesson_id to filter records and populate the gradable_items_inputs.js.erb file. Then, when success...AJAX puts the code from the gradable_items_inputs template inside the div with id #gradable_items_container.
Is my thought process here flawed? I guess the answer must be yes...since it is not working.
jQuery ->
el = $("#course_lesson_id")
el.on "change", ->
$.ajax "/gradable_items_inputs?lesson=#{el.val()}",
beforeSend: ->
$("#ajax_tell").addClass "is-fetching"
success: (response) ->
$("#gradable_items_container").html(response)
complete: (response) ->
$("#ajax_tell").removeClass "is-fetching"
error: ->
$("#{ajax_tell}").html "<p>ERROR</p>"
timeout: 3000
alert "test"
The gradable_items_inputs.js.erb file:
$('#gradable_items_container').html('
<% #gradable_items.each do |gradable_item| %>
<%= f.simple_fields_for :graded_items do |graded_item| %>
<p>
<%= gradable_item.name %>
<%= graded_item.input :gradable_item_id, input_html: { value: gradable_item.id, }, as: :hidden %>
<%= graded_item.input :grade, collection: gradescales(#course), label: false %>
</p>
<% end %>
<% end %>
');
courses_controller.rb
def gradable_items_inputs
#lesson = Lesson.find(params[:lesson])
respond_to do |format|
format.js { }
end
end
Try adding
dataType:'script'
To the Ajax call params. This will ensure that the request format is js.
The best way to debug an Ajax call is to monitor it from both sides. Look at your rails server log to see how the request is received and the use your browser network inspector to see the response.
it seems you haven't created the routes for gradable_item_inputs.
check routes.rb, must have the following code:
resources :courses do
collection do
get gradable_item_inputs
end
end

collection.build of nested attribute through a remote_link does not create params when submitting form

I have the following model:
class Activity < ActiveRecord::Base
has_many :clientships, :dependent => :destroy, :after_add => :default_client_info
accepts_nested_attributes_for :clientships, :allow_destroy => true
end
In my controller, if I perform the following
def new
#activity = IndividualActivity.new(params[:activity])
#activity.clientships.build(:client => Client.first)
...
end
and then save the form, it creates the relevant params and submits successfully.
However, if I chose to call the following through a remote link
#activity.clientships.build(:client => Client.last)
the view is updated with the new clientship record but when I submit the form, the params[:activity] is not created for the second nested attribute. (Why not!?)
This is the view:
%h1 Create a new Activity
- form_for #activity do |f|
%div
= render "activities/client_selector", :f => f
%div
= f.submit "Save!"
Here is the remote_link's controller action
def add_client
#activity = IndividualActivity.new(session[:individual_activity])
# Refresh client
#activity.clientships.build(:client => Client.find(params[:client_id]))
respond_to do |format|
format.js
end
end
This is the add_client.html.js:
page.replace_html "selected_clients", :partial => 'activities/clients'
This is the activities/clients partial:
- form_for #activity do |f|
- f.fields_for :clientships do |client_f|
%tr
%td= client_f.hidden_field :client_id
%td= client_f.object.client.full_name
Does anyone know how I can troubleshoot this further? I seem to have come to a dead-end with my debugging... One thing to note, there is a double use of the following form_for used in new.html.haml and the activities/clients partial (is this problematic?)
- form_for #activity do |f|
I am on rails v2.3.5
Thanks
You ask about debugging, so the first step may be looking at the server log (log/development.log).
There you should see the "params" hash.
Maybe your params contain "activity"=>{"client_id"=>..} instead of "client_id"=>.. ?
Also look at the generated HTML page - use a Firebug or just use a "view source" method of your browser. Look, especially, for input names.
If everything looks OK, put a few debug calls in your action, and look at the development.log for some database activity - do the SQL queries look like they are doing what you want?
In your question there is no 'save' method. The 'build' method does NOT save the created record. Maybe this is your problem?
def add_client
logger.debug "Creating Activity"
#activity = IndividualActivity.new(session[:individual_activity])
logger.debug "Building clientship"
# Refresh client
#activity.clientships.build(:client => Client.find(params[:client_id]))
logger.debug "#activity = #{#activity.inspect}"
# Maybe you were missing this part of code?
logger.debug "Saving #activity"
#activity.save! # use a ! to easily see any problems with saving.
# Remove in production and add a proper if
logger.debug "Saved. #activity = #{#activity.inspect}"
respond_to do |format|
format.js
end
end
You should create a functional test (in case you haven't already) and ensure that if you send proper parameters, your action works as intended.
The test will narrow your search. If the test fails, you know you have a problem in the action. If the test is OK, you need to ensure the parameters are sent properly, and you probably have the problem in your view.
UPDATE:
You said you have TWO forms on the page. This may be the problem, since only one form may be sent at a time. Otherwise it would need to work in a way which can send two requests in one request.
First thing (useful in all similar problems): validate whether your page has correct HTML structure - for example http://validator.w3.org would be a good start. Try to make the code validate. I know that some people treat a "green" status as a unachievable mastery, but just it's really not so hard. With valid code you may be sure that the browser really understands what you mean.
Second: Place all your inputs in a single form. You have problems with nested attributes. For start, try to manually insert inputs with name like <input name="activity[clientship_attributes][0][name]" value="John"/>, and for existing clientships ensure that there is an input with name = activity[clientship_attributes][0][id].
This is the way nested attributes are handled.
Your view may create such fields automagically. This construction should be what you need: (it worked in one of my old project in rails 2.x, I have just replaced the names with ones you use)
<% form_for(#activity) do |f| %>
<p><%= f.text_field :activity_something %></p>
<% #activity.clientships.each do |clientship| %>
<% f.fields_for :clientships, clientship do |cform| %>
<p><%= cform.text_field :name %></p>
<p><%= cform.text_fiels :something %></p>
<% end %>
<% end %>
<% end %>
If you really want to use a partial there, don't create a new form in the partial. Use only the parts of above code.
To pass a variable to the partial, use :locals attribute in the place where you call render :partial:
<%= render :partial => 'clientship', :locals => {:form => f} %>
Then, in your partial, you may use a local variable form where you would use f outside of the partial. You may, of course, map the variables to the same name: :locals => {:f => f}

Resources