Created
January 31, 2018 17:19
-
-
Save rosylilly/5cd2916a07387d9bce0091d34e0badff to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
class PartialValidator < ActiveModel::EachValidator | |
def validate_each(record, attribute, value) | |
return if options[:if] && !valuable(record, options[:if]) | |
return if options[:unless] && valuable(record, options[:unless]) | |
value.validate | |
value.errors.messages.each_pair do |attr, messages| | |
messages.each do |message| | |
record.errors.add(:"#{attribute}.#{attr}", message) | |
end | |
end | |
end | |
protected | |
def valuable(record, opt) | |
opt = opt.to_proc if opt.is_a?(Symbol) | |
opt.call(record) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
module Partializable | |
extend ActiveSupport::Concern | |
class Model | |
include ActiveModel::Model | |
attr_accessor :record, :mapping | |
def self.attributes | |
@attributes ||= [] | |
end | |
def self.attr_reader(*attrs) | |
attributes.concat(attrs.map(&:to_sym)) | |
attributes.uniq! | |
attrs.each do |attr| | |
attr = attr.to_s.to_sym | |
define_method(attr) do | |
self[attr] | |
end | |
end | |
end | |
def self.attr_writer(*attrs) | |
attributes.concat(attrs.map(&:to_sym)) | |
attributes.uniq! | |
attrs.each do |attr| | |
attr = attr.to_s.to_sym | |
define_method(:"#{attr}=") do |val| | |
self[attr] = val | |
end | |
end | |
end | |
def self.attr_accessor(*attrs) | |
attr_reader(*attrs) | |
attr_writer(*attrs) | |
end | |
def [](attr) | |
attr = attr.to_s.to_sym | |
reader = (mapping || {}).fetch(attr) { attr } | |
record ? record_send(reader) : instance_variable_get(:"@#{attr}") | |
end | |
def []=(attr, val) | |
attr = attr.to_s.to_sym | |
writer = (mapping || {}).fetch(attr) { attr } | |
record ? record_send(:"#{writer}=", val) : instance_variable_set(:"@#{attr}", val) | |
end | |
def as_json | |
attrs = self.class.attributes.map do |key| | |
[key, send(key)] | |
end | |
Hash[attrs] | |
end | |
protected | |
def record_send(method, *args) | |
methods = method.to_s.split('.') | |
actual = methods.pop | |
rec = methods.inject(record) do |receiver, m| | |
receiver.send(m) | |
end | |
rec.send(actual, *args) | |
end | |
end | |
module ClassMethods | |
def partials | |
@partials ||= [] | |
end | |
def partial_options | |
@partial_options ||= {} | |
end | |
def partialize(name, class_name: nil, mapping: {}, prefix: nil) | |
name = name.to_s.to_sym | |
partials.push(name) | |
klass = (class_name || name).to_s.classify.constantize | |
klass.attributes.each do |attr| | |
mapping[attr] ||= "#{prefix ? "#{prefix}_" : ''}#{attr}" | |
end | |
partial_options[name] = { mapping: mapping } | |
define_method(name) do | |
instance_variable_get(:"@#{name}") || | |
instance_variable_set(:"@#{name}", klass.new(record: self, mapping: mapping)) | |
end | |
define_method(:"#{name}=") do |origin| | |
partial = origin.dup | |
partial.instance_variable_set(:@record, self) | |
partial.instance_variable_set(:@mapping, mapping) | |
instance_variable_set(:"@#{name}", partial) | |
klass.attributes.each do |attr| | |
partial.send(:"#{attr}=", origin.send(attr)) unless mapping[attr].to_s.include?('.') | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment