Случайная публикация Ruby on Rails через act_as_taggable_on_steroids - PullRequest
1 голос
/ 26 июня 2011

Использование Rails 3, и я нуб RoR, так что это может быть просто, но я не могу понять это. Я имею в виду, я могу заставить его работать, но я не могу придумать лучший способ.

Хорошо, я прочитал каждый вопрос на SO о выборе случайных записей через Rails, и я думаю, что ответ довольно прост по большей части. Однако я вынужден вызывать метод act_as_taggable_on_steroids перед выбором случайной записи, поэтому мой предпочтительный метод не работает, так как find_tagged_with возвращает массив.

Это вопрос из двух частей. Мне нужно знать, какой из этих методов является лучшим с точки зрения производительности, а также как предотвратить попадание повторяющихся записей в результаты, если этот метод вызывается более одного раза с другим tag.name.

Вот способы, которые я до сих пор пробовал:

  def related_posts(tag)
    rand_id = rand(Post.find_tagged_with(tag.name).count)
    rand_record = Post.find_tagged_with(tag.name, :conditions => [ "posts.id >= ?", rand_id], :limit => 2)
  end

  def related_posts(tag)
    rand_id = rand(Post.find_tagged_with(tag.name).count)
    post = Post.find_tagged_with(tag.name, :offset => rand_id, :limit => 2)
  end  

  def related_posts(tag)
    post = Post.find_tagged_with(tag.name, :order => 'RAND()', :limit => 2)
  end

  def related_posts(tag)
    posts = Post.find_tagged_with(tag.name)
    offset = rand(posts.count)
    posts.find(:offset =>offset) #doesn't work since this is an array at this point :(
  end

  def related_posts(tag)
    related = []
    posts = Post.find_tagged_with(tag.name)
    related << random_post(posts)
    related << random_post(posts)
    return related
  end
  def random_post(obj)
    rand_id = rand(obj.count)
    rand_record = obj[rand_id]
  end

Редактировать: Это кажется самым быстрым, хотя у меня очень мало опыта тестирования производительности rails приложений.

  def related_posts(tag)
    posts = Post.find_tagged_with(tag.name).sort_by { rand }.slice(0, 2)
  end

Кто бы ни ответил на этот вопрос, не могли бы вы также объяснить, что именно происходит? Это случайное ранжирование записей и сортировка на уровне базы данных или что-то еще. Кроме того, что это обычно означает для производительности с приложением rails?

1 Ответ

1 голос
/ 26 июня 2011

Я сломаю эту строку для тебя:

posts = Post.find_tagged_with(tag.name).sort_by { rand }.slice(0, 2)

Первый цепочечный вызов find_tagged_with устанавливает SQL и выполняет запрос. Я предполагаю, что это ActiveRecord :: Relation объект.

Второй, sort_by - это встроенный метод Rails. Таким образом, он не использует базу данных для сортировки. Это может стать дорогостоящим, если во время первого вызова вы получили десятки тысяч записей. Подробнее об этом здесь: http://paulsturgess.co.uk/articles/show/85-ruby-on-rails-sort_by-vs-sort

Наконец, срез (0, 2) - это метод Array, который сокращает массив результатов. Есть множество других способов сделать это, таких как .first (2) или [0..2]

Кроме того, вот подробное руководство по тестированию Ruby on Rails (тестирование производительности каждого метода): http://guides.rubyonrails.org/performance_testing.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...