0

I'm using ActiveModel to make my tableless models feel like ActiveRecord models. I'm using a custom store and I need to be able to validate uniqueness of a record.

How can I implement the required uniqueness check using ActiveModel?

Roman
  • 10,309
  • 17
  • 66
  • 101

3 Answers3

1

I ended up doing something like this:

class Theme < Base

  include ActiveModel::Validations

  attr_accessor :id, :name
  validate      :uniqueness_of_theme_name, :on => :create

  def initialize(attrs = {})
    attrs.each do |name, value|
      send("#{name}=", value)
    end
  end

  def uniqueness_of_theme_name
    errors.add(:name, "name is already in use") unless Theme.find_by_name(name).nil?
  end

  def self.find_by_name(name)
    return store.find({ 'name' => "/^#{name}$/i" }).any?
  end

  def self.create(attributes = {})
    theme = Theme.new(attributes)
    theme.save

    return theme
  end

  def persisted?
    id && !id.nil?
  end

  def save()
    # only call validation during create context
    context = persisted? :update : :create
    false if invalid?(context)
    store.save(self)
    true
  end

  def self.create(attrs = {})
    theme = Theme.new(attrs)
    theme.save
    theme
  end

end

Maybe someone can tell me if this was the correct way to go about it

Roman
  • 10,309
  • 17
  • 66
  • 101
-1

Check this railscasts, it might help

http://railscasts.com/episodes/193-tableless-model

once you do your model, add the validations and then @model.valid?

Rodrigo Zurek
  • 4,555
  • 7
  • 33
  • 45
  • 2
    I know that tutorial is about table less models but it doesn't have any examples of uniqueness checks. – Roman Sep 18 '12 at 01:37
-1

ActiveModel can be used with according to another railscasts, which is more suitable for that use-case.

class Theme

  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  attr_accessor :id, :name

  validates :name, uniqueness: true, on: :create

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def persisted?
    false
  end
end
Anatoly
  • 15,298
  • 5
  • 53
  • 77
  • 1
    @mikhailob, based on what does the above code check the uniqueness of `:name`? I think validating uniqueness is a especial situation where it's correctness heavily relies on there being a data store and could not have been abstracted into the ActiveModel which doesn't require tables at all. – Roman Sep 18 '12 at 05:02
  • 1
    @Arman ActiveModel validation does happen once you call **save** (or explicit **valid?** method) on the Ruby object before any attempts to save data into MongoDB (or whatever you want). ActiveModel is an abstraction can help you to use plain object like ActiveRecord table-behind model. – Anatoly Sep 18 '12 at 05:35