Skip to content

Commit

Permalink
Added AR methods especially #attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
maiha committed Mar 16, 2010
1 parent 88048c0 commit ba6a790
Show file tree
Hide file tree
Showing 14 changed files with 481 additions and 18 deletions.
49 changes: 44 additions & 5 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,55 @@ This library provides some of them to Ohm::Model.

require 'ohm-arfreaks'

class Page < Ohm::Model
class Video < Ohm::Model
attribute :url
set :tags
end

Page.first
# => #<Page:1 url="http://...">
Video.first
=> #<Video id: 470, url: "a", tags: []>

Page.create!(:url=>...)
Video.create!(:url=>...)
Video.new.save!

Page.new.save!
### Available Methods

def self.primary_key # AR
def self.columns # AR
def self.column_names # AR
def self.content_columns # AR
def self.columns_hash # AR
def self.create!(attributes) # AR
def save! # AR
def self.first(*args) # AR
def self.last(*args) # AR
def self.count(*args) # AR
def self.delete_all(cond = nil) # AR
def new_record? # AR
def attributes # AR

(reported by: % grep 'def ' lib/ohm-arfreaks.rb |grep '# AR' )

### NOTE

Ohm::Model#attributes returns an names of attributed fields in vanilla ohm gem.
Of course, it's not familier to our ar-freaks, so it's overwritten by this gem.

class Video < Ohm::Model
attribute :url
set :tags
end

Video.first.attributes
=> [:url] # in vanilla ohm
=> {:url=>"a", :tags=>[]} # in ohm-arfreaks


Test
----

% redis-server spec/redis.conf # running on port:6380 in default
% spec -c spec


Homepage
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ AUTHOR = "maiha"
EMAIL = "maiha@wota.jp"
HOMEPAGE = "http://github.com/maiha/ohm-arfreaks"
SUMMARY = "Ohm::Model extensions for AR freaks"
GEM_VERSION = "0.0.1"
GEM_VERSION = "0.1.0"

spec = Gem::Specification.new do |s|
s.rubyforge_project = 'asakusarb'
Expand Down
115 changes: 107 additions & 8 deletions lib/ohm-arfreaks.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,133 @@
module Ohm
class Model
######################################################################
### Columns

Column = Struct.new(:name, :type)

def self.primary_key # AR
:id
end

def self.columns # AR
[Column.new(primary_key, :attribute)] +
content_columns +
[:collection, :counter].map do |type|
__send__("#{type}s").map{|name| Column.new(name, type)}
end.flatten
end

def self.column_names # AR
columns.map(&:name)
end

def self.content_columns # AR
attributes.map{|name| Column.new(name, :attribute)}
end

def self.columns_hash # AR
columns.inject({}){|h,c| h[c.name] = c; h}
end

######################################################################
### Validations

RecordNotSaved = Class.new(RuntimeError)

def self.create!(attributes)
def self.create!(attributes) # AR
object = new(attributes)
object.save!
object
end

def save!
def save! # AR
save || raise(RecordNotSaved)
end

######################################################################
### Accessor methods

def self.first(*args)
(args.empty? ? all : find(*args)).first
def self.first(*args) # AR
(args.empty? ? all : find(*args))[0]
end

def self.last(*args)
(args.empty? ? all : find(*args)).last
def self.last(*args) # AR
(args.empty? ? all : find(*args))[-1]
end

# TODO: should use native 'count' method for performance reason
def self.count(*args)
def self.count(*args) # AR
(args.empty? ? all : find(*args)).size
end

######################################################################
### ActiveRecord class methods

def self.delete_all(cond = nil) # AR
if cond
raise NotImplementedError, "Sorry, conditional delete_all is not implemented yet"
else
all.each(&:delete)
end
end

######################################################################
### ActiveRecord instance methods

def new_record? # AR
new?
end

######################################################################
### Overwrite attributes (and related methods)

def attributes # AR
hash = {}
self.class.attributes.each do |attr|
hash[attr] = __send__(attr)
end
self.class.collections.each do |attr|
hash[attr] = (begin __send__(attr).to_a; rescue MissingID; []; end)
end
self.class.counters.each do |attr|
hash[attr] = __send__(attr).to_i
end
return hash
end

def delete
delete_from_indices
delete_attributes(self.class.attributes)
delete_attributes(self.class.counters)
delete_attributes(self.class.collections)
delete_model_membership
self
end

def inspect
attrs = attributes.map{|(k,v)| "#{k}: #{v.inspect}"}.join(', ')
"#<#{self.class} id: #{new_record? ? "nil" : id}, #{attrs}>"
end

# Write attributes using SET
# This method will be removed once MSET becomes standard.
def write_with_set
self.class.attributes.each do |att|
value = send(att)
value.to_s.empty? ?
db.set(key(att), value) :
db.del(key(att))
end
end

