Custom method in model


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


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!


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).


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

<% @longgenes.each do |lgene| %>   <%= %> <% 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