datamapper(dm-core) 1.1.0では0.10.0からdeprecatedになっていた明示的なINの利用が出来なくなりました。明示的なINと暗黙的なINって何なのかというと下記の様な違いです。

# implicit
Foo.all(:id.in => [1, 2, 3])

# explicit
Foo.all(:id => [1, 2, 3])

対象がArrayだと自動的にINになるんですね。1.0.2で使ってたけどdeprecatedの表示は出てなかった気がするけどなあ。ヤラレタ。

つい先日、LokkaにもCI環境が整ったのでデグレしないようにテスト駆動バグ修正していくことにしました。

RuntimeError - explicit use of 'in' operator is deprecated - Issues - komagata/lokka - GitHub

[DataMapper] Re: Deprecate Warnings on dm-do-adapter

This deprecation warning is silenced in DataMapper 1.1.1 which will be released within the next few days.

Cheers

DataObjects::URI.new with arguments is deprecated, use a Hash of URI components

dm-do-adapterで出る上記のdeprecatedは次の1.1.1で直るそうです。Lokkaでもログにでちゃうけどしばらくの辛抱かな。

機能としては簡単だけど名前の付け方で悩んでいる。どうでもいいことかも知れないけど数日悩んでいる。

ブログ(Lokka)に記事のドラフト機能を追加したい。つまりデータとしては存在するけどおもてには表示しない記事。そこで下記のようにフラグを用意し、その一覧をとってくるメソッドを用意する。

class Post
  property :title, String
  property :draft, Boolean

  def self.draft # 重複!
    all(:draft => true)
  end

  def self.not_draft
    all(:draft => false)
  end
end
>> Post.draft
>> Post.not_draft.all(:title.like => '%foo%')

draftがフラグ名だとメソッド名とかぶるので使えない。この例はDataMapperだけどActiveRecordのnamed_scopeでも同様だ。

こういう場合、今までの俺は、

フラグ名:publish
メソッド名:published, unpublished

みたいな名前を付けてたんだけど、draftというフラグ名を見てこっちの方が具体的な名前だからいいなと思った。できればdraftを採用したい。publishは動詞でdraftは名詞だから上手くいかないのかな。こういうモノを作る場合のRuby/Rails界隈の簡単ルールみたいなものがあったら知りたい・・・。

DataMapperのdefault_scopeのマージされ方がおかしい。

class Entry
  default_scope(:default).update(:draft => false)
end
>> Entry.count
SQL: (0.000099) SELECT COUNT(*) FROM "entries" WHERE ("draft" = 'f'))
=> 1
>> Entry.count(:draft => true)
SQL: (0.000099) SELECT COUNT(*) FROM "entries" WHERE ("draft" = 'f' AND "draft" = 't')
=> 0

ActiveRecordでも多用していた機能なので困ったなと思ってたら・・・。

#1202 Overwriting default_scope conditions is broken - DataMapper - datamapper

It's a private API so the ticket should be treated more like a suggestion to make the default_scope a public method and of course make it work correctly.

default_scopeはprivate APIなのでbugではなくsuggestion扱いだそうです。ticketのstateもholdになってました・・・。

tikushoo

DataMapperを教えておじいさん | Selfkleptomaniacに回答しようとしたら、既に解決されていた・・・。

require 'rubygems'
require 'dm-core'
require 'dm-migrations'

class Repo
  include DataMapper::Resource
  property :id, Serial
  property :body, String
end

DataMapper.logger.set_log STDERR, :debug, "SQL: ", true
DataMapper.setup(:default, 'sqlite::memory:')
Repo.auto_migrate!                                                                                                                                                

puts Repo.all(:body.like => '%hoge%') |
     Repo.all(:body.like => '%fuga%') |
     Repo.all(:body.like => '%piyo%')

結果:

SQL: (0.000045) SELECT sqlite_version(*)
SQL: (0.000082) DROP TABLE IF EXISTS "repos"
SQL: (0.000014) PRAGMA table_info("repos")
SQL: (0.000393) CREATE TABLE "repos" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "body" VARCHAR(50))
SQL: (0.000079) SELECT "id", "body" FROM "repos" WHERE ("body" LIKE '%piyo%' OR "body" LIKE '%hoge%' OR "body" LIKE '%fuga%') ORDER BY "id"

検索条件の場合、分かりやすく書くとこういう感じでしょうか。検索条件の論理演算がRubyの演算子で出来るのが面白いですね。しかし恐ろしく遅そうなSQLが。

Lokkaでもしちゃんと検索をやるならばLuceneのRuby版であるFerretdm-ferret-adapterで使うのが楽そうです。datamapperのadapterになってるということはindexの置き場所も何でもいいというフリーダムさ。検索式を解析するFerret::QueryParserが日本語対応してるかわからないので面倒かもしれません。