Custom method in model

Hello,

I am a RAILS beginner and have been building an application that has
quite a few models in it. The problem I encounter is the following:

There are three models: Contig, Intergenic, Longshortgene

A contig has many intergenics and many longshortgenes.

One of the fields in Intergenic is of the form A-B, where A and B are
Longshortgene objects.

From the intergenics view, I would like to use A and B, in separate
calls, to find any longshortgenes that have the same geneid (A or B)
and belong to the same contig as the intergenics object.

My intergenics controller's "show" method is as follows:

def show
    @intergenic = Intergenic.find(params[:id])

    genearr=@intergenic.regionid.split('-')
    genearr.each do |gene|
      @longgenes = @intergenic.ls_neighborhood(gene, 'LONG')
      @shortgenes = @intergenic.ls_neighborhood(gene, 'SHORT')
      render :action => 'list'
    end

  end

My model intergenic.rb contains the following:

belongs_to :contig

  def ls_neighborhood(geneid,genetype)
    Longshortgene.find_by_sql["select l.geneid from longshortgenes l
where l.geneid=? and l.contig_id=? and
l.genetype=?",geneid,contig_id,genetype]
  end

From the "show" view, I just try to access @longgenes and @shortgenes
and do something with them.

Until I inserted the above blocks of code, my application was
functional. Now I get the following error:

ArgumentError in IntergenicsController#show

wrong number of arguments (4 for 1)

RAILS_ROOT: /Users/apati/Projects/qa
Application Trace | Framework Trace | Full Trace

app/models/intergenic.rb:6:in `find_by_sql'
app/models/intergenic.rb:6:in `ls_neighborhood'
app/controllers/intergenics_controller.rb:27:in `show'
app/controllers/intergenics_controller.rb:26:in `each'
app/controllers/intergenics_controller.rb:26:in `show'

Could someone please point out what I am doing wrong?

Thank you very much!

Amrita

I believe find_by_sql gets wrapped in parentheses and quotes. Like so:

find_by_sql("select l.geneid from longshortgenes as l where
l.geneid=#{geneid} and l.contig_id=#{contig_id} and
l.genetype=#{genetype}")

You might want to double-check that query, but that's the format for
find_by_sql.

-- Josh

amrita wrote:

Thanks Josh. The errors have gone now. But when I do the following in
the view,

<% @longgenes.each do |lgene| %>
<%= lgene %>
<% end %>

it doesn't print anything. I have ensured that the data is such that
if the query is executed correctly, @longgenes will have some values
in it.

Thanks,
Amrita

Thanks Josh. The errors have gone now. But when I do the following in
the view,

<% @longgenes.each do |lgene| %>
<%= lgene %>
<% end %>

That's because <%= %> just ends up calling to_s on the result, and
to_s on an activerecord object isn't something you can dump straight
in a view (because it's full of things like < which makes the browser
go uts).

Fred

Right, so include the method you want to call on lgene:

<% @longgenes.each do |lgene| %>
  <%= lgene.name %>
<% end %>

For example.

-- Josh

Frederick Cheung wrote:

Fred and Josh, Thanks for your replies. I tried that already. It
doesn't print anything. I also inserted the following in the view:

<% if @longgenes.length == 0 %>
<b> no long genes </b>
<% end %>

and it prints "no long genes". So, @longgenes doesn't contain
anything.

I am using Aptana Studio and when I load the html page, I see the
queries being executed on the console. I changed the query in the
model to the following:

Longshortgene.find_by_sql("SELECT * FROM `longshortgenes` WHERE
(`longshortgenes`.`geneid`='#{geneid}' and
`longshortgenes`.`contig_id`=#{contig_id} and
`longshortgenes`.`genetype`='#{genetype}')")

The queries get executed but the view finds @longgenes empty. Is there
a problem in returning values from the model's method to the
controller's method?

I executed the same queries (copied from Aptana's console) on MySQl
and it returns the correct number of rows from that table.

Can you see what is going wrong?

Thanks,
Amrita

Just to verify that find_by_sql is working correctly, I replaced the
existing query with

Longshortgene.find_by_sql("SELECT * FROM `longshortgenes`")

and it works correctly! Then there is a problem with the way the
longer query is framed?

Also, when I replace all the variables in the query with constants,
i,e, geneid with an actual value and contig_ig with an actual value,
it works! When I use variables, the query is translated correctly as
is shown on the console, but no output is obtained :frowning:

OK, I made it work, but the solution was more of a hack. I moved all
the logic to the model's method, so that I do no pass any arguments
from the controller to the model method call. That solved the problem.
So now in my controller, I have,

@lsgenes = @intergenic.ls_neighborhood

In my model, I have:

  def ls_neighborhood
    genearr=regionid.split('-')
    sql="SELECT * FROM longshortgenes WHERE
longshortgenes.contig_id="+contig_id.to_s+" AND
(longshortgenes.geneid='"+genearr[0]+"' OR
longshortgenes.geneid='"+genearr[1]+"')"
    Longshortgene.find_by_sql(sql)
  end

So, the application works, but when you create a custom find method,
how do you pass arguments correctly?

Thanks,
Amrita