Ajax in RoR - observe_field

Hey, I’m trying to achieve something relatively simple and missing
something that is probably very simple, which I’m loosing my head over.
My situation is the following: I have two tables:
-education_plans
-students
Each student has_one ed_plan and each ed_plan belongs to one student.
What I’m trying to achieve is on the form when new ed_plan is created, I
want to have a text box where I can enter st_id(not primary key of the
students table, my own id created for each student). Then the call is
made to the get_student_info method where student info is pulled and
associated with the education plan. This is where the problem is because
I render text or template from get_student_info method fine, but how do
I at the same time associate returned info about the student with
ed_plan.
I’ve tried number of various combinations and I just can’t get it to
work. I’m really hoping you guys can help me out.
So my new view on ed_plans looks like this:
<% form_for(@education_plan) do |f| %>
<%= f.error_messages %>

  <td><%=text_field_tag :st_id %></td>

<%= observe_field(:st_id, :frequency => 0.25, :update =>

:student_id,
:url =>{:action => :get_student_info}, :with =>
‘st_id’) %>

Student name Student ID Grade
<%= f.label :comments %> <%= f.text_area(:comments, :cols => 30, :rows => 4) %>
<%= f.label :service_code %> <%= f.text_field(:service_code, :size =>3) %>
<%= f.label :school_number %> <%= f.text_field(:school_number, :size =>3) %>
<%= f.submit 'Create'%>

the get_student_info methods looks like this:
def get_student_info
@student = Student.find_by_osis(params[:osis])

@education_plan.student_id = @student

   return @student

end

Also, one thing I couldn’t get that if I uncomment the line #
@education_plan.student_id = @student I get error method not available
for nil object, which is very weird because that method is in the
EducationPlan controller.
THanks for you help…

On Sat, Oct 24, 2009 at 7:09 PM, Misiek Sz
[email protected] wrote:

made to the get_student_info method where student info is pulled and

