1
0
Fork 0
musicbrainz/lib/musicbrainz/models/base_model.rb

109 lines
2.6 KiB
Ruby

module MusicBrainz
class BaseModel
def self.inherited(klass)
klass.send(:include, InstanceMethods)
klass.send(:extend, ClassMethods)
end
module ClassMethods
def field(name, type)
fields[name] = type
attr_reader name
define_method("#{name}=") do |val|
instance_variable_set("@#{name}", validate_type(val, type))
end
end
def fields
instance_variable_set(:@fields, {}) unless instance_variable_defined?(:@fields)
instance_variable_get(:@fields)
end
def client
MusicBrainz.client
end
def find(hash)
underscored_name = underscore_name.to_sym
client.load(underscored_name, hash, { binding: underscored_name, create_model: underscored_name })
end
def search(hash)
hash = escape_strings(hash)
query_val = build_query(hash)
underscored_name = underscore_name
client.load(underscored_name.to_sym, { query: query_val, limit: 10 }, { binding: underscored_name.insert(-1,"_search").to_sym })
end
class ::String
def underscore
self.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end
end
def build_query(hash)
return ["#{hash.first[0].to_s}:\"#{hash.first[1]}\""] if hash.size ==1
arr ||= []
hash.each { |k, v| arr << "#{k.to_s}:\"#{hash[k]}\"" }
arr.join(' AND ')
end
def escape_strings(hash)
hash.each { |k, v| hash[k] = CGI.escape(v).gsub(/\!/, '\!') }
hash
end
def underscore_name
self.name[13..-1].underscore
end
# these probably should be private... but I'm not sure how to get it to work in a module...
# private_class_method :build_query, :escape_strings
end
module InstanceMethods
def initialize(params = {})
params.each do |field, value|
self.send(:"#{field}=", value)
end
end
def client
MusicBrainz.client
end
private
def validate_type(val, type)
if type == Integer
val.to_i
elsif type == Float
val.to_f
elsif type == String
val.to_s
elsif type == Date
val = if val.nil? or val == ""
[2030, 12, 31]
elsif val.split("-").length == 1
[val.split("-").first.to_i, 12, 31]
elsif val.split("-").length == 2
val = val.split("-").map(&:to_i)
[val.first, val.last, -1]
else
val.split("-").map(&:to_i)
end
Date.new(*val)
else
val
end
end
end
end
end