From 7295839e20bd02b60764a302987def91a8e6f453 Mon Sep 17 00:00:00 2001 From: Igor Galeta Date: Wed, 11 Aug 2010 17:00:35 +0300 Subject: [PATCH 1/8] Use ActiveModel::MassAssignmentSecurity from Rails 3 ActiveModel --- lib/active_presenter.rb | 4 ++- lib/active_presenter/base.rb | 45 +++------------------------------ lib/active_presenter/version.rb | 2 +- lib/tasks/gem.rake | 12 ++++----- 4 files changed, 14 insertions(+), 49 deletions(-) diff --git a/lib/active_presenter.rb b/lib/active_presenter.rb index 4a6d0ea..c28798f 100644 --- a/lib/active_presenter.rb +++ b/lib/active_presenter.rb @@ -1,7 +1,9 @@ require 'rubygems' require 'active_record' -Dir.glob(File.dirname(__FILE__)+'/active_presenter/**/*.rb').each { |l| require l } module ActivePresenter NAME = 'active_presenter' + + autoload :Base, 'active_presenter/base' + autoload :Version, 'active_presenter/version' end diff --git a/lib/active_presenter/base.rb b/lib/active_presenter/base.rb index 23f86bf..8e69872 100644 --- a/lib/active_presenter/base.rb +++ b/lib/active_presenter/base.rb @@ -3,10 +3,11 @@ module ActivePresenter # class Base include ActiveSupport::Callbacks + include ActiveModel::MassAssignmentSecurity + define_callbacks :before_validation, :before_save, :after_save class_inheritable_accessor :presented - class_inheritable_accessor :attr_protected, :attr_accessible self.presented = {} # Indicates which models are to be presented by this presenter. @@ -68,30 +69,6 @@ def self.human_name(options = {}) # :nodoc: I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options)) end - # Note that +attr_protected+ is still applied to the received hash. Thus, - # with this technique you can at most _extend_ the list of protected - # attributes for a particular mass-assignment call. - def self.attr_protected(*attributes) - write_inheritable_attribute(:attr_protected, Set.new(attributes.map {|a| a.to_s}) + (protected_attributes || [])) - end - - # Returns an array of all the attributes that have been protected from mass-assignment. - def self.protected_attributes # :nodoc: - read_inheritable_attribute(:attr_protected) - end - - # Note that +attr_accessible+ is still applied to the received hash. Thus, - # with this technique you can at most _narrow_ the list of accessible - # attributes for a particular mass-assignment call. - def self.attr_accessible(*attributes) - write_inheritable_attribute(:attr_accessible, Set.new(attributes.map(&:to_s)) + (accessible_attributes || [])) - end - - # Returns an array of all the attributes that have been made accessible to mass-assignment. - def self.accessible_attributes # :nodoc: - read_inheritable_attribute(:attr_accessible) - end - # Accepts arguments in two forms. For example, if you had a SignupPresenter that presented User, and Account, you could specify arguments in the following two forms: # # 1. SignupPresenter.new(:user_login => 'james', :user_password => 'swordfish', :user_password_confirmation => 'swordfish', :account_subdomain => 'giraffesoft') @@ -124,9 +101,8 @@ def attributes=(attrs) attrs = attrs.stringify_keys multi_parameter_attributes = {} - attrs = remove_attributes_protected_from_mass_assignment(attrs) - attrs.each do |k,v| + sanitize_for_mass_assignment(attrs).each do |k, v| if (base_attribute = k.to_s.split("(").first) != k.to_s presentable = presentable_for(base_attribute) multi_parameter_attributes[presentable] ||= {} @@ -292,24 +268,11 @@ def attribute_protected?(name) presentable = presentable_for(name) return false unless presentable flat_attribute = {flatten_attribute_name(name, presentable) => ''} #remove_att... normally takes a hash, so we use a '' - presented[presentable].new.send(:remove_attributes_protected_from_mass_assignment, flat_attribute).empty? + presented[presentable].new.send(:sanitize_for_mass_assignment, flat_attribute).empty? end def run_callbacks_with_halt(callback) run_callbacks(callback) { |result, object| result == false } end - - def remove_attributes_protected_from_mass_assignment(attributes) - if self.class.accessible_attributes.nil? && self.class.protected_attributes.nil? - attributes - elsif self.class.protected_attributes.nil? - attributes.reject { |key, value| !self.class.accessible_attributes.include?(key.gsub(/\(.+/, ""))} - elsif self.class.accessible_attributes.nil? - attributes.reject { |key, value| self.class.protected_attributes.include?(key.gsub(/\(.+/,""))} - else - raise "Declare either attr_protected or attr_accessible for #{self.class}, but not both." - end - end - end end diff --git a/lib/active_presenter/version.rb b/lib/active_presenter/version.rb index e0f7d8a..7679ab0 100644 --- a/lib/active_presenter/version.rb +++ b/lib/active_presenter/version.rb @@ -1,5 +1,5 @@ module ActivePresenter - module VERSION + module Version MAJOR = 1 MINOR = 3 TINY = 0 diff --git a/lib/tasks/gem.rake b/lib/tasks/gem.rake index 5df7c97..c7136d5 100644 --- a/lib/tasks/gem.rake +++ b/lib/tasks/gem.rake @@ -4,7 +4,7 @@ task :clean => :clobber_package spec = Gem::Specification.new do |s| s.name = ActivePresenter::NAME - s.version = ActivePresenter::VERSION::STRING + s.version = ActivePresenter::Version::STRING s.summary = s.description = "ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)" s.author = "James Golick & Daniel Haran" @@ -29,14 +29,14 @@ task :tag_warn do puts "*" * 40 puts "Don't forget to tag the release:" puts - puts " git tag -a v#{ActivePresenter::VERSION::STRING}" + puts " git tag -a v#{ActivePresenter::Version::STRING}" puts puts "or run rake tag" puts "*" * 40 end task :tag do - sh "git tag -a v#{ActivePresenter::VERSION::STRING}" + sh "git tag -a v#{ActivePresenter::Version::STRING}" end task :gem => :tag_warn @@ -46,8 +46,8 @@ namespace :gem do desc 'Upload gems (ruby & win32) to rubyforge.org' task :rubyforge => :gem do sh 'rubyforge login' - sh "rubyforge add_release giraffesoft active_presenter #{ActivePresenter::VERSION::STRING} pkg/#{spec.full_name}.gem" - sh "rubyforge add_file giraffesoft active_presenter #{ActivePresenter::VERSION::STRING} pkg/#{spec.full_name}.gem" + sh "rubyforge add_release giraffesoft active_presenter #{ActivePresenter::Version::STRING} pkg/#{spec.full_name}.gem" + sh "rubyforge add_file giraffesoft active_presenter #{ActivePresenter::Version::STRING} pkg/#{spec.full_name}.gem" end end @@ -58,5 +58,5 @@ task :install => [:clobber, :package] do end task :uninstall => :clean do - sh "sudo gem uninstall -v #{ActivePresenter::VERSION::STRING} -x #{ActivePresenter::NAME}" + sh "sudo gem uninstall -v #{ActivePresenter::Version::STRING} -x #{ActivePresenter::NAME}" end From 03a52033542c8b021faa69aef877e2a3e373a719 Mon Sep 17 00:00:00 2001 From: Igor Galeta Date: Wed, 11 Aug 2010 17:16:07 +0300 Subject: [PATCH 2/8] Rails 3.0.0.rc support --- lib/active_presenter/base.rb | 156 +++++++++++++++++------------------ 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/lib/active_presenter/base.rb b/lib/active_presenter/base.rb index 8e69872..7f540ba 100644 --- a/lib/active_presenter/base.rb +++ b/lib/active_presenter/base.rb @@ -2,10 +2,16 @@ module ActivePresenter # Base class for presenters. See README for usage. # class Base - include ActiveSupport::Callbacks + extend ActiveModel::Callbacks + extend ActiveModel::Naming + extend ActiveModel::Translation + + include ActiveModel::Conversion include ActiveModel::MassAssignmentSecurity + + attr_reader :errors - define_callbacks :before_validation, :before_save, :after_save + define_model_callbacks :validation, :save class_inheritable_accessor :presented self.presented = {} @@ -23,52 +29,54 @@ class Base # presents :primary_address => Address, :secondary_address => Address # end # - def self.presents(*types) - types_and_classes = types.extract_options! - types.each { |t| types_and_classes[t] = t.to_s.tableize.classify.constantize } + class << self + def presents(*types) + types_and_classes = types.extract_options! + types.each { |t| types_and_classes[t] = t.to_s.tableize.classify.constantize } - attr_accessor *types_and_classes.keys + attr_accessor *types_and_classes.keys + + types_and_classes.keys.each do |t| + define_method("#{t}_errors") do + send(t).errors + end + + presented[t] = types_and_classes[t] + end + end - types_and_classes.keys.each do |t| - define_method("#{t}_errors") do - send(t).errors + def human_attribute_name(attribute_key_name, options = {}) + presentable_type = presented.keys.detect do |type| + attribute_key_name.to_s.starts_with?("#{type}_") || attribute_key_name.to_s == type.to_s end + attribute_key_name_without_class = attribute_key_name.to_s.gsub("#{presentable_type}_", "") - presented[t] = types_and_classes[t] + if presented[presentable_type] and attribute_key_name_without_class != presentable_type.to_s + presented[presentable_type].human_attribute_name(attribute_key_name_without_class, options) + else + I18n.translate(presentable_type, options.merge(:default => presentable_type.to_s.humanize, :scope => [:activerecord, :models])) + end end - end - - def self.human_attribute_name(attribute_key_name, options = {}) - presentable_type = presented.keys.detect do |type| - attribute_key_name.to_s.starts_with?("#{type}_") || attribute_key_name.to_s == type.to_s + + # Since ActivePresenter does not descend from ActiveRecord, we need to + # mimic some ActiveRecord behavior in order for the ActiveRecord::Errors + # object we're using to work properly. + # + # This problem was introduced with Rails 2.3.4. + # Fix courtesy http://gist.github.com/191263 + def self_and_descendants_from_active_record # :nodoc: + [self] end - attribute_key_name_without_class = attribute_key_name.to_s.gsub("#{presentable_type}_", "") - if presented[presentable_type] and attribute_key_name_without_class != presentable_type.to_s - presented[presentable_type].human_attribute_name(attribute_key_name_without_class, options) - else - I18n.translate(presentable_type, options.merge(:default => presentable_type.to_s.humanize, :scope => [:activerecord, :models])) + def human_name(options = {}) # :nodoc: + defaults = self_and_descendants_from_active_record.map do |klass| + :"#{klass.name.underscore}" + end + defaults << self.name.humanize + I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options)) end end - # Since ActivePresenter does not descend from ActiveRecord, we need to - # mimic some ActiveRecord behavior in order for the ActiveRecord::Errors - # object we're using to work properly. - # - # This problem was introduced with Rails 2.3.4. - # Fix courtesy http://gist.github.com/191263 - def self.self_and_descendants_from_active_record # :nodoc: - [self] - end - - def self.human_name(options = {}) # :nodoc: - defaults = self_and_descendants_from_active_record.map do |klass| - :"#{klass.name.underscore}" - end - defaults << self.name.humanize - I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options)) - end - # Accepts arguments in two forms. For example, if you had a SignupPresenter that presented User, and Account, you could specify arguments in the following two forms: # # 1. SignupPresenter.new(:user_login => 'james', :user_password => 'swordfish', :user_password_confirmation => 'swordfish', :account_subdomain => 'giraffesoft') @@ -82,13 +90,12 @@ def self.human_name(options = {}) # :nodoc: # If you don't specify an instance, one will be created by calling Model.new # def initialize(args = {}) - args ||= {} - + @errors = ActiveModel::Errors.new(self) + return self unless args presented.each do |type, klass| value = args.delete(type) send("#{type}=", value.is_a?(klass) ? value : klass.new) end - self.attributes = args end @@ -98,11 +105,11 @@ def initialize(args = {}) # def attributes=(attrs) return if attrs.nil? - - attrs = attrs.stringify_keys + + attrs = attrs.stringify_keys multi_parameter_attributes = {} - sanitize_for_mass_assignment(attrs).each do |k, v| + sanitize_for_mass_assignment(attrs).each do |k,v| if (base_attribute = k.to_s.split("(").first) != k.to_s presentable = presentable_for(base_attribute) multi_parameter_attributes[presentable] ||= {} @@ -129,26 +136,20 @@ def method_missing(method_name, *args, &block) presented_attribute?(method_name) ? delegate_message(method_name, *args, &block) : super end - # Returns an instance of ActiveRecord::Errors with all the errors from the presentables merged in using the type_attribute form (i.e. user_login). - # - def errors - @errors ||= ActiveRecord::Errors.new(self) - end - # Returns boolean based on the validity of the presentables by calling valid? on each of them. # def valid? + validated = false errors.clear - if run_callbacks_with_halt(:before_validation) + result = _run_validation_callbacks do presented.keys.each do |type| presented_inst = send(type) - next unless save?(type, presented_inst) merge_errors(presented_inst, type) unless presented_inst.valid? end - - errors.empty? + validated = true end + errors.empty? && validated end # Do any of the attributes have unsaved changes? @@ -162,16 +163,14 @@ def changed? # def save saved = false - ActiveRecord::Base.transaction do - if valid? && run_callbacks_with_halt(:before_save) - saved = presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save} - raise ActiveRecord::Rollback unless saved # TODO: Does this happen implicitly? + if valid? + _run_save_callbacks do + saved = presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save} + raise ActiveRecord::Rollback unless saved + end end - - run_callbacks_with_halt(:after_save) if saved end - saved end @@ -180,16 +179,16 @@ def save # Returns true on success, will raise otherwise. # def save! - raise ActiveRecord::RecordInvalid.new(self) unless valid? - raise ActiveRecord::RecordNotSaved unless run_callbacks_with_halt(:before_save) - + saved = false ActiveRecord::Base.transaction do - presented.keys.select {|key| save?(key, send(key))}.each {|key| send(key).save!} - - run_callbacks_with_halt(:after_save) + raise ActiveRecord::RecordInvalid.new(self) unless valid? + _run_save_callbacks do + presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save!} + saved = true + end + raise ActiveRecord::RecordNotSaved.new(self) unless saved end - - true + saved end # Update attributes, and save the presentables @@ -220,9 +219,13 @@ def save?(presented_key, presented_instance) def id # :nodoc: nil end - + def new_record? - true + presented_instances.map(&:new_record?).all? + end + + def persisted? + presented_instances.map(&:persisted?).all? end protected @@ -256,10 +259,10 @@ def attribute_prefix(type) def merge_errors(presented_inst, type) presented_inst.errors.each do |att,msg| - if att == 'base' + if att == :base errors.add(type, msg) else - errors.add(attribute_prefix(type)+att, msg) + errors.add(attribute_prefix(type)+att.to_s, msg) end end end @@ -267,12 +270,9 @@ def merge_errors(presented_inst, type) def attribute_protected?(name) presentable = presentable_for(name) return false unless presentable - flat_attribute = {flatten_attribute_name(name, presentable) => ''} #remove_att... normally takes a hash, so we use a '' + #remove_att... normally takes a hash, so we use a '' + flat_attribute = {flatten_attribute_name(name, presentable) => ''} presented[presentable].new.send(:sanitize_for_mass_assignment, flat_attribute).empty? end - - def run_callbacks_with_halt(callback) - run_callbacks(callback) { |result, object| result == false } - end end end From 80f4851fcc26a74dce88ba4d2bd1a54dae43541a Mon Sep 17 00:00:00 2001 From: Igor Galeta Date: Wed, 11 Aug 2010 17:27:45 +0300 Subject: [PATCH 3/8] Generage gemspec and remove no need rake tasks --- LICENSE | 22 -------------- README | 1 - README.rdoc | 12 ++++---- Rakefile | 42 ++++++++++++++++++++++++--- TODO | 3 -- active_presenter.gemspec | 46 +++++++++++++++++++++++++++++ lib/active_presenter.rb | 2 -- lib/tasks/doc.rake | 19 ------------ lib/tasks/gem.rake | 62 ---------------------------------------- 9 files changed, 89 insertions(+), 120 deletions(-) delete mode 100644 LICENSE delete mode 120000 README delete mode 100644 TODO create mode 100644 active_presenter.gemspec delete mode 100644 lib/tasks/doc.rake delete mode 100644 lib/tasks/gem.rake diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 663b71f..0000000 --- a/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2008 Daniel Haran, James Golick, GiraffeSoft, Inc. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/README b/README deleted file mode 120000 index 257e9c4..0000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -README.rdoc \ No newline at end of file diff --git a/README.rdoc b/README.rdoc index 8407ddd..a94e1c4 100644 --- a/README.rdoc +++ b/README.rdoc @@ -6,19 +6,17 @@ By acting nearly identically to ActiveRecord models, ActivePresenter makes prese == Get It -As a gem: +As a gem (Gemfile): - $ sudo gem install active_presenter + gem 'active_presenter', :git => 'git://github.com/galetahub/active_presenter.git' -As a rails gem dependency: +As a rails plugin: - config.gem 'active_presenter' + rails install plugin git://github.com/galetahub/active_presenter.git Or get the source from github: - $ git clone git://github.com/giraffesoft/active_presenter.git - -(or fork it at http://github.com/giraffesoft/active_presenter) + $ git clone git://github.com/galetahub/active_presenter.git == Usage diff --git a/Rakefile b/Rakefile index 15ee492..f0b0892 100644 --- a/Rakefile +++ b/Rakefile @@ -1,10 +1,44 @@ +# encoding: utf-8 require 'rake' +require 'rake/testtask' require 'rake/rdoctask' -require File.dirname(__FILE__)+'/lib/active_presenter' -Dir.glob(File.dirname(__FILE__)+'/lib/tasks/**/*.rake').each { |l| load l } +require File.join(File.dirname(__FILE__), 'lib', 'active_presenter', 'version') +desc 'Default: run unit tests.' task :default => :test -task :test do - Dir['test/**/*_test.rb'].each { |l| require l } +desc 'Test the active_presenter plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the active_presenter plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'ActivePresenter' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +begin + require 'jeweler' + Jeweler::Tasks.new do |gemspec| + gemspec.name = "active_presenter" + gemspec.version = ActivePresenter::Version::STRING + gemspec.summary = "ActivePresenter is the presenter library" + gemspec.description = "ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)" + gemspec.email = "james@giraffesoft.ca" + gemspec.homepage = "git://github.com/galetahub/freeberry.git" + gemspec.authors = ["James Golick", "Daniel Haran", "Igor Galeta"] + gemspec.files = FileList["[A-Z]*", "{lib}/**/*"] + gemspec.rubyforge_project = "active_presenter" + end + + Jeweler::GemcutterTasks.new +rescue LoadError + puts "Jeweler not available. Install it with: gem install jeweler" end diff --git a/TODO b/TODO deleted file mode 100644 index 17d5f44..0000000 --- a/TODO +++ /dev/null @@ -1,3 +0,0 @@ -Document protected API -Add support for namespaced models. -Add support for presented collections \ No newline at end of file diff --git a/active_presenter.gemspec b/active_presenter.gemspec new file mode 100644 index 0000000..0bce5d6 --- /dev/null +++ b/active_presenter.gemspec @@ -0,0 +1,46 @@ +# Generated by jeweler +# DO NOT EDIT THIS FILE DIRECTLY +# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{active_presenter} + s.version = "1.3.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["James Golick", "Daniel Haran", "Igor Galeta"] + s.date = %q{2010-08-11} + s.description = %q{ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)} + s.email = %q{james@giraffesoft.ca} + s.extra_rdoc_files = [ + "README.rdoc" + ] + s.files = [ + "README.rdoc", + "Rakefile", + "lib/active_presenter.rb", + "lib/active_presenter/base.rb", + "lib/active_presenter/version.rb" + ] + s.homepage = %q{git://github.com/galetahub/freeberry.git} + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{active_presenter} + s.rubygems_version = %q{1.3.7} + s.summary = %q{ActivePresenter is the presenter library} + s.test_files = [ + "test/base_test.rb", + "test/test_helper.rb" + ] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + else + end + else + end +end + diff --git a/lib/active_presenter.rb b/lib/active_presenter.rb index c28798f..f1f5edf 100644 --- a/lib/active_presenter.rb +++ b/lib/active_presenter.rb @@ -2,8 +2,6 @@ require 'active_record' module ActivePresenter - NAME = 'active_presenter' - autoload :Base, 'active_presenter/base' autoload :Version, 'active_presenter/version' end diff --git a/lib/tasks/doc.rake b/lib/tasks/doc.rake deleted file mode 100644 index 86c5d71..0000000 --- a/lib/tasks/doc.rake +++ /dev/null @@ -1,19 +0,0 @@ -desc 'Generate documentation for the ResourceController plugin.' -Rake::RDocTask.new(:rdoc) do |rdoc| - rdoc.rdoc_dir = 'rdoc' - rdoc.title = 'ActivePresenter' - rdoc.options << '--line-numbers' << '--inline-source' - rdoc.rdoc_files.include('README') - rdoc.rdoc_files.include('lib/**/*.rb') -end - -task :upload_docs => :rdoc do - puts 'Deleting previous rdoc' - `ssh jamesgolick.com 'rm -Rf /home/apps/jamesgolick.com/public/active_presenter/rdoc'` - - puts "Uploading current rdoc" - `scp -r rdoc jamesgolick.com:/home/apps/jamesgolick.com/public/active_presenter/rdoc` - - puts "Deleting rdoc" - `rm -Rf rdoc` -end diff --git a/lib/tasks/gem.rake b/lib/tasks/gem.rake deleted file mode 100644 index c7136d5..0000000 --- a/lib/tasks/gem.rake +++ /dev/null @@ -1,62 +0,0 @@ -require 'rake/gempackagetask' - -task :clean => :clobber_package - -spec = Gem::Specification.new do |s| - s.name = ActivePresenter::NAME - s.version = ActivePresenter::Version::STRING - s.summary = - s.description = "ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)" - s.author = "James Golick & Daniel Haran" - s.email = 'james@giraffesoft.ca' - s.homepage = 'http://jamesgolick.com/active_presenter' - s.rubyforge_project = 'active_presenter' - s.has_rdoc = true - - s.required_ruby_version = '>= 1.8.5' - - s.files = %w(README LICENSE Rakefile) + - Dir.glob("{lib,test}/**/*") - - s.require_path = "lib" -end - -Rake::GemPackageTask.new(spec) do |p| - p.gem_spec = spec -end - -task :tag_warn do - puts "*" * 40 - puts "Don't forget to tag the release:" - puts - puts " git tag -a v#{ActivePresenter::Version::STRING}" - puts - puts "or run rake tag" - puts "*" * 40 -end - -task :tag do - sh "git tag -a v#{ActivePresenter::Version::STRING}" -end -task :gem => :tag_warn - -namespace :gem do - namespace :upload do - - desc 'Upload gems (ruby & win32) to rubyforge.org' - task :rubyforge => :gem do - sh 'rubyforge login' - sh "rubyforge add_release giraffesoft active_presenter #{ActivePresenter::Version::STRING} pkg/#{spec.full_name}.gem" - sh "rubyforge add_file giraffesoft active_presenter #{ActivePresenter::Version::STRING} pkg/#{spec.full_name}.gem" - end - - end -end - -task :install => [:clobber, :package] do - sh "sudo gem install pkg/#{spec.full_name}.gem" -end - -task :uninstall => :clean do - sh "sudo gem uninstall -v #{ActivePresenter::Version::STRING} -x #{ActivePresenter::NAME}" -end From f28868d3fa7aa5fb49559d7bc6b1ac8ece1cb595 Mon Sep 17 00:00:00 2001 From: Igor Galeta Date: Wed, 11 Aug 2010 17:41:17 +0300 Subject: [PATCH 4/8] Fix issue undefined method valid? for nil:NilClass --- lib/active_presenter/base.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/active_presenter/base.rb b/lib/active_presenter/base.rb index 7f540ba..f82faa1 100644 --- a/lib/active_presenter/base.rb +++ b/lib/active_presenter/base.rb @@ -142,8 +142,8 @@ def valid? validated = false errors.clear result = _run_validation_callbacks do - presented.keys.each do |type| - presented_inst = send(type) + presented.each do |type, klass| + presented_inst = send(type) || klass.new next unless save?(type, presented_inst) merge_errors(presented_inst, type) unless presented_inst.valid? end From 770a94259d6593aeb47481ab5a9a485a8e128218 Mon Sep 17 00:00:00 2001 From: Igor Galeta Date: Wed, 11 Aug 2010 17:45:51 +0300 Subject: [PATCH 5/8] Bump version --- active_presenter.gemspec | 2 +- lib/active_presenter/base.rb | 2 +- lib/active_presenter/version.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/active_presenter.gemspec b/active_presenter.gemspec index 0bce5d6..0a37bcd 100644 --- a/active_presenter.gemspec +++ b/active_presenter.gemspec @@ -5,7 +5,7 @@ Gem::Specification.new do |s| s.name = %q{active_presenter} - s.version = "1.3.0" + s.version = "1.3.1" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["James Golick", "Daniel Haran", "Igor Galeta"] diff --git a/lib/active_presenter/base.rb b/lib/active_presenter/base.rb index f82faa1..a37e06c 100644 --- a/lib/active_presenter/base.rb +++ b/lib/active_presenter/base.rb @@ -143,7 +143,7 @@ def valid? errors.clear result = _run_validation_callbacks do presented.each do |type, klass| - presented_inst = send(type) || klass.new + presented_inst = (send(type) || klass.new) next unless save?(type, presented_inst) merge_errors(presented_inst, type) unless presented_inst.valid? end diff --git a/lib/active_presenter/version.rb b/lib/active_presenter/version.rb index 7679ab0..2e3176e 100644 --- a/lib/active_presenter/version.rb +++ b/lib/active_presenter/version.rb @@ -2,7 +2,7 @@ module ActivePresenter module Version MAJOR = 1 MINOR = 3 - TINY = 0 + TINY = 1 STRING = [MAJOR, MINOR, TINY].join('.') end From d65c339c4432cb1594470a431d1cd465a5717ada Mon Sep 17 00:00:00 2001 From: Matt Huggins Date: Tue, 3 May 2011 22:53:59 -0500 Subject: [PATCH 6/8] Allow hash to be passed to save and save! methods, similar to ActiveRecord --- lib/active_presenter/base.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/active_presenter/base.rb b/lib/active_presenter/base.rb index a37e06c..756ff84 100644 --- a/lib/active_presenter/base.rb +++ b/lib/active_presenter/base.rb @@ -161,10 +161,10 @@ def changed? # # Returns true or false based on success. # - def save + def save(options={}) saved = false ActiveRecord::Base.transaction do - if valid? + if !perform_validations?(options) || (perform_validations?(options) && valid?) _run_save_callbacks do saved = presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save} raise ActiveRecord::Rollback unless saved @@ -178,10 +178,10 @@ def save # # Returns true on success, will raise otherwise. # - def save! + def save!(options={}) saved = false ActiveRecord::Base.transaction do - raise ActiveRecord::RecordInvalid.new(self) unless valid? + raise ActiveRecord::RecordInvalid.new(self) if perform_validations?(options) && !valid? _run_save_callbacks do presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save!} saved = true @@ -274,5 +274,9 @@ def attribute_protected?(name) flat_attribute = {flatten_attribute_name(name, presentable) => ''} presented[presentable].new.send(:sanitize_for_mass_assignment, flat_attribute).empty? end + + def perform_validations?(options={}) + options[:validate] != false + end end end From d3c9f59f7df12baadae3816fea9d8391d4547933 Mon Sep 17 00:00:00 2001 From: Igor Galeta Date: Thu, 20 Oct 2011 20:05:50 +0300 Subject: [PATCH 7/8] Update gemspec and version --- Rakefile | 20 ------------ active_presenter.gemspec | 56 ++++++++++----------------------- lib/active_presenter/version.rb | 9 ++---- 3 files changed, 18 insertions(+), 67 deletions(-) diff --git a/Rakefile b/Rakefile index f0b0892..700871f 100644 --- a/Rakefile +++ b/Rakefile @@ -2,7 +2,6 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask' -require File.join(File.dirname(__FILE__), 'lib', 'active_presenter', 'version') desc 'Default: run unit tests.' task :default => :test @@ -23,22 +22,3 @@ Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_files.include('README') rdoc.rdoc_files.include('lib/**/*.rb') end - -begin - require 'jeweler' - Jeweler::Tasks.new do |gemspec| - gemspec.name = "active_presenter" - gemspec.version = ActivePresenter::Version::STRING - gemspec.summary = "ActivePresenter is the presenter library" - gemspec.description = "ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)" - gemspec.email = "james@giraffesoft.ca" - gemspec.homepage = "git://github.com/galetahub/freeberry.git" - gemspec.authors = ["James Golick", "Daniel Haran", "Igor Galeta"] - gemspec.files = FileList["[A-Z]*", "{lib}/**/*"] - gemspec.rubyforge_project = "active_presenter" - end - - Jeweler::GemcutterTasks.new -rescue LoadError - puts "Jeweler not available. Install it with: gem install jeweler" -end diff --git a/active_presenter.gemspec b/active_presenter.gemspec index 0a37bcd..82d6c65 100644 --- a/active_presenter.gemspec +++ b/active_presenter.gemspec @@ -1,46 +1,22 @@ -# Generated by jeweler -# DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command # -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "active_presenter/version" Gem::Specification.new do |s| - s.name = %q{active_presenter} - s.version = "1.3.1" - - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.name = "galetahub-active_presenter" + s.version = ActivePresenter::VERSION.dup + s.platform = Gem::Platform::RUBY + s.summary = "ActivePresenter is the presenter library" + s.description = "ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)" s.authors = ["James Golick", "Daniel Haran", "Igor Galeta"] - s.date = %q{2010-08-11} - s.description = %q{ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)} - s.email = %q{james@giraffesoft.ca} - s.extra_rdoc_files = [ - "README.rdoc" - ] - s.files = [ - "README.rdoc", - "Rakefile", - "lib/active_presenter.rb", - "lib/active_presenter/base.rb", - "lib/active_presenter/version.rb" - ] - s.homepage = %q{git://github.com/galetahub/freeberry.git} - s.rdoc_options = ["--charset=UTF-8"] + s.email = "galeta.igor@gmail.com" + s.rubyforge_project = "active_presenter" + s.homepage = "https://github.com/galetahub/active_presenter" + + s.files = Dir["{app,lib}/**/*"] + ["Rakefile", "README.rdoc"] + s.test_files = Dir["{test}/**/*"] + s.extra_rdoc_files = ["README.rdoc"] s.require_paths = ["lib"] - s.rubyforge_project = %q{active_presenter} - s.rubygems_version = %q{1.3.7} - s.summary = %q{ActivePresenter is the presenter library} - s.test_files = [ - "test/base_test.rb", - "test/test_helper.rb" - ] - - if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - s.specification_version = 3 - - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - else - end - else - end + + s.add_dependency("activerecord", ">= 0") end - diff --git a/lib/active_presenter/version.rb b/lib/active_presenter/version.rb index 2e3176e..5c48de7 100644 --- a/lib/active_presenter/version.rb +++ b/lib/active_presenter/version.rb @@ -1,9 +1,4 @@ +# encoding: utf-8 module ActivePresenter - module Version - MAJOR = 1 - MINOR = 3 - TINY = 1 - - STRING = [MAJOR, MINOR, TINY].join('.') - end + VERSION = "0.1.0".freeze end From 9d7e438966933a7ee40a0b27a3ce086a81a400db Mon Sep 17 00:00:00 2001 From: Marco Cosentino Date: Fri, 21 Oct 2011 19:44:41 +0200 Subject: [PATCH 8/8] Added column_for_attribute to the presenter --- lib/active_presenter/base.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/active_presenter/base.rb b/lib/active_presenter/base.rb index 756ff84..aa6caa2 100644 --- a/lib/active_presenter/base.rb +++ b/lib/active_presenter/base.rb @@ -228,6 +228,13 @@ def persisted? presented_instances.map(&:persisted?).all? end + def column_for_attribute(attr) + p = presentable_for(attr) + return nil unless p + send(p).send(:column_for_attribute, flatten_attribute_name(attr,p)) + end + + protected def presented_instances presented.keys.map { |key| send(key) }