Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/52.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在Rails中对复杂的多AR对象表进行排序/分页/筛选_Ruby On Rails_Ruby_Sorting_Filter_Pagination - Fatal编程技术网

Ruby on rails 在Rails中对复杂的多AR对象表进行排序/分页/筛选

Ruby on rails 在Rails中对复杂的多AR对象表进行排序/分页/筛选,ruby-on-rails,ruby,sorting,filter,pagination,Ruby On Rails,Ruby,Sorting,Filter,Pagination,我有一个从多ActiveRecord对象数组中提取的复杂表。此列表是特定用户所有“喜爱”项目(歌曲、消息、博客帖子等)的组合显示。这些项中的每一项都是一个成熟的AR对象 我的目标是为用户提供一个简化的搜索、排序和分页界面。用户不需要知道歌曲有歌手,消息有作者——对于最终用户,表中的两个条目都将显示为“user”。因此,搜索框将只是一个下拉列表,询问他们搜索哪个(用户名、创建地址等)。在内部,我需要将其转换为适当的对象搜索,合并结果并显示 我可以单独进行分页(mislav将分页)、排序和过滤,但将

我有一个从多ActiveRecord对象数组中提取的复杂表。此列表是特定用户所有“喜爱”项目(歌曲、消息、博客帖子等)的组合显示。这些项中的每一项都是一个成熟的AR对象

我的目标是为用户提供一个简化的搜索、排序和分页界面。用户不需要知道歌曲有歌手,消息有作者——对于最终用户,表中的两个条目都将显示为“user”。因此,搜索框将只是一个下拉列表,询问他们搜索哪个(用户名、创建地址等)。在内部,我需要将其转换为适当的对象搜索,合并结果并显示

我可以单独进行分页(mislav将分页)、排序和过滤,但将它们组合在一起会遇到一些问题

例如,如果我对项目的组合列表进行分页,分页插件可以很好地处理它。由于分页是在应用程序和数据库中进行的,因此这是没有效率的,但我们假设预期的用例将表明绝大多数用户的偏好项将少于30个,并且所有其他行为、服务器功能等表明这不会成为瓶颈

但是,如果我想对列表进行排序,我不能通过分页插件对其进行排序,因为它依赖于结果集是从单个SQL查询派生的假设,并且字段名在整个过程中是一致的。因此,我必须通过ruby对合并的数组进行排序,例如

@items.sort_by{ |i| i.whatever }
但是,由于这些项不共享公共名称,我必须首先询问对象,然后调用正确的排序方式。例如,如果用户希望按用户名排序,如果排序的对象是消息,我将按作者排序,但如果对象是歌曲,我将按歌手排序。这一切都很恶心,感觉很不象红宝石

过滤器也会出现同样的问题。如果用户过滤“父项”(消息的线程,歌曲的相册),我必须将其转换为适当的集合对象方法。也很恶心

这不是确切的设置,但已经足够接近了。请注意,这是一个遗留应用程序,因此更改它非常困难,尽管并非不可能。当然,也可以做一些枯燥的工作,但是不要关注下面代码的风格或优雅。但是,解决方案的风格/优雅很重要!:D

型号:

class User < ActiveRecord::Base
  ...
  has_and_belongs_to_many :favorite_messages, :class_name => "Message"
  has_and_belongs_to_many :favorite_songs,    :class_name => "Song"
  has_many                :authored_messages, :class_name => "Message"
  has_many                :sung_songs,        :class_name => "Song"
end

class Message < ActiveRecord::Base
  has_and_belongs_to_many :favorite_messages  
  belongs_to              :author, :class_name => "User"
  belongs_to              :thread
end

class Song < ActiveRecord::Base
  has_and_belongs_to_many :favorite_songs  
  belongs_to              :singer, :class_name => "User"
  belongs_to              :album
end
def show
  u = User.find 123

  @items = Array.new
  @items << u.favorite_messages
  @items << u.favorite_songs
  # etc. etc. 

  @items.flatten!

  @items = @items.sort_by{ |i| i.created_at }

  @items = @items.paginate :page => params[:page], :per_page => 20
end