<%= observe_field(:st_id, :frequency => 0.25, :update => <%= f.label :service_code %>

EducationPlan controller.
The error message says that you’re calling a method on a nil object.
If you uncomment that line, you will be calling the student_id method
on @education_plan instance, but @education_plan is nil there.


Leonardo M…
There’s no place like ~

Leonardo M. wrote:

On Sat, Oct 24, 2009 at 7:09 PM, Misiek Sz
[email protected] wrote:

made to the get_student_info method where student info is pulled and
�
� �<%= observe_field(:st_id, :frequency => 0.25, :update =>
� �<%= f.label :service_code %>

EducationPlan controller.
The error message says that you’re calling a method on a nil object.
If you uncomment that line, you will be calling the student_id method
on @education_plan instance, but @education_plan is nil there.


Leonardo M…
There’s no place like ~

Thanks. Why is it nil if the method is part of the controller?

And also how can I create an association between education_plan and
student based on the ajax call from education_plan?

Misiek Sz wrote:
[…]

Thanks. Why is it nil if the method is part of the controller?

Because you haven’t assigned a value to @education_plan ! This doesn’t
happen automatically.
Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Sun, Oct 25, 2009 at 2:11 PM, Misiek Sz
[email protected] wrote:

The error message says that you’re calling a method on a nil object.
If you uncomment that line, you will be calling the student_id method
on @education_plan instance, but @education_plan is nil there.


Leonardo M…
There’s no place like ~

Thanks. Why is it nil if the method is part of the controller?
Which method is part of the controller? you are referencing an
instance variable (@education_plan) which is not defined yet.
The method in question, here, is student_id which is from the model
(EducationPlan) but the object where you’re trying to call this method
from is not of a EducationPlan instance, it is not even an instance,
it is nil, and that’s why you get that error.

And also how can I create an association between education_plan and
student based on the ajax call from education_plan?

I really don’t understand how you want to do the association here. The
AJAX call behaves exactly as any other calls in the terms of the
controller.
If a Student has one EducationPlan, and you have:
@student = Student.find(whatever)
you should be able to do:
@student.education_plan
and
@student.education_plan=

So, if you’re retrieving the student from the database, you’ll get the
associated education plan.

It looks like you have a misconception of the ActiveRecord
associations, have you read the guide[1] for this? maybe it can help
you to get it right.

[1]Active Record Associations — Ruby on Rails Guides

Hope it helps.-

Leonardo M…
There’s no place like ~

THank you for helping me out. So, I went through association guide, but
still I can’t get it to work. My concept is this.
Display a form to create a new EducationPLan. On the form have a text
box and when the value is entered it doesn’t create an association yet,
but returns student record(if found), which then is saved together with
the form.
Is this concept correct?
I can render student info on the education_plan form fine, but is
possible to have that information handled and have that 1-1 relationship
saved when the form is submitted?

On Sun, Oct 25, 2009 at 2:33 PM, Marnen Laibow-Koser
[email protected] wrote:

Misiek Sz wrote:
[…]

Thanks. Why is it nil if the method is part of the controller?

Because you haven’t assigned a value to @education_plan ! This doesn’t
happen automatically.
Yes, this looks like another concept error on instance variables from
Misiek

Leonardo M…
There’s no place like ~

On Sun, Oct 25, 2009 at 3:23 PM, Misiek Sz
[email protected] wrote:

saved when the form is submitted?
OK, now the situation is clearer for me. There’s something you’re not
getting from associations, let’s see if with the example you get it
more clear.
If you want to create the association when you create the education
plan, why would you try to get it on the get_info action and not on
the create action?
When you get (render) the student info on the create form for
education plan, you should keep the student id and send it with the
rest of the education plan parameters as the
education_plan[student_id].
Then, in the create action, you can do
EducationPlan.new(params[:education_plan]) (or whatever your params
are called) and, if you have the right student_id the relationship
should be created automatically.

If it doesn’t work, you should “pastie” your code so we can debug it
better.

Hope it helps.


Leonardo M…
There’s no place like ~

Leonardo M. wrote:

On Sun, Oct 25, 2009 at 3:23 PM, Misiek Sz
[email protected] wrote:

saved when the form is submitted?
OK, now the situation is clearer for me. There’s something you’re not
getting from associations, let’s see if with the example you get it
more clear.
If you want to create the association when you create the education
plan, why would you try to get it on the get_info action and not on
the create action?
When you get (render) the student info on the create form for
education plan, you should keep the student id and send it with the
rest of the education plan parameters as the
education_plan[student_id].
Then, in the create action, you can do
EducationPlan.new(params[:education_plan]) (or whatever your params
are called) and, if you have the right student_id the relationship
should be created automatically.

If it doesn’t work, you should “pastie” your code so we can debug it
better.

Hope it helps.


Leonardo M…
There’s no place like ~
was on the road past two days…
I want to do exactly what you are saying Leonardo.
Here is my code for
education_plans_controller.rb


def create
@education_plan = EducationPlan.new(params[:education_plan])

this is my sneaky way around, which I don’t want to use…You’ll see

what i’m doing when you see the view

@student = Student.find(params[:student_id])

@tutor = Tutor.find(params[:tutor_id])

@education_plan.student = @student

@education_plan.tutor = @tutor

respond_to do |format|
  if @education_plan.save
    flash[:notice] = 'EducationPlan was successfully created.'
    format.html { redirect_to(@education_plan) }
    format.xml  { render :xml => @education_plan, :status => 

:created, :location => @education_plan }
else
format.html { render :action => “new” }
format.xml { render :xml => @education_plan.errors, :status =>
:unprocessable_entity }
end
end
end
def new
@education_plan = EducationPlan.new
@education_plan.plan_details.build

respond_to do |format|
  format.html # new.html.erb
  format.xml  { render :xml => @education_plan }
end

end

education_plan - new view

New Education Plan

<% form_for(@education_plan) do |f| %>
<%= f.error_messages %>

Enter Student OSIS: <%=text_field_tag :osis %><%= image_tag 'loading.gif', :id =>'loading', :style => 'display: none'%>
<div>
  <table>
    <thead>
      <tr>
       <th></th><th>Code #</th><th>Start 

date





<% 6.times do |i| %>
<% f.fields_for :plan_details do |p| %>
<%= render :partial => ‘new_detail’, :object => p %>
<% end %>
<% end %>

  </table>
  </div>
Evaluation/Measurement/Assesment
<%= f.label :comments %> <%= f.text_area(:comments, :cols => 30, :rows => 4) %>

<%= f.submit 'Create'%>

<% end %>

<%= link_to ‘Back’, education_plans_path %>

<%= observe_field(:osis, :frequency => 0.25, :update => :student_info,
:url =>{:controller => ‘students’, :action =>
:get_student_info},
:with => ‘osis’,
:before => “Element.show(‘loading’)”,
:complete => “Element.hide(‘loading’)”) %>

students_controller.rb

def get_student_info
@student = Student.find_by_osis(params[:osis])
if @student.nil?
render :text => ‘Couldn' find the student’
elsif !@student.education_plan.nil?
render :text => ‘Student already has an education plan.’
else
render :partial => true, :action => ‘show’
end
end

students show view

<%=hidden_field_tag(:student_id, @student.id) %>
<%=h @student.first_name + ’ ’ + @student.last_name %>


So, with my workaround it does what I want, but then all kinds of other
problems are introduced i.e. error handling etc.

I hope this illustrates better what I’m trying to do.
Thanks!

I totally get what you are saying. But in practice its not as easy.
So when you say
So you need to modify your view to accomplish this.
You mean in my view of student information include a hidden field with
name education_plan[student_id] or there is a way to set the params (in
students for education_plans) without sending back the hidden field in
the ajax render :partial?

On Thu, Oct 29, 2009 at 2:23 AM, Misiek Sz
[email protected] wrote:

the create action?
better.


def create
@education_plan = EducationPlan.new(params[:education_plan])

this is my sneaky way around, which I don’t want to use…You’ll see

what i’m doing when you see the view
I think that with this is enough.

@student = Student.find(params[:student_id])

@tutor = Tutor.find(params[:tutor_id])

@education_plan.student = @student

@education_plan.tutor = @tutor

You have you tutor_id and student_id parameters but you’re using them
in the wrong way.
You should send the parameters inside the params[:education_plan] array.
You should receive, in the controller,
params[:education_plan][:student_id] and
params[:education_plan][:tutor_id] instead of params[:student_id] and
params[:tutor_id].
So you need to modify your view to accomplish this. Once you have
this, in your controller:
@education_plans = EducationPlan.new(params[:education_plan]) will do
all the magic with relationships.
You don’t need to do @education_plan.student = Student.find(student_id)

One more thing, if you’re testing, you can ensure that behavior in a
test and then adjust you application. If you’re not testing… well…
you should.

Hope it helps.


Leonardo M…
There’s no place like ~

I created clean new app to test and poke around. I got to work, but I
wonder if there is still a better way to handle it and someone could
point it our.
So i have two models:
class Project < ActiveRecord::Base
has_one :task
end

class Widget < ActiveRecord::Base
belongs_to :project
validates_presence_of :project
validates_associated :project
end
widget/new view

New widget

<% form_for(@widget) do |f| %> <%= f.error_messages %> <%= text_field_tag :wids %>

<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :wid %>
<%= f.text_field :wid %>

<%= observe_field 'wids' ,:url => { :action => :find_project }, :frequency => 0.25, :update => :disp, :with => 'wids' %> <%= f.submit 'Create' %> <% end %> <%= link_to 'Back', widgets_path %>

widget controller
def find_project
@project = Project.find(params[:wids])
render :partial => ‘find_project’
end
_find_project view

Name: <%=h @project.name %>

<%= hidden_field_tag 'widget[project_id]',@project.id %>

The piece that doesn’t sit well with me is the immediate line above as
its not dynamic. Meaning if I wanted to reuse find_project method in
ajax call from other controller than widgets then I havd hard code
hidden_field_tag name for that controller as well.

Is there a better way to handle this situation?