ruport 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +13 -4
- data/CHANGELOG +15 -1
- data/Rakefile +1 -1
- data/bin/rope +5 -1
- data/examples/basic_grouping.rb +13 -3
- data/examples/latex_table.rb +17 -0
- data/examples/line_graph_report.rb +23 -0
- data/examples/line_graph_report.rb.rej +15 -0
- data/examples/line_graph_report.rb~ +23 -0
- data/examples/line_plotter.rb +1 -0
- data/examples/sql_erb.rb +20 -0
- data/examples/template.rb +1 -1
- data/examples/text_processors.rb +3 -9
- data/lib/ruport.rb +2 -3
- data/lib/ruport.rb~ +69 -0
- data/lib/ruport/attempt.rb +63 -0
- data/lib/ruport/data.rb +1 -1
- data/lib/ruport/data.rb.rej +5 -0
- data/lib/ruport/data.rb~ +1 -0
- data/lib/ruport/data/groupable.rb +20 -0
- data/lib/ruport/data/record.rb +18 -13
- data/lib/ruport/data/table.rb +92 -26
- data/lib/ruport/data/table.rb~ +329 -0
- data/lib/ruport/format.rb +7 -1
- data/lib/ruport/format/engine/table.rb +2 -1
- data/lib/ruport/format/plugin.rb +8 -8
- data/lib/ruport/format/plugin/csv_plugin.rb +5 -1
- data/lib/ruport/format/plugin/html_plugin.rb +12 -8
- data/lib/ruport/format/plugin/latex_plugin.rb +50 -0
- data/lib/ruport/format/plugin/text_plugin.rb +38 -33
- data/lib/ruport/meta_tools.rb +3 -3
- data/lib/ruport/query.rb +21 -9
- data/lib/ruport/report.rb +35 -20
- data/lib/ruport/report/graph.rb +14 -0
- data/lib/ruport/system_extensions.rb +9 -8
- data/test/_test_groupable.rb +0 -0
- data/test/samples/data.tsv +3 -0
- data/test/samples/erb_test.sql +1 -0
- data/test/samples/query_test.sql +1 -0
- data/test/test_collection.rb +1 -1
- data/test/test_format.rb +1 -1
- data/test/test_format_engine.rb +17 -0
- data/test/test_groupable.rb +41 -0
- data/test/test_invoice.rb +1 -1
- data/test/test_latex.rb +20 -0
- data/test/test_plugin.rb +59 -29
- data/test/test_query.rb +12 -6
- data/test/test_record.rb +23 -4
- data/test/test_record.rb.rej +46 -0
- data/test/test_report.rb +32 -7
- data/test/test_table.rb +152 -4
- data/test/ts_all.rb +21 -0
- data/test/unit.log +61 -154
- metadata +32 -12
- data/lib/ruport/rails.rb +0 -2
- data/lib/ruport/rails/reportable.rb +0 -58
data/AUTHORS
CHANGED
@@ -8,17 +8,26 @@
|
|
8
8
|
= Contributors / People we've (legally) stolen from:
|
9
9
|
|
10
10
|
Iain Broadfoot:
|
11
|
-
- RuportDay 2006 Participant
|
11
|
+
- RuportDay 2006 Participant
|
12
12
|
|
13
13
|
Eric Pugh:
|
14
|
-
- RuportDay 2006 Participant
|
14
|
+
- RuportDay 2006 Participant
|
15
15
|
|
16
16
|
James Edward Gray II:
|
17
17
|
- Original inspiration via query.rb
|
18
18
|
- system_extensions.rb
|
19
19
|
|
20
|
+
Mathijs Mohlmann:
|
21
|
+
- Performance Enhancement
|
22
|
+
TextPlugin r264-r265
|
23
|
+
HTMLPlugin r266
|
24
|
+
|
20
25
|
Francis Hwang:
|
21
|
-
- SQLSplit
|
26
|
+
- SQLSplit
|
22
27
|
|
23
28
|
Simon Claret:
|
24
|
-
- Initial PDF table support (now deprecated)
|
29
|
+
- Initial PDF table support (now deprecated)
|
30
|
+
|
31
|
+
Daniel Berger:
|
32
|
+
- we vendored and modified attempt.rb to support it directly in Report.
|
33
|
+
Original website: http://raa.ruby-lang.org/project/attempt/
|
data/CHANGELOG
CHANGED
@@ -1,4 +1,18 @@
|
|
1
|
-
|
1
|
+
The current version of Ruby Reports is 0.6.0
|
2
|
+
|
3
|
+
changes since 0.5.4
|
4
|
+
|
5
|
+
From Ruport News (http://www.stonecode.org/blog/?cat=14)
|
6
|
+
|
7
|
+
* added ERb support inside SQL queries
|
8
|
+
* a new LaTeX plugin for the table formatting engine
|
9
|
+
* support for summation in data tables
|
10
|
+
* new grouping functionality based on the tagging system
|
11
|
+
* very large performance enhancements in HTML and text rendering
|
12
|
+
* better integration with FasterCSV
|
13
|
+
* some simple interfaces for graphs and data tables
|
14
|
+
* syntactic sugar (shortcuts) for common tasks
|
15
|
+
* support for rerunning reports on timeouts and errors
|
2
16
|
|
3
17
|
changes since 0.5.3
|
4
18
|
|
data/Rakefile
CHANGED
@@ -23,7 +23,7 @@ end
|
|
23
23
|
|
24
24
|
spec = Gem::Specification.new do |spec|
|
25
25
|
spec.name = LEAN ? "lean-ruport" : "ruport"
|
26
|
-
spec.version = "0.
|
26
|
+
spec.version = "0.6.0"
|
27
27
|
spec.platform = Gem::Platform::RUBY
|
28
28
|
spec.summary = "A generalized Ruby report generation and templating engine."
|
29
29
|
spec.files = Dir.glob("{examples,lib,test,bin}/**/**/**/*") +
|
data/bin/rope
CHANGED
@@ -68,7 +68,11 @@ class #{class_name} < Ruport::Report
|
|
68
68
|
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
# uncomment the line below to let the report be run directly
|
72
|
+
#
|
73
|
+
# if __FILE__ == $0
|
74
|
+
# #{class_name}.run { |res| puts res.results }
|
75
|
+
# end
|
72
76
|
EOR
|
73
77
|
|
74
78
|
TEST = <<EOR
|
data/examples/basic_grouping.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
require "ruport"
|
2
2
|
a = [ ['a',7],['b',5],['c',11],
|
3
|
-
['d',9],['a',3],['b',2] ].to_table(%w[letter num])
|
3
|
+
['d',9],['a',3],['b',2], ['e',4] ].to_table(%w[letter num])
|
4
4
|
puts "Initial Data:\n#{a}"
|
5
|
+
|
6
|
+
|
7
|
+
# group by column values
|
5
8
|
b = a.split(:group => "letter")
|
6
9
|
totals = [].to_table(%w[group sum])
|
7
|
-
b.
|
8
|
-
puts "After grouping:\n#{totals}"
|
10
|
+
b.each_group { |x| totals << [x,b[x].sum("num")] }
|
11
|
+
puts "After column grouping:\n#{totals}"
|
9
12
|
|
13
|
+
# group by tag name
|
14
|
+
a.create_tag_group(:num_even) { |r| (r.num % 2).zero? }
|
15
|
+
a.create_tag_group(:num_odd) { |r| (r.num % 2).nonzero? }
|
16
|
+
c = a.group_by_tag
|
17
|
+
totals.data.clear
|
18
|
+
c.each_group { |x| totals << [x,c[x].sum("num")] }
|
19
|
+
puts "After tag grouping:\n#{totals}"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + "/../lib/")
|
2
|
+
require "ruport"
|
3
|
+
|
4
|
+
# build up a Table - this could be built in a range of ways
|
5
|
+
# Check the API documentation and recipe book for more information
|
6
|
+
data = [[1,4,7,9], [6,2,3,0]].to_table(%w[a b c d])
|
7
|
+
|
8
|
+
# Build the report object
|
9
|
+
report = Ruport::Format.table_object(:plugin => :latex, :data => data)
|
10
|
+
|
11
|
+
# By default, the latex plugin will return plain text latex source
|
12
|
+
# changing the format option asks Ruport to attempt to render
|
13
|
+
# the source into a PDF using pdflatex
|
14
|
+
report.options = { :format => :pdf }
|
15
|
+
|
16
|
+
# save the resulting report to a file on the filesystem
|
17
|
+
File.open( "table.tex","w") { |f| f.puts report.render }
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "ruport"
|
2
|
+
class GraphSample < Ruport::Report
|
3
|
+
|
4
|
+
include Graph
|
5
|
+
|
6
|
+
prepare do
|
7
|
+
@data = [[5,7,9,12,14,16,18]].to_table(%w[jan feb mar apr may jun jul])
|
8
|
+
end
|
9
|
+
|
10
|
+
generate do
|
11
|
+
render_graph do |g|
|
12
|
+
g.data = @data
|
13
|
+
g.width = 700
|
14
|
+
g.height = 500
|
15
|
+
g.title = "A Simple Line Graph"
|
16
|
+
g.style = :line
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
GraphSample.run { |r| puts r.results }
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "ruport"
|
2
|
+
class GraphSample < Ruport::Report
|
3
|
+
|
4
|
+
include Graph
|
5
|
+
|
6
|
+
prepare do
|
7
|
+
@data = [[5,7,9,12,14,16,18]].to_table(%w[jan feb mar apr may jun jul])
|
8
|
+
end
|
9
|
+
|
10
|
+
generate do
|
11
|
+
render_graph do |g|
|
12
|
+
g.data = @data
|
13
|
+
g.width = 700
|
14
|
+
g.height = 500
|
15
|
+
g.title = "A Simple Line Graph"
|
16
|
+
g.style = :line
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
GraphSample.run { |r| puts r.results }
|
22
|
+
|
23
|
+
|
data/examples/line_plotter.rb
CHANGED
data/examples/sql_erb.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "ruport"
|
2
|
+
require "rubygems"
|
3
|
+
|
4
|
+
class Foo < Ruport::Report
|
5
|
+
|
6
|
+
SQL = "select * from <%= helper %>"
|
7
|
+
|
8
|
+
prepare do
|
9
|
+
source :default, :dsn => "dbi:mysql:foo", :user => "root"
|
10
|
+
end
|
11
|
+
|
12
|
+
generate do
|
13
|
+
query(SQL)
|
14
|
+
end
|
15
|
+
|
16
|
+
def helper; "bar" end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
Foo.run { |r| puts r.results }
|
data/examples/template.rb
CHANGED
data/examples/text_processors.rb
CHANGED
@@ -3,17 +3,11 @@ require "ruport"
|
|
3
3
|
class MyReport < Ruport::Report
|
4
4
|
prepare {
|
5
5
|
self.results = "Foo Bar Baz"
|
6
|
-
text_processor(:replace_foo) {
|
7
|
-
text_processor(:replace_bar) {
|
8
|
-
text_processor(:replace_baz) {
|
6
|
+
text_processor(:replace_foo) { |r| r.gsub(/Foo/,"Ruport") }
|
7
|
+
text_processor(:replace_bar) { |r| r.gsub(/Bar/,"Is") }
|
8
|
+
text_processor(:replace_baz) { |r| r.gsub(/Baz/, "Cool!") }
|
9
9
|
}
|
10
10
|
generate {
|
11
11
|
process_text results, :filters => [:replace_foo,:replace_bar,:replace_baz]
|
12
12
|
}
|
13
13
|
end
|
14
|
-
|
15
|
-
MyReport.run { |e| puts e.results }
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
data/lib/ruport.rb
CHANGED
@@ -9,10 +9,9 @@
|
|
9
9
|
#
|
10
10
|
# See LICENSE and COPYING for details
|
11
11
|
#
|
12
|
-
|
13
12
|
module Ruport
|
14
13
|
|
15
|
-
VERSION = "0.
|
14
|
+
VERSION = "0.6.0"
|
16
15
|
|
17
16
|
# Ruports logging and error interface.
|
18
17
|
# Can generate warnings or raise fatal errors
|
@@ -65,6 +64,6 @@ module Ruport
|
|
65
64
|
end
|
66
65
|
|
67
66
|
|
68
|
-
%w[config meta_tools report format query
|
67
|
+
%w[attempt config data meta_tools report format query mailer].each { |lib|
|
69
68
|
require "ruport/#{lib}"
|
70
69
|
}
|
data/lib/ruport.rb~
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# ruport.rb : Ruby Reports toplevel module
|
2
|
+
#
|
3
|
+
# Author: Gregory T. Brown (gregory.t.brown at gmail dot com)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006, All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. You may modify and redistribute this freely under
|
8
|
+
# your choice of the GNU General Public License or the Ruby License.
|
9
|
+
#
|
10
|
+
# See LICENSE and COPYING for details
|
11
|
+
#
|
12
|
+
module Ruport
|
13
|
+
|
14
|
+
VERSION = "0.6.0"
|
15
|
+
|
16
|
+
# Ruports logging and error interface.
|
17
|
+
# Can generate warnings or raise fatal errors
|
18
|
+
#
|
19
|
+
# Takes a message to display and a set of options.
|
20
|
+
# Will log to the file defined by Config::log_file
|
21
|
+
#
|
22
|
+
# Options:
|
23
|
+
# <tt>:status</tt>:: sets the severity level. defaults to <tt>:warn</tt>
|
24
|
+
# <tt>:output</tt>:: optional 2nd output, defaults to <tt>$stderr</tt>
|
25
|
+
# <tt>:level</tt>:: set to <tt>:log_only</tt> to disable secondary output
|
26
|
+
# <tt>:exception</tt>:: exception to throw on fail. Defaults to RunTimeError
|
27
|
+
#
|
28
|
+
# The status <tt>:warn</tt> will invoke Logger#warn. A status of
|
29
|
+
# <tt>:fatal</tt> will invoke Logger#fatal and raise an exception
|
30
|
+
#
|
31
|
+
# By default, <tt>log()</tt> will also print warnings to $stderr
|
32
|
+
# You can redirect this to any I/O object via <tt>:output</tt>
|
33
|
+
#
|
34
|
+
# You can prevent messages from appearing on the secondary output by setting
|
35
|
+
# <tt>:level</tt> to <tt>:log_only</tt>
|
36
|
+
#
|
37
|
+
# If you want to recover these messages to secondary output for debugging, you
|
38
|
+
# can use Config::enable_paranoia
|
39
|
+
def self.log(message,options={})
|
40
|
+
options = {:status => :warn, :output => $stderr}.merge(options)
|
41
|
+
options[:output].puts "[!!] #{message}" unless
|
42
|
+
options[:level].eql?(:log_only) and not Ruport::Config.paranoid?
|
43
|
+
Ruport::Config::logger.send(options[:status],message) if Config.logger
|
44
|
+
if options[:status].eql? :fatal
|
45
|
+
raise(options[:exception] || RuntimeError, message)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#Alias for Ruport.log
|
50
|
+
def self.complain(*args); Ruport.log(*args) end
|
51
|
+
|
52
|
+
# yields a Ruport::Config object, allowing you to specify configuration
|
53
|
+
# options.
|
54
|
+
#
|
55
|
+
# Example:
|
56
|
+
#
|
57
|
+
# Ruport.configure do |c|
|
58
|
+
# c.source :default, :dsn => "dbi:mysql:foo",
|
59
|
+
# :user => "clyde", :password => "pman"
|
60
|
+
# end
|
61
|
+
def self.configure(&block)
|
62
|
+
block.call(Ruport::Config)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
%w[attempt config meta_tools report format query data mailer].each { |lib|
|
68
|
+
require "ruport/#{lib}"
|
69
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
class Attempt
|
4
|
+
VERSION = '0.1.0'
|
5
|
+
|
6
|
+
# Number of attempts to make before failing. The default is 3.
|
7
|
+
attr_accessor :tries
|
8
|
+
|
9
|
+
# Number of seconds to wait between attempts. The default is 60.
|
10
|
+
attr_accessor :interval
|
11
|
+
|
12
|
+
# a level which ruport understands.
|
13
|
+
attr_accessor :log_level
|
14
|
+
|
15
|
+
# If set, this increments the interval with each failed attempt by that
|
16
|
+
# number of seconds.
|
17
|
+
attr_accessor :increment
|
18
|
+
|
19
|
+
# If set, the code block is further wrapped in a timeout block.
|
20
|
+
attr_accessor :timeout
|
21
|
+
|
22
|
+
# Determines which exception level to check when looking for errors to
|
23
|
+
# retry. The default is 'Exception' (i.e. all errors).
|
24
|
+
attr_accessor :level
|
25
|
+
|
26
|
+
# :call-seq:
|
27
|
+
# Attempt.new{ |a| ... }
|
28
|
+
#
|
29
|
+
# Creates and returns a new +Attempt+ object. Use a block to set the
|
30
|
+
# accessors.
|
31
|
+
#
|
32
|
+
def initialize
|
33
|
+
@tries = 3 # Reasonable default
|
34
|
+
@interval = 60 # Reasonable default
|
35
|
+
@increment = nil # Should be an int, if provided
|
36
|
+
@timeout = nil # Wrap the code in a timeout block if provided
|
37
|
+
@level = Exception # Level of exception to be caught
|
38
|
+
|
39
|
+
yield self if block_given?
|
40
|
+
end
|
41
|
+
|
42
|
+
def attempt
|
43
|
+
count = 1
|
44
|
+
begin
|
45
|
+
if @timeout
|
46
|
+
Timeout.timeout(@timeout){ yield }
|
47
|
+
else
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
rescue @level => error
|
51
|
+
@tries -= 1
|
52
|
+
if @tries > 0
|
53
|
+
msg = "Error on attempt # #{count}: #{error}; retrying"
|
54
|
+
count += 1
|
55
|
+
Ruport.log(msg, :level => log_level)
|
56
|
+
@interval += @increment if @increment
|
57
|
+
sleep @interval
|
58
|
+
retry
|
59
|
+
end
|
60
|
+
raise
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/ruport/data.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
%w[taggable record collection table set].each { |l| require "ruport/data/#{l}" }
|
1
|
+
%w[groupable taggable record collection table set ].each { |l| require "ruport/data/#{l}" }
|
data/lib/ruport/data.rb~
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
%w[taggable record collection table set groupable].each { |l| require "ruport/data/#{l}" }
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ruport::Data
|
2
|
+
module Groupable
|
3
|
+
|
4
|
+
def group_by_tag
|
5
|
+
r_tags = data.map {|row| row.tags}.flatten.uniq
|
6
|
+
d = r_tags.map do |t|
|
7
|
+
select {|row| row.tags.include? t }.to_table(column_names)
|
8
|
+
end
|
9
|
+
r = Record.new d, :attributes => r_tags
|
10
|
+
class << r
|
11
|
+
def each_group; attributes.each { |a| yield(a) }; end
|
12
|
+
end; r
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_tag_group(label,&block)
|
16
|
+
select(&block).each { |r| r.tag label }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/lib/ruport/data/record.rb
CHANGED
@@ -47,7 +47,11 @@ module Ruport::Data
|
|
47
47
|
end
|
48
48
|
else
|
49
49
|
@data = data.dup
|
50
|
-
@attributes = options[:attributes]
|
50
|
+
@attributes = if options[:attributes]
|
51
|
+
options[:attributes]
|
52
|
+
else
|
53
|
+
[]
|
54
|
+
end
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
@@ -68,8 +72,8 @@ module Ruport::Data
|
|
68
72
|
raise "Invalid index" unless index < @data.length
|
69
73
|
@data[index]
|
70
74
|
else
|
71
|
-
raise "Invalid index" unless
|
72
|
-
@data[
|
75
|
+
raise "Invalid index" unless attributes.index(index.to_s)
|
76
|
+
@data[attributes.index(index.to_s)]
|
73
77
|
end
|
74
78
|
end
|
75
79
|
|
@@ -86,8 +90,8 @@ module Ruport::Data
|
|
86
90
|
raise "Invalid index" unless index < @data.length
|
87
91
|
@data[index] = value
|
88
92
|
else
|
89
|
-
raise "Invalid index" unless
|
90
|
-
@data[attributes.index(index)] = value
|
93
|
+
raise "Invalid index" unless attributes.index(index.to_s)
|
94
|
+
@data[attributes.index(index.to_s)] = value
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
@@ -95,9 +99,9 @@ module Ruport::Data
|
|
95
99
|
# If attributes and data are equivalent, then == evaluates to true.
|
96
100
|
# Otherwise, == returns false
|
97
101
|
def ==(other)
|
98
|
-
return false if
|
99
|
-
return false if other.attributes &&
|
100
|
-
|
102
|
+
return false if attributes && !other.attributes
|
103
|
+
return false if other.attributes && !attributes
|
104
|
+
attributes == other.attributes && @data == other.data
|
101
105
|
end
|
102
106
|
|
103
107
|
alias_method :eql?, :==
|
@@ -113,19 +117,20 @@ module Ruport::Data
|
|
113
117
|
#
|
114
118
|
# a = Data::Record.new([1,2],:attributes => %w[a b])
|
115
119
|
# a.to_h #=> {"a" => 1, "b" => 2}
|
116
|
-
def to_h; Hash[
|
120
|
+
def to_h; Hash[*attributes.zip(data).flatten] end
|
117
121
|
|
118
122
|
# Returns a copy of the list of attribute names associated with this Record.
|
119
123
|
#
|
120
124
|
# a = Data::Record.new([1,2],:attributes => %w[a b])
|
121
125
|
# a.attributes #=> ["a","b"]
|
122
|
-
def attributes; @attributes
|
126
|
+
def attributes; @attributes.map { |a| a.to_s }; end
|
123
127
|
|
124
128
|
# Sets the attribute list for this Record
|
125
129
|
#
|
126
130
|
# my_record.attributes = %w[foo bar baz]
|
127
131
|
attr_writer :attributes
|
128
132
|
|
133
|
+
|
129
134
|
# Allows you to change the order of or reduce the number of columns in a
|
130
135
|
# Record. Example:
|
131
136
|
#
|
@@ -140,9 +145,9 @@ module Ruport::Data
|
|
140
145
|
# Same as Record#reorder but is destructive
|
141
146
|
def reorder!(*indices)
|
142
147
|
indices = reorder_data!(*indices)
|
143
|
-
if
|
148
|
+
if attributes
|
144
149
|
if indices.all? { |e| e.kind_of? Integer }
|
145
|
-
@attributes = indices.map { |i|
|
150
|
+
@attributes = indices.map { |i| attributes[i] }
|
146
151
|
else
|
147
152
|
@attributes = indices
|
148
153
|
end
|
@@ -181,7 +186,7 @@ module Ruport::Data
|
|
181
186
|
# my_record.foo #=> 2
|
182
187
|
def method_missing(id,*args)
|
183
188
|
id = id.to_s.gsub(/=$/,"")
|
184
|
-
if
|
189
|
+
if attributes.include?(id)
|
185
190
|
args.empty? ? self[id] : self[id] = args.first
|
186
191
|
else
|
187
192
|
super
|