rails: query and filter n:m related objects using active record

独自空忆成欢 提交于 2019-12-11 14:03:34

问题


I'm trying to use active-record query possible connections between airports. I described the models I created already in another question here:

n:m self-join with ruby on rails active record

Basically, what I can do now is that:

ny = Airport.create({"city" => "New York"})
la = Airport.create({"city" => "Los Angeles"})

ny.destinations << la
la.destinations << ny

I ran into an issue querying the data I'm looking for, which is quite simple in SQL but I had no luck with active record yet.

ny = Airport.where('city = ?', 'New York')
ny.destinations

returns the correct objects, but all of them.

The SQL query looks like that:

 SELECT "airports".* FROM "airports" INNER JOIN "connections" ON "airports"."id" = "connections"."destination_id" WHERE "connections"."airport_id" = 3

I'd like to filter those results by cities starting with "s" for example, so an SQL query could look like that:

SELECT "airports".* FROM "airports" INNER JOIN "connections" ON "airports"."id" = "connections"."destination_id" WHERE "connections"."airport_id" = 3 AND airports"."city" LIKE "s%"

I tried it this way:

ny.destinations.where('city LIKE ?', '#{params[:query]}%')

But I always get an empty result.

How could I use active record to filter my resulting objetcs?

edit: Thats the best solution I found so far:

I added the cityLike() method to the Airport model:

app/models/airport.rb:

class Airport < ActiveRecord::Base
  attr_accessible :city, :name

  has_many :connections
  has_many :destinations, :through => :connections
  has_many :inverse_connections, :class_name => "Connection", :foreign_key => "destination_id"
  has_many :inverse_destinations, :through => :inverse_connections, :source => :airport

  def self.cityLike(query)
    where("city LIKE ?", "%#{query}%")
  end
end

app/model/connection.rb:

class Connection < ActiveRecord::Base
  attr_accessible :destination_id, :airport_id

  belongs_to :airport
  belongs_to :destination, :class_name => "Airport"
end

Now I can query the objects with the following statement:

Airport.find(1).destinations.cityLike("a")

Not sure if it's the best solution, but it produces the query I was looking for.

Thanks a lot to all af you!


回答1:


ActiveRecord::Base.execute(sql) lets you use pure SQL to do your query and returns the relevant model.




回答2:


What about this?

Airport.find(:all, joins: "INNER JOIN `connections` ON airports.id = connections.destination_id").where("connections.airport_id = ? AND airports.city LIKE ?", ny_id, "s%")



回答3:


This code:

ny.destinations.where('city LIKE ?', '#{params[:query]}%')

works like this--first you have an object ny repesenting the city of New York. When you say ".destinations" you have now followed a relation you defined in your model to retrieve all the destinations that you can get to from New York. However, if I'm imagining your database schema correctly, these destinations don't actually have a field called "city"; instead, they have a destination_id, which ties the destination to a particular airport, and it's the airport that has a city associated with it.

So when you query the destination table for 'city LIKE ?', it doesn't find any matching records.

Instead, try

ny.destinations.joins(:airports).where('city LIKE ?', '#{params[:query]}%')


来源:https://stackoverflow.com/questions/16426898/rails-query-and-filter-nm-related-objects-using-active-record

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!