# Write attributes using MSET
# This is the preferred method, and will be the only option
# available once MSET becomes standard.
def write_with_mset
unless self.class.attributes.empty?
rems, adds = self.class.attributes.map { |a| [key(a), send(a)] }.partition { |t| t.last.to_s.empty? }
db.del(*rems.flatten.compact) unless rems.empty?
db.mset(adds.flatten) unless adds.empty?
end
end
end
end
8 changes: 4 additions & 4 deletions ohm-arfreaks.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

Gem::Specification.new do |s|
s.name = %q{ohm-arfreaks}
s.version = "0.0.1"
s.version = "0.1.0"

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["maiha"]
s.date = %q{2010-02-05}
s.date = %q{2010-03-17}
s.description = %q{Ohm::Model extensions for AR freaks}
s.email = %q{maiha@wota.jp}
s.extra_rdoc_files = ["README.markdown", "LICENSE"]
s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/ohm-arfreaks.rb"]
s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/ohm-arfreaks.rb", "spec/db", "spec/db/redis.pid", "spec/attributes_spec.rb", "spec/redis.conf", "spec/provide_helper.rb", "spec/columns_spec.rb", "spec/model.rb", "spec/methods_spec.rb", "spec/its_helper.rb", "spec/spec_helper.rb", "spec/validations_spec.rb"]
s.homepage = %q{http://github.com/maiha/ohm-arfreaks}
s.require_paths = ["lib"]
s.rubyforge_project = %q{asakusarb}
s.rubygems_version = %q{1.3.5}
s.rubygems_version = %q{1.3.6}
s.summary = %q{Ohm::Model extensions for AR freaks}

if s.respond_to? :specification_version then
Expand Down
54 changes: 54 additions & 0 deletions spec/attributes_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require File.join(File.dirname(__FILE__), '/spec_helper')

describe Ohm::Model do
provide :attributes do
subject {
Video.create!(:url => "http://localhost/")
}

######################################################################
### Attribute

its(:attributes) { should be_kind_of(Hash) }

it "should contain given attribute" do
subject.attributes[:url].should == "http://localhost/"
end

######################################################################
### Counter

it "should contain given counter" do
subject.attributes[:viewed].should == 0
end

it "should contain a valid counter value after incr and reload" do
subject.incr(:viewed)
subject.attributes[:viewed].should == 1
Video[subject.id].attributes[:viewed].should == 1
end

######################################################################
### Set

it "should contain given set as array" do
subject.tags.concat "foo"
subject.attributes[:tags].should be_kind_of(Array)
end

it "should contain given set" do
subject.tags.concat "foo"
subject.attributes[:tags].should == ["foo"]
end

it "should contain given set as array" do
subject.tags.concat "foo"
subject.tags.concat "bar"
subject.attributes[:tags].should == ["foo", "bar"]
end

it "should contain empty array when no set given" do
subject.attributes[:tags].should == []
end
end
end
75 changes: 75 additions & 0 deletions spec/columns_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
require File.join(File.dirname(__FILE__), '/spec_helper')

describe Ohm::Model do
######################################################################
### columns

it do
Video.should provide(:columns)
end

describe ".columns" do
it "should return an array of Column" do
Video.columns.map(&:class).should == [Ohm::Model::Column, Ohm::Model::Column, Ohm::Model::Column, Ohm::Model::Column]
end

it "should contains column names" do
Video.columns.map(&:name).should == [:id, :url, :tags, :viewed]
end

it "should contains column types" do
Video.columns.map(&:type).should == [:attribute, :attribute, :collection, :counter]
end
end

######################################################################
### column_names

it do
Video.should provide(:column_names)
end

describe ".column_names" do
it "should return an array of Symbol" do
Video.column_names.map(&:class).uniq.should == [Symbol]
end

it "should return column names" do
Video.column_names.should == [:id, :url, :tags, :viewed]
end
end

######################################################################
### content_columns

it do
Video.should provide(:content_columns)
end

describe ".content_columns" do
it "should return an array of Column" do
Video.content_columns.map(&:class).uniq.should == [Ohm::Model::Column]
end

it "should contains only attribute columns" do
Video.content_columns.map(&:type).uniq.should == [:attribute]
end

it "should not contains primary keys" do
Video.content_columns.map(&:name).should_not include(:id)
end
end

######################################################################
### columns_hash

it do
Video.should provide(:columns_hash)
end

describe ".columns_hash" do
it "should return a hash" do
Video.columns_hash.should be_kind_of(Hash)
end
end
end
Empty file added spec/db/redis.pid
Empty file.
15 changes: 15 additions & 0 deletions spec/its_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Spec
module Example
module Subject
module ExampleGroupMethods
def its(*args, &block)
describe(args.first) do
define_method(:subject) { super().send(*args) }
it(&block)
end
end
end
end
end
end

Loading

0 comments on commit ba6a790

Please sign in to comment.