Forum: Ruby on Rails find primary key via object attribute

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
6ce7537a93c6e45469b745b9f5ec7524?d=identicon&s=25 Justin Ko (jko170)
on 2006-12-26 23:34
I'm having a hard time wrapping my head around on implementing something
like this:
------------

class Student < ARB
   has_many: attendances

class Attendance < ARB
   belongs_to: student

------------

class AttendancesController < ApplicationController
  def check_in
  end

  def create
    @attendance = Attendance.new(params[:attendance])

    respond_to do |format|
      if @attendance.save
        flash[:notice] = 'You have successfully checked in.'
        format.html { redirect_to :action => "check_in" }
      else
        format.html { render :action => "check_in" }
      end
    end
  end
end

----------
The Student table has a column named 'idn'.
The Attendance table has a column named 'student_id' and a 'created_on'
column.

This is what I've got so far: The student "checks in" by typing in their
IDN number into a text_field in the 'check_in' view. After hitting
'submit' the create method is invoked and the IDN number that the
student submitted is entered into the student_id field in the Attendance
table. This is what I would like to do: When the student submits their
IDN number, rails searches for the number in the idn column in the
student table. After locating it, the primary key for that IDN number is
entered into the student_id column in the Attendance table. If there is
no matching IDN then of course an error is invoked.

What would be the best way to do this? before_save method in the
Attendance model? I'm pretty much clueless. Sorry for the long
explanation but I wanted to be as detailed as possible. Any help would
be very appreciated.
8e7e5b934fcbcdfb475072685755457f?d=identicon&s=25 Taylor Strait (taylorstrait)
on 2006-12-27 06:12
You can do this in your create method create:

#use AR helper find method to cut to the chase
@student = Student.find_by_idn(params[:idn])

#create a new attendance and link the records
attn = Attendence.new
@attn.student = @student
@attn.save
8e7e5b934fcbcdfb475072685755457f?d=identicon&s=25 Taylor Strait (taylorstrait)
on 2006-12-27 06:27
In your migration make sure to set :unique => true for the idn like
this:

t.column :idn, :integer, :null => false, :unique => true

AND validate it in your model:

Class Student
  validates_uniqueness_of :idn
  validates_presence_of   :idn
6ce7537a93c6e45469b745b9f5ec7524?d=identicon&s=25 Justin Ko (jko170)
on 2006-12-27 07:49
Thanks for the reply!  I keep getting an error like this:
ActiveRecord::StatementInvalid in AttendancesController#create

Mysql::Error: #23000Column 'student_id' cannot be null: INSERT INTO
attendances (`created_on`, `student_id`) VALUES('2006-12-27 00:40:05',
NULL)

I can't figure out why the idn parameter doesn't pass through. Here is
my 'check_in' view:

<%= error_messages_for :attendance %>

<% form_for :attendance, :url => { :action => :create } do |form| %>
  <%= form.text_field :idn %>
  <p><%= submit_tag 'Check In' %></p>

<% end %>

Here is my newly updated AttendancesController:

class AttendancesController < ApplicationController
  def check_in
  end

  def create
    #use AR helper find method to cut to the chase
    @student = Student.find_by_idn(params[:idn])

    #create a new attendance and link the records
    @attn = Attendance.new
    @attn.student = @student
    @attn.save

    respond_to do |format|
      if @attn.save
        flash[:notice] = 'You have successfully checked in.'
        format.html { redirect_to :action => "check_in" }
      else
        format.html { render :action => "check_in" }
      end
    end
  end

end

I changed my migration like you suggested. Thanks for the help so far, I
knew this would look easier than I imagined.
8e7e5b934fcbcdfb475072685755457f?d=identicon&s=25 Taylor Strait (taylorstrait)
on 2006-12-27 21:54
> Thanks for the reply!  I keep getting an error like this:
> ActiveRecord::StatementInvalid in AttendancesController#create
>
> Mysql::Error: #23000Column 'student_id' cannot be null: INSERT INTO
> attendances (`created_on`, `student_id`) VALUES('2006-12-27 00:40:05',
> NULL)

1) Is a record created in your database or not?

2) If the student_id is NULL, then perhaps it is because @student is
also null.  Try doing the create function in the console step by step to
see what is happening.

3) check development.log for more info on what is happening under the
hood.


>     #create a new attendance and link the records
>     @attn = Attendance.new
>     @attn.student = @student
>     @attn.save
>
>     respond_to do |format|
>       if @attn.save
>         flash[:notice] = 'You have successfully checked in.'

This will try to save @attn twice.  You save it directly and then save
again if @attn.  Delete one of the save lines.
6ce7537a93c6e45469b745b9f5ec7524?d=identicon&s=25 Justin Ko (jko170)
on 2006-12-31 06:26
Okay this is driving me crazy. I keep getting the same error. I deleted
the @attn.save line so there is no duplication. A record is not getting
saved in the database. I did however get a record to be saved via the
console as follows:

>>  a = Attendance.new
>>  s = Student.find_by_idn(1546)
>>  a.student = s
>>  a.save
student doesn't exist
>>  s.save
true

How can I replicate this in my app?
6ce7537a93c6e45469b745b9f5ec7524?d=identicon&s=25 Justin Ko (jko170)
on 2006-12-31 10:49
Okay I got the correct student_id being saved into the database with the
following method in the Attendance model:

def before_create
    self.student = Student.find_by_idn(student_id)
end

I have another problem now. If the IDN is not found or doesn't exist,
the student_id attribute for the Attendance object returns nil and
brings up the same error as before (the student_id cannot be NULL). How
can I get the nice looking error messages that you often see for simple
validations?
It would say something like "#{student_id} is not a valid IDN" above the
check in form.
This topic is locked and can not be replied to.