-
-
Save doitian/4307089 to your computer and use it in GitHub Desktop.
Add a active model wrapper to edit settings in form. `type_caster.rb` can be put in lib directory, which convert the field to specific type. The wrapper idea also can be used to wrap any other object, such as [Railscasts #396](https://github.com/railscasts/396-importing-csv-and-excel/blob/master/store-with-validations/app/models/product_import.rb)
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
<h1>Settings</h1> | |
<%= simple_form_for @settings, :as => 'settings', :url => admin_settings_path, :html => { :class => 'form form-horizontal' } do |f| %> | |
<fieldset> | |
<legend>Points Earning</legend> | |
<%= f.input :site_name %> | |
<%= f.input :per_page %> | |
</fieldset> | |
<div class="control-group"> | |
<div class="controls"> | |
<%= f.submit 'Update', :class => 'btn btn-primary' %> | |
</div> | |
</div> | |
<% 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
# Use type_caster to edit settings using form builder | |
# | |
# gem: https://github.com/huacnlee/rails-settings-cached | |
class Settings < RailsSettings::CachedSettings | |
attr_accessible :var | |
class Fields | |
include ActiveModel::Validations | |
include ActiveModel::Conversion | |
extend ActiveModel::Naming | |
include TypeCaster | |
field :site_name, :string | |
field :per_page, :integer | |
validates :per_page, :numericality => { :greater_than => 0 } | |
def initialize(attributes = {}, settings = Settings) | |
@settings = settings | |
@attributes = attributes.with_indifferent_access | |
end | |
def new_record? | |
false | |
end | |
def persisted? | |
true | |
end | |
def load | |
@attributes = HashWithIndifferentAccess.new | |
self.class.fields.each do |name, caster| | |
self.send "#{name}=", @settings.send(name) | |
end | |
self | |
end | |
def save! | |
raise ActiveRecord::RecordInvalid unless valid? | |
save | |
end | |
def save | |
return false unless valid? | |
attributes.each do |name, value| | |
if self.class.fields.key?(name.to_sym) | |
@settings.send "#{name}=", read_attribute(name) | |
end | |
end | |
self | |
end | |
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
class SettingsController < ApplicationController | |
def edit | |
@settings = Settings::Fields.new | |
@settings.load | |
end | |
def update | |
@settings = Settings::Fields.new(params[:settings]) | |
if @settings.save | |
redirect_to edit_settings_path, :notice => 'Settings were successfully updated' | |
else | |
render :edit | |
end | |
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
module TypeCaster | |
def self.included(klass) | |
klass.extend ClassMethods | |
klass.instance_eval do | |
type :string, &:to_s | |
type :integer, &:to_i | |
type :float, &:to_f | |
type :boolean do |value| | |
if value.is_a?(TrueClass) || value.is_a?(FalseClass) | |
return value | |
elsif value.is_a?(String) | |
return value.presence == ("true" || "1") | |
elsif value.is_a?(Integer) | |
return value == 1 | |
else | |
nil | |
end | |
end | |
end | |
end | |
def attributes=(attributes) | |
@attributes = attributes.with_indifferent_access | |
end | |
def attributes | |
@attributes ||= HashWithIndifferentAccess.new | |
end | |
def read_attribute(attr) | |
caster = self.class.fields[attr.to_sym] | |
caster.call attributes[attr] | |
end | |
def write_attribute(attr, value) | |
caster = self.class.fields[attr.to_sym] | |
attributes[attr] = caster.call(value) | |
end | |
module ClassMethods | |
def types | |
@types ||= {} | |
end | |
def type(type_name, &caster) | |
types[type_name] = caster | |
end | |
def fields | |
@fields ||= {} | |
end | |
def field(name, type) | |
fields[name] = types[type] | |
define_method "#{name}=" do |value| | |
write_attribute(name, value) | |
end | |
define_method name do | |
read_attribute(name) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment