Rails 3 - has_one模型,如何查找关联记录满足特定条件的记录

时间:2011-09-10 13:01:33

标签: ruby-on-rails has-one

我有模特Post:

class Post < ActiveRecord::Base
has_one :location, :dependent => :destroy
belongs_to :person
belongs_to :activity

我有模型位置:

class Location < ActiveRecord::Base
belongs_to :post
validates :address, :presence => true
attr_accessible :address, :latitude, :longitude
geocoded_by :address
after_validation :geocode, :if => :address_changed?

我需要查找距离指定位置50英里的所有帖子。我找了一些例子,但没找到我需要的东西。我试图以两种方式解决问题而失败了。我是Rails的初学者并且没有解决这个问题,我认为这对其他使用has_one模型很有用。

我试过了:

posts_controller.rb

def index
if params[:saddress].present?
  @locations = Location.near(params[:saddress], 50, :order => :distance)
  for location in @locations
    @posts << location.post
  end
else
  @posts = Post.all
end

index.html.erb

 <h1>Events</h1>
 <fieldset>
 <legend>Find event</legend>
 <%= form_tag(posts_path, :method => "get") do %>
   <%= label_tag(:saddress, "Address:") %>
   <%= text_field_tag :saddress, params[:saddress] %> <br/>
   <%= label_tag(:sactivity, "Activity type:") %>
   <%= select_tag :sactivity, options_from_collection_for_select(Activity.all, "id", "name", params[:sactivity]) %>
   <%= submit_tag "Поиск"%>
 <%end%>
 </fieldset>
 <%if @user%>
   <%= link_to "Новое событие", new_post_path %>
 <%end%>
 <table>
 <tr>
 <th>Created</th>
 <th>Author</th>    
 <th>Event</th>
 <th>Address</th>
 <th>Activity type</th>
 </tr>
 <% for post in @posts.sort.each %>
   <%if post%>
     <tr>
     <td><%= post.created_at %></td>
     <td><%= post.person.name %></td>
     <td><%= link_to post.name, post %></td>
     <td><%if post.location%><%= post.location.address %> <%end%></td>
     <td><%= post.activity.name %></td>
     </tr>
   <%end%>
 <%end%>
 </table>

导致错误:

PostsController #index中的NoMethodError 当你没想到它时,你有一个零对象! 您可能期望一个Array实例。 在评估nil时发生错误。&lt;&lt;

请帮我解决错误。也许还有其他一些简单的方法。

我也在posts_controller.rb中试过这个:

if params[:saddress].present?
  @locations = Location.near(params[:saddress], 50, :order => :distance)
  @posts = Post.find(:all, :include => [:location], :conditions => ["locations.id in ?", @locations])
else
  @posts = Post.all
end

在这种情况下,我遇到了SQL问题。

1 个答案:

答案 0 :(得分:0)

PostsController#index方法中,您需要初始化@posts变量。在您可以向其追加项目之前成为一个数组。如果你省略(像你一样),@ post将被隐式初始化为nil,这解释了你的错误。像这样更改你的代码:

def index
  if params[:saddress].present?
  @posts = []
    @locations = Location.near(params[:saddress], 50, :order => :distance)
    for location in @locations
      @posts << location.post
    end
  else
    @posts = Post.all
  end
end

上述代码的另一个(较短的)变体是

def index
  if params[:saddress].present?
    @locations = Location.near(params[:saddress], 50, :order => :distance)
    @posts = @locations.collect(&:post)
    # ^^ this is the short form of the following equivalent expression:
    # @posts = @locations.collect{ |loc| loc.post }
  else
    @posts = Post.all
  end
end