def search

  # Assume user is searching for username like 'Bob'

  u = User.find 123

  @items = Array.new
  @items << u.favorite_messages.find( :all, :conditions => "LOWER( author ) LIKE LOWER('%bob%')" )
  @items << u.favorite_songs.find( :all, :conditions => "LOWER( singer ) LIKE ... " )
  # etc. etc. 

  @items.flatten!

  @items = @items.sort_by{ |i| determine appropriate sorting based on user selection }

  @items = @items.paginate :page => params[:page], :per_page => 20
end
   #index.html.erb
   ...
   <table>
     <tr>
       <th>Title (sort ASC/DESC links)</th>
       <th>Created By (sort ASC/DESC links))</th>
       <th>Collection Title (sort ASC/DESC links)</th>
       <th>Created At (sort ASC/DESC links)</th> 
     </tr>
     <% @items.each |item| do %>
       <%= render { :partial => "message", :locals => item } if item.is_a? Message %>
       <%= render { :partial => "song",    :locals => item } if item.is_a? Song %>
     <%end%>
   ...
   </table>

   #message.html.erb
   # shorthand, not real ruby
   print out message title, author name, thread title, message created at

   #song.html.erb
   # shorthand
   print out song title, singer name, album title, song created at
class用户“消息”
有很多:最喜欢的歌曲,:class\u name=>“歌曲”
有许多:编写的消息,:class\u name=>“消息”
有很多:唱过歌,:class\u name=>“歌”
结束
类消息“用户”
属于:线程
结束
类歌曲“用户”
属于:相册
结束
控制器:

class User < ActiveRecord::Base
  ...
  has_and_belongs_to_many :favorite_messages, :class_name => "Message"
  has_and_belongs_to_many :favorite_songs,    :class_name => "Song"
  has_many                :authored_messages, :class_name => "Message"
  has_many                :sung_songs,        :class_name => "Song"
end

class Message < ActiveRecord::Base
  has_and_belongs_to_many :favorite_messages  
  belongs_to              :author, :class_name => "User"
  belongs_to              :thread
end

class Song < ActiveRecord::Base
  has_and_belongs_to_many :favorite_songs  
  belongs_to              :singer, :class_name => "User"
  belongs_to              :album
end
def show
  u = User.find 123

  @items = Array.new
  @items << u.favorite_messages
  @items << u.favorite_songs
  # etc. etc. 

  @items.flatten!

  @items = @items.sort_by{ |i| i.created_at }

  @items = @items.paginate :page => params[:page], :per_page => 20
end

def search

  # Assume user is searching for username like 'Bob'

  u = User.find 123

  @items = Array.new
  @items << u.favorite_messages.find( :all, :conditions => "LOWER( author ) LIKE LOWER('%bob%')" )
  @items << u.favorite_songs.find( :all, :conditions => "LOWER( singer ) LIKE ... " )
  # etc. etc. 

  @items.flatten!

  @items = @items.sort_by{ |i| determine appropriate sorting based on user selection }

  @items = @items.paginate :page => params[:page], :per_page => 20
end
   #index.html.erb
   ...
   <table>
     <tr>
       <th>Title (sort ASC/DESC links)</th>
       <th>Created By (sort ASC/DESC links))</th>
       <th>Collection Title (sort ASC/DESC links)</th>
       <th>Created At (sort ASC/DESC links)</th> 
     </tr>
     <% @items.each |item| do %>
       <%= render { :partial => "message", :locals => item } if item.is_a? Message %>
       <%= render { :partial => "song",    :locals => item } if item.is_a? Song %>
     <%end%>
   ...
   </table>

   #message.html.erb
   # shorthand, not real ruby
   print out message title, author name, thread title, message created at

   #song.html.erb
   # shorthand
   print out song title, singer name, album title, song created at
def显示
u=User.find 123
@items=Array.new
@项目20
结束
def搜索
#假设用户正在搜索类似“Bob”的用户名
u=User.find 123
@items=Array.new
@项目“较低(作者),如较低(“%bob%”)
@项目“较低(歌手)如…”)
#等等等等。
@物品。压扁!
@items=@items.sort_by{i|根据用户选择确定适当的排序}
@items=@items.paginate:page=>params[:page],:per_page=>20
结束
查看:

class User < ActiveRecord::Base
  ...
  has_and_belongs_to_many :favorite_messages, :class_name => "Message"
  has_and_belongs_to_many :favorite_songs,    :class_name => "Song"
  has_many                :authored_messages, :class_name => "Message"
  has_many                :sung_songs,        :class_name => "Song"
end

class Message < ActiveRecord::Base
  has_and_belongs_to_many :favorite_messages  
  belongs_to              :author, :class_name => "User"
  belongs_to              :thread
end

class Song < ActiveRecord::Base
  has_and_belongs_to_many :favorite_songs  
  belongs_to              :singer, :class_name => "User"
  belongs_to              :album
end
def show
  u = User.find 123

  @items = Array.new
  @items << u.favorite_messages
  @items << u.favorite_songs
  # etc. etc. 

  @items.flatten!

  @items = @items.sort_by{ |i| i.created_at }

  @items = @items.paginate :page => params[:page], :per_page => 20
end

def search

  # Assume user is searching for username like 'Bob'

  u = User.find 123

  @items = Array.new
  @items << u.favorite_messages.find( :all, :conditions => "LOWER( author ) LIKE LOWER('%bob%')" )
  @items << u.favorite_songs.find( :all, :conditions => "LOWER( singer ) LIKE ... " )
  # etc. etc. 

  @items.flatten!

  @items = @items.sort_by{ |i| determine appropriate sorting based on user selection }

  @items = @items.paginate :page => params[:page], :per_page => 20
end
   #index.html.erb
   ...
   <table>
     <tr>
       <th>Title (sort ASC/DESC links)</th>
       <th>Created By (sort ASC/DESC links))</th>
       <th>Collection Title (sort ASC/DESC links)</th>
       <th>Created At (sort ASC/DESC links)</th> 
     </tr>
     <% @items.each |item| do %>
       <%= render { :partial => "message", :locals => item } if item.is_a? Message %>
       <%= render { :partial => "song",    :locals => item } if item.is_a? Song %>
     <%end%>
   ...
   </table>

   #message.html.erb
   # shorthand, not real ruby
   print out message title, author name, thread title, message created at

   #song.html.erb
   # shorthand
   print out song title, singer name, album title, song created at
#index.html.erb
...
标题(分类ASC/DESC链接)
创建人(排序ASC/DESC链接))
集合标题(分类ASC/DESC链接)
创建于(排序ASC/DESC链接)
“message”,:locals=>item}如果item.is_a?消息%>
“song”,:locals=>item}如果item.is_a?歌曲%>
...
#message.html.erb
#速记,不是真正的ruby
打印出消息标题、作者姓名、线程标题、在处创建的消息
#song.html.erb
#速记
打印歌曲标题、歌手姓名、专辑标题、在

你应该试着思考斯芬克斯。为了了解它的工作原理,您可以访问我的网站www.campzero.com,尝试使用“达卡”搜索


Thinking sphinx是一个rails插件,可以帮助您搜索多个模型/字段,并且内置分页/排序功能。更多信息请访问网站。

您应该尝试思考斯芬克斯。为了了解它的工作原理,您可以访问我的网站www.campzero.com,尝试使用“达卡”搜索


Thinking sphinx是一个rails插件,可以帮助您搜索多个模型/字段,并且内置分页/排序功能。更多信息请访问网站。

仅供参考,我用一个非常胖的模型完成了所有这一切,但它似乎运行得非常好。

仅供参考,我用一个非常胖的模型完成了所有这一切,但它似乎运行得非常好。

您还可以为每种类型的
项目添加#collection_title和#title方法,通过ducktyping进行排序。

您还可以为每种类型的
项目添加#collection_title和#title方法
,并通过ducktyping进行排序。

我喜欢它,但为这个小功能安装搜索引擎似乎有些过火(因为启动和运行sphinx等并不繁琐),但是,为这个小功能安装搜索引擎似乎有些过分(因为让sphinx启动并运行起来并不繁琐,等等)