Rails - это плохая практика или это можно оптимизировать? - PullRequest
2 голосов
/ 26 апреля 2011

Будет ли это считаться плохой практикой?

unless Link.exists?(:href => 'example.com/somepage')
  Domain.where(:domain => 'example.com').first.links.create(:href => 'example.com/somepage', :text => 'Some Page')
end

Я понимаю, что, возможно, запрашиваю больше данных, чем мне действительно нужно, могу ли я как-то оптимизировать это?

Домен является уникальным индексом, поэтомупоиск должен быть довольно быстрым.

Запуск Rails 3.0.7

Ответы [ 2 ]

3 голосов
/ 26 апреля 2011

Вы можете реорганизовать свой код следующим образом:

Класс домена

class Domain < ActiveRecord::Base
  has_many :links
end

Класс ссылки

class Link < ActiveRecord::Base
  belongs_to :domain

  validates :href,
            :uniqueness => true

  attr :domain_url

  def domain_url=(main_domain_url)
    self.domain = Domain.where(domain: main_domain_url).first ||
                  Domain.new(domain: main_domain_url)
  end

  def domain_url
    self.domain.nil? ? '' : self.domain.domain_url
  end
end

Использование

Link.create(href: 'example.com/somepage',
            text: 'Some Page',
            domain_url: 'example.com')

Заключение

В обоих случаях (ваш и мой) вы получаете два запроса (примерно так):

Domain Load (1.0ms)  SELECT "domains".* FROM "domains" WHERE "domains"."domain" = 'example.com' LIMIT 1
  AREL (0.1ms)  INSERT INTO "links" ("href", "text", "domain_id", "created_at", "updated_at") VALUES ('example.com/somepage', 'Some Page', 5, '2011-04-26 08:51:20.373523', '2011-04-26 08:51:20.373523')

Но с помощью этого кода вы также защищены от неизвестных доменов, поэтому Linkсоздаст его автоматически.

Также вы можете использовать проверяет уникальность, чтобы вы могли удалить все unless Link.exists?(:href => '...').

2 голосов
/ 26 апреля 2011
Domain.where(:domain => 'example.com').
  first.links.
  find_or_create_by_href_and_text(:href => 'example.com/somepage', :text => "Some Page")

UPD

@domain = Domain.where(:domain => 'example.com').
            first.links.
            find_or_create_by_href('example.com/somepage')
@domain.text = "My Text"
@domain.save

Или вы можете использовать расширенный update_or_create_by_* метод:

Domain.update_or_create_by_href('example.com/somepage') do |domain|
  domain.text = "My Text"
end

Подробнее здесь:

find_or_create_by в Rails 3 и обновление для создания записей

...