Skip to content

Instantly share code, notes, and snippets.

@ainame
Last active June 20, 2016 01:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ainame/4dab69fb6ee3a9143241 to your computer and use it in GitHub Desktop.
Save ainame/4dab69fb6ee3a9143241 to your computer and use it in GitHub Desktop.
ActiveRecord::Enumで陥りがちなミスを避ける ref: http://qiita.com/ainame/items/a097558e74bf7d5087b9
class NotifyEndpoint
enum platform: [:apns, :gcm]
end
# OK: newやcreateでは渡せる
endpoint = NotifyEndpoint.new(platform: :apns)
# OK: platform=メソッドにも渡せる
endpoint.platform = :gcm
# OK: apnsというスコープは定義されている
endpoints = NotifyEndpoint.apns
# NG: whereに文字列やシンボルを渡しても正しく動作しない
# しかしエラーが出ずに0としてSELECTされる!!
endpoints = NotifyEndpoint.where(platform: :gcm)
#=> SELECT * FROM notify_endoints WHERE platform = 0;
# OK: NotifyEndpoint.platformsから、enumの序数を取得してwhereで指定する
endpoints = NotifyEndpoint.where(platform: NotifyEndpoint.platforms[:gcm])
#=> SELECT * FROM notify_endoints WHERE platform = 1;
if defined?(ActiveRecord) && defined?(::ActiveRecord::Enum)
module ActiveRecord
module Enum
module Scoping
def self.extended(base)
::ActiveRecord::Enum.alias_method_chain(:enum, :scoping)
end
end
def enum_with_scoping(definitions)
enum_without_scoping(definitions)
define_scoping_method(definitions)
end
private
def define_scoping_method(definitions)
definitions.each do |name, values|
scoping_method_name = "#{name}_as".to_sym
scope(scoping_method_name, - > (item) { enum_scope(name, item) }})
end
end
end
def enum_scope(enum_name, item_name)
query_hash = {}
query_hash[enum_name.to_sym] = send(enum_name.to_s.pluralize)[item_name]
where(query_hash)
end
end
::ActiveRecord::Base.extend(::ActiveRecord::Enum::Scoping)
end
endpoints = NotifyEndpoint.platform_as(:gcm)
#=> SELECT * FROM notify_endpoints WHERE platform = 1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment