I have a form:
<%= form_for(:report_main, :url => {:action => 'exporttoxiccreate'}) do |f| %>
<%= collection_select(:waste, :code, Waste.find_all_by_istoxic(false), :id, :code, :include_blank => '') %>
<%= f.check_box(:q_pripadnost) %>
<%= f.text_field(:amount) %>
<% end %>
and this code in controller:
def exporttoxiccreate
#report = ReportMain.new
#reportexport = ReportExport.new
#reportparam = params[:report_main]
#report.waste_id = #reportparam.waste.code
#report.amount = #reportparam.amount
if #report.save
#reportexport.report_main_id = #report.id
else
redirect_to(:action => 'exporttoxicnew')
end
#reportexport.q_pripadnost = #reportparam.q_pripadnost
if #reportexport.save
redirect_to(:action => 'show', :id => #reportexport.id)
else
redirect_to(:action => 'exporttoxicnew')
end
end
I want to save in two tables, in two objects data from this form, and I need to separate params to manipulate with. I tried with this:
#reportexport.q_pripadnost = #reportparam.q_pripadnost
I want to set q_pripadnost field in #reportexport with some value from param.
Where I make mistake?
When you get params from a form in Rails, it comes in the form of a hash. For example:
params[:report_main][:waste]
params[:report_main][:amount]
So when you call #reportparam = params[:report_main], you are setting #reportparam to a hash, but then you are trying to use it later like an object. For example, instead of #reportparam.q_pripadnost, use #reportparam[:q_pripadnost].
You can take a closer look at your variable by temporarily changing your action to show a text version of the variable, for example:
def exporttoxiccreate
#reportparam = params[:report_main]
render :text => #reportparam.to_yaml
end
Related
I do not have much idea on jQuery/Ajax. Could someone help me to submit the forms dynamically
here is the requirement:
- I have set of tests
- Each test has a result
- Each test result stored as separate record
I am thinking of following approach:
- display each test result as a separate form and submit each one of them using AJAX
I hope there would be a better approach, please help me
here are my code:
//results controller
class ResultsController < ApplicationController
def index
#results = Result.all
#tests = Tests.all
end
def new
#result = Result.new
end
//view
#tests.each do |test|
= form_for(#result) do |r|
= r.label :test_id, test.name
= r.hidden_field :test_id, :value => test_id
= r.select :status, options_for_select(%w[UNTESTED PASS FAIL PENDING BLOCKED INVALID])
= r.submit "Submit"
The index action from controller will call index page
In index page
= #tests.each do |test|
#test.#{test.id}= render partial: "test", :locals => {test: test}
create one _test.html page In _test page do all this,
= form_for(test) do |test|
= r.label :test_id, test.name
= r.hidden_field :test_id, :value => test_id
= r.select :status, options_for_select(%w[UNTESTED PASS FAIL PENDING BLOCKED INVALID])
= r.submit "Submit"
create one index.js.html file
:plain
$("#test_#{#test.id}").html("#{escape_javascript(render(:partial => "test", :locals => { :test => #test}))}");
I've build quite complex form which creates one prescription with many realtions. I am using this syntax in view:
- provide(:title, 'Create prescription')
%h1 Add medicines to prescription
.row
.span6.offset3
= form_for #prescription do |f|
= render 'shared/error_prescription_messages'
%p
= f.hidden_field :patient_id, :value => params[:patient_id]
= f.hidden_field :user_id, :value => current_user.id
= f.fields_for :relations do |builder|
= render 'child_form', :f => builder
%p= f.submit "Submit"
chlid_form is quite simple :
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
- if params[:prescription].nil? || params[:prescription][:relations_attributes][n.to_sym][:medicine_name].nil?
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}"
- else
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}", :value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount, :value => 1
= f.label :daily
= f.number_field :daily, :value => 1
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days, :value => 1
So as you can see I'm using f.options[:child_index] to get index of child (0,1,2...) cause I generate multiple items with this particular form. I then put it to variable it and sucessfully use it in :id_element => "#my_medicine_id#{it}" which works PERFECTLY fine (creates my_medicine_id0, my_medicine_id1 ....) Although it doesn't work in this line:
:value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
where n is just n=it.to_s.
I though somethings wrong in controller but if I change this line to whatever
:value => params[:prescription][:relations_attributes]**[:'0']**[:medicine_name] or any other integer from 0 to 4 everything works great, but I NEED dynamic change in this one. So I got proof that it DOES work because it generates integer fine here "#my_medicine_id#{it}" but won't work in hash! And when I print the whole hash from params I get this:
{"patient_id"=>"7", "user_id"=>"1", "relations_attributes"=>{"0"=>{"medicine_id"=>"13490", "medicine_name"=>"Locacid 500 mcg/g (0,05%) (1 tuba 30 g)", "amount"=>"0", "daily"=>"1", "period_in_days"=>"1"}, "1"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "2"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "3"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "4"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}}}
so to get the values I need it's pretty obvious that
params[:prescription][:relations_attributes][SOME_KIND_OF_INETEGER][:medicine_name] should work, but doesn't.
Controller code:
class PrescriptionsController < ApplicationController
before_action :signed_in_user
before_action :doctor_user, only: [:new, :create]
before_action :pharmacist_user, only: [:update]
def new
#prescription =Prescription.new
5.times { #prescription.relations.build }
end
def create
#prescription = Prescription.new(new_prescription_params)
if #prescription.save
flash[:success] = "Prescription created."
redirect_to #prescription
else
5.times { #prescription.relations.build }
render 'new', :prescription => params[:prescription]
end
end
def show
#prescription = Prescription.find(params[:id])
#medicines = #prescription.medicines.paginate(page: params[:page], :per_page => 10)
end
def update
#prescription = Prescription.find(params[:id])
#patient = Patient.find(params[:patient_id])
if !prescription_expired?(#prescription)
#prescription.realized = 1
if #prescription.save
flash[:success] = "Prescription realized."
redirect_to #patient
else
redirect_to root_url
end
else
flash[:notice] = "Can't realize, prescription expired."
redirect_to #patient
end
end
private
def new_prescription_params
params.require(:prescription).
permit(:patient_id, :user_id, relations_attributes: [:medicine_id, :medicine_name, :amount, :daily, :period_in_days])
end
def doctor_user
redirect_to(root_url) unless current_user.function == "doctor"
end
def pharmacist_user
redirect_to(root_url) unless current_user.function == "pharmacist"
end
def prescription_expired?(presc)
presc.created_at < 1.month.ago
end
def signed_in_user
unless signed_in?
store_location
flash[:notice] = "Please log in."
redirect_to login_url
end
end
end
I run out of ideas so I ask you guys if anyone can help. Thanks.
There is no point in using params in your view since you already assigned those to your models. Also when you rendering your new action, those params doesn't exist as nothing has been send to the server yet. Just get rid of all the values from inputs.
Your partial should look like:
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount
= f.label :daily
= f.number_field :daily
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days
If you want your fields to have default value, set default value inside your database.
I have a model in which I have a boolean attribute, published. In my Post controller I have added it to my permitted attributes. Like this:
params.require(:post).permit([...], :published)
My index action that should list all published posts looks like this:
def index
if session[:user_id]
#posts = Post.paginate(:page => params[:page])
else
#posts = Post.where("published = 1").paginate(:page => params[:page])
end
end
And lastly my form looks like this:
= form_for #post, :html => { :multipart => true } do |f|
[...]
.field
= f.label :published, "Publicera:"
= f.check_box :published
.actions
= f.submit
Currently no posts is listen on my index page, even if I either the new or updat view checks the checkbox. And I'm not sure how to fix it, any ideas?
The problem seems be be with my where predicate. This worked:
#posts = Post.where(:published => true).paginate(:page => params[:page])
UPDATE
I have mange to get it working by changing the Model call from
#comments = VideoComment.all(:conditions => { :video_id => #video.id}, :limit => 5, :order => :created_at)
#comments = VideoComment.last(5).reverse
It works, but it gives me the last video comments from all the videos whereas I only want those from the current video (#video.id).
Any clue on how to do that?
I have a Videocontroller and a VideoComments controller which manages the comments for the Video controller. I am trying to make my remote form update the comments list with ajax but it does not seem to work. Can you find what I did wrong?
HTML code of the show page :
- if current_user
#comment-form
= render 'video_comments/comment_form'
%ul
#comments
= render #comments
video_comments/_comment_form.html.haml
= form_for current_user.video_comments.build(:video_id => params[:id]), :remote => true do |f|
.form-fields
.comment-content
= f.text_area :content, rows:2
= f.hidden_field :video_id
= f.hidden_field :user_id
.submit-form
= f.submit "Add a comment", :class => "btn btn-default "
The Video_Commentscontroller createaction :
def create
#comment = VideoComment.create(params[:video_comment])
#video = #comment.video
#comments = VideoComment.all(:conditions => { :video_id => #video.id}, :limit => 5, :order => :created_at)
render :toggle
end
The toggle.js.erb file which manages the page changes :
$("#comment-form").html("<%= escape_javascript render 'comment_form' %>");
$("#comments").html("<%= escape_javascript render #comments %>");
If you are using Rails 3 you can do
#comments = VideoComment.where(:video_id => #video.id).order(:created_at).limit(5)
Or if you have relations properly defined you can also do
#comments = #video.comments.order(:created_at).limit(5)
I have form that create two objects and save them to database.
I want to do next things:
save data in database (booth objects)
validate fields (I have validation in model)
and if validation fail, I want to populate fields with entered data
edit action for this form
Problems:
If I use #report I get:
Called id for nil, which would
mistakenly be 4 error
(can't find object). I have in controller, in encreate action #report = ReportMain.new and in action that render that view.
When I use :report_main (model name) it works, it save data to database, but I can't get fields populated when validation fails.
Questions:
What to do with this two models to make this to work (validation, populating fields, edit)?
Can you give me some advice if approach is wrong?
My view looks like this:
<%= form_for(#report, :url => {:action => 'encreate'}) do |f| %>
<%= render "shared/error_messages", :target => #report %>
<%= f.text_field(:amount) %>
<% fields_for #reporte do |r| %>
<%= r.check_box(:q_pripadnost) %>Pripadnost Q listi
<%= select_tag('nacinpakovanja',options_for_select([['Drveno bure', 'Drveno bure'], ['Kanister', 'Kanister'], ['Sanduk', 'Sanduk'], ['Kese', 'Kese'], ['Posude pod pritiskom', 'Posude pod pritiskom'], ['Kompozitno pakovanje', 'Kompozitno pakovanje'], ['Rasuto', 'Rasuto'], ['Ostalo', 'Ostalo']])) %>
<%= r.text_field(:ispitivanjebroj) %>
<%= r.text_field(:datumispitivanja) %>
<% end %>
<input id="datenow" name="datenow" size="30" type="text" value="<%= #date %>">
<div class="form-buttons">
<%= submit_tag("Unesi izvestaj") %>
</div>
<% end %>
encreate actin in ReportController:
def encreate
#report = ReportMain.new
#reporte = ReportE.new
#reportparam = params[:report_main]
#report.waste_id = params[:waste][:code]
#report.warehouse_id = Warehouse.find_by_user_id(current_user.id).id
#report.user_id = current_user.id
#report.company_id = current_user.company_id
#report.amount = #reportparam[:amount]
#report.isimport = false
#report.isfinished = false
#report.reportnumber = ReportMain.where(:company_id => current_user.company_id, :isimport => false).count.to_i+1
if #report.save
#reporte.report_main_id = #report.id
else
redirect_to(:action => 'exportnew')
return
end
#reporte.vrstaotpada = params[:vrstaotpada]
#reporte.nacinpakovanja = params[:nacinpakovanja]
#reporte.ispitivanjebroj = #reportparam[:ispitivanjebroj]
#reporte.datumispitivanja = #reportparam[:datumispitivanja]
#reporte.q_pripadnost = #reportparam[:q_pripadnost]
#reporte.datumpredaje = #date
if #reporte.save
redirect_to(:action => 'show', :id => #reporte.id)
else
redirect_to(:action => 'exportnew')
end
end
I think your problem in this case is that you use redirect_to instead of render. When you use redirect_to then you lose all the variables from your current action. I would probably do something like this in your encreate action:
if #reporte.save
render :show
else
render :exportnew
end
When you use render then it will use the variables from the current action but the view from the action you send to the render method. So when form_for is called with the #report variable, it is already populated with the values that was sent to encreate. Just make sure that you use the same variable names in the different actions but it looks like you do that already.