tag:blogger.com,1999:blog-49374887290222456452009-06-13T12:39:50.936-05:00Stochastic BytesChristopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-4937488729022245645.post-86396191665646373842009-04-22T22:12:00.001-05:002009-04-22T22:20:42.705-05:00Time, DateTime and to_yaml<p>This is interesting. If you convert an instance of DateTime to YAML and reload it using <tt>YAML.load</tt>, it comes back as an instance of Time, minus the fractional seconds.</p>
<script src="http://gist.github.com/100257.js"></script>
<p>Also, if you convert a DateTime to UTC then to a Time, it drops the fractional seconds. Converting a DateTime directly to a Time does NOT drop the fractional seconds, nor does converting a Time to UTC. Weird.</p>
<script src="http://gist.github.com/100273.js"></script>
<p>As you can see, I'm using ActiveSupport. I don't really know how much (or if any) that is affecting this weird behavior.</p>
<p>Heh, I don't really know if "fractional seconds" is proper terminology either.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-8639619166564637384?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com0tag:blogger.com,1999:blog-4937488729022245645.post-13184083491683493332008-07-20T18:23:00.001-05:002008-07-20T18:23:57.310-05:00eager loading + limit + order in named scope = ActiveRecord 2.1.0 bug<p>I found this bug while writing <a href="http://github.com/cjbottaro/paginate_izzle">my pagination plugin</a> that uses named scopes. It's caused by an oversight in <tt>construct_finder_sql_for_association_limiting</tt> and manifests when the following three conditions are met:</p>
<ul>
<li>there is a has_many association being eager loaded</li>
<li>the query is being limited</li>
<li>there is order specified by a named scope</li>
</ul>
<p>I fixed the bug by making modifications to <tt>construct_finder_sql_for_association_limiting</tt>. You can apply the fix by including the following code into your Rails project:</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby source_ruby_rails"><span class="meta meta_module meta_module_ruby"><span class="keyword keyword_control keyword_control_module keyword_control_module_ruby">module</span> <span class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby">ActiveRecord</span></span>
<span class="meta meta_module meta_module_ruby"> <span class="keyword keyword_control keyword_control_module keyword_control_module_ruby">module</span> <span class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby">Associations</span></span>
<span class="meta meta_module meta_module_ruby"> <span class="keyword keyword_control keyword_control_module keyword_control_module_ruby">module</span> <span class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby">ClassMethods</span></span>
<span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">construct_finder_sql_for_association_limiting</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> join_dependency</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
scope <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> scope<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>find</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{}</span>
order <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span>options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>order</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> scope<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>order</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]]</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>compact<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>join<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>, <span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"> <span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> Only join tables referenced in order or conditions since this is particularly slow on the pre-query.
</span> tables_from_conditions <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> conditions_tables<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>options<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
tables_from_order <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> order_tables<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>options<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
all_tables <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> tables_from_conditions <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">+</span> tables_from_order
distinct_join_associations <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> all_tables<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>uniq<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>map<span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span><span class="variable variable_other variable_other_block variable_other_block_ruby">table</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>
join_dependency<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>joins_for_table_name<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>table<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>flatten<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>compact<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>uniq
is_distinct <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">!</span>options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>joins</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>blank? <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> include_eager_conditions?<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> tables_from_conditions<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> include_eager_order?<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> tables_from_order<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
sql <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>SELECT <span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class="keyword keyword_control keyword_control_ruby">if</span> is_distinct
sql <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"><<</span> connection<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>distinct<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span><span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>connection<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>quote_table_name table_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>.<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>primary_key<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> order<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">else</span>
sql <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"><<</span> primary_key
<span class="keyword keyword_control keyword_control_ruby">end</span>
sql <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"><<</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span> FROM <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>connection<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>quote_table_name table_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span> <span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class="keyword keyword_control keyword_control_ruby">if</span> is_distinct
sql <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"><<</span> distinct_join_associations<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>collect<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">&</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>association_join</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>join
add_joins!<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>sql<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> scope<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
add_conditions!<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>sql<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>conditions</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> scope<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
add_group!<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>sql<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>group</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> scope<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">if</span> order <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">and</span> is_distinct
connection<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>add_order_by_for_association_limiting!<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>sql<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>order</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> order<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">else</span>
add_order!<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>sql<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>order</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> scope<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
add_limit!<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>sql<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> scope<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">return</span> sanitize_sql<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>sql<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="keyword keyword_control keyword_control_ruby">end</span></span></pre>
<br/>
<p>If you are curious about what exactly was changed, see <a href="http://pastie.org/237580">this diff pastie</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-1318408349168349333?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com1tag:blogger.com,1999:blog-4937488729022245645.post-18776513251723647632008-07-17T12:45:00.002-05:002008-07-17T12:47:03.726-05:00callback chains and metaclasses<p>For whatever reason (don't ask) our Rails app needed to be able to define callbacks on objects. As it stands now, you can only define callbacks on classes. Well, metaclasses are classes that pertain to a single specific object, so I figured I could add the callbacks there and everything will work.</p>
<p>Please excuse my <em>extremely</em> contrived example.</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby">p <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">Post</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>find<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">...</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">if</span> p<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>contains_porn?
<span class="meta meta_class meta_class_ruby"> <span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby"><span class="variable variable_other variable_other_object variable_other_object_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"><<</span> p</span></span></span>
before_save <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>filter_content</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
p<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>save <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> should trigger filter_content</span></span></pre>
<p>Well it doesn't work.</p>
<p>After digging through the ActiveSupport source code, I saw that it only looks for callback chains in the object's class, not metaclass. That's not too hard to fix...</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby"><span class="meta meta_module meta_module_ruby"><span class="keyword keyword_control keyword_control_module keyword_control_module_ruby">module</span> <span class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby">ActiveSupport</span></span>
<span class="meta meta_module meta_module_ruby"> <span class="keyword keyword_control keyword_control_module keyword_control_module_ruby">module</span> <span class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby">Callbacks</span></span>
<span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">run_callbacks</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">kind<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{}</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">&</span>block</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
callback_chain_method <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span><span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>kind<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>_callback_chain<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"> <span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> Meta class inherits Class so we don't have to merge it in 1.9
</span> <span class="keyword keyword_control keyword_control_ruby">if</span> <span class="variable variable_other variable_other_constant variable_other_constant_ruby">RUBY_VERSION</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby">>=</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>1.9<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span>
metaclass<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>send<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>callback_chain_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>run<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="variable variable_language variable_language_ruby">self</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">&</span>block<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">else</span>
callbacks <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="variable variable_language variable_language_ruby">self</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>class<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>send<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>callback_chain_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_operator keyword_operator_other keyword_operator_other_ruby">|</span> metaclass<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>send<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>callback_chain_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
callbacks<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>run<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="variable variable_language variable_language_ruby">self</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">&</span>block<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="keyword keyword_control keyword_control_ruby">end</span></span></pre>
<p>Credit to Josh Peek for the Ruby 1.9 fix</p>
<p>Ok, so that got it working... with <strong>one major caveat: you cannot serialize objects that use callbacks</strong>. Ruby cannot serialize objects that have metaclasses and the <tt>run_callbacks</tt> method creates a metaclass whether you use it or not.</p>
<p>That's fine with me, I don't really like serializing objects anyways, but apparently it's a major problem for other people...</p>
<p>
<a href="http://github.com/rails/rails/commit/e0846c8417093853f4f7f62732983e990c28d669">http://github.com/rails/rails/commit/e0846c8417093853f4f7f62732983e990c28d669</a>
<br/>
<a href="http://rails.lighthouseapp.com/projects/8994/tickets/575-callbacks-don-t-work-from-extended-modules">http://rails.lighthouseapp.com/projects/8994/tickets/575-callbacks-don-t-work-from-extended-modules</a>
</p>
<p>Josh Peek suggested a solution where we store the callback chains on the objects themselves, so object specific callbacks would be done like this...</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby">p <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">Post</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>find<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">...</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
p<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>before_save <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>filter_content</span> <span class="keyword keyword_control keyword_control_ruby">if</span> p<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>contains_porn?
p<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>save <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> should trigger filter_content</span></span></pre>
<p>That seems like a very simple, clean and rational solution. I'll look into coding it up later.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-1877651325172364763?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com0tag:blogger.com,1999:blog-4937488729022245645.post-60333012781622639342008-05-18T20:48:00.001-05:002008-05-18T20:48:15.977-05:00Metaprogramming Fun in Ruby<p>My friend, who is just learning Ruby, asked how he can automatically wrap some code around each user defined method in a class. The requirement (from his bosses) is to log when each method is being called. </p>
<p>To be more concrete, we want to factor out lines 3, 5, 9 and 11 from the following snippet.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_ruby"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">AutoLogger</span></span>
<span class='linenum'> 2</span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_a</span></span>
<span class='linenum'> 3</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>start logging method_a<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 4</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_a<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 5</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>end logging method_a<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 6</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 7</span>
<span class='linenum'> 8</span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_b</span></span>
<span class='linenum'> 9</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>start logging method_b<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 10</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_b<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 11</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>end logging method_b<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 12</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 13</span> <span class="keyword keyword_control keyword_control_ruby">end</span></span></pre>
<p>The problem really boils down to two problems. First, how to redefine a method to be the original method body wrapped between the logging code. Second, how do we specify which methods in a class should be wrapped.</p>
<p>Each solution (except for the first one) relies on using <tt>Module#define_method</tt> to redefine the method in question. Sometimes we pass in a block that defines the original method, other times we make an <tt>UnboundMethod</tt> out of the original method and call it from the block that makes the new method body, binding it to <tt>self</tt> which at execution time is an instance of our class.</p>
<p>My friend said ideally, he wants every "user defined" method to automatically be wrapped.</p>
<p>The first solution I came up with was using <tt>method_missing</tt>. This solution has the drawback of having to refactor all your code to call <tt>log_some_method</tt> instead of <tt>some_method</tt>.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_ruby source_ruby_rails"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">AutoLogger</span></span>
<span class='linenum'> 2</span>
<span class='linenum'> 3</span> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_missing</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">name<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">*</span>args</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 4</span> name <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> name<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>to_s
<span class='linenum'> 5</span> <span class="keyword keyword_control keyword_control_ruby">if</span> name<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_numeric constant_numeric_ruby">0</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span><span class="constant constant_numeric constant_numeric_ruby">4</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby">==</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>log_<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span>
<span class='linenum'> 6</span> method_name <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> name<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_numeric constant_numeric_ruby">4</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">..</span><span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">-</span><span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span>
<span class='linenum'> 7</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>start logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 8</span> <span class="variable variable_language variable_language_ruby">self</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>send<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>method_name<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>to_sym<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">*</span>args<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 9</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>end logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 10</span> <span class="keyword keyword_control keyword_control_ruby">else</span>
<span class='linenum'> 11</span> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">super</span>
<span class='linenum'> 12</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 13</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 14</span>
<span class='linenum'> 15</span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_a</span></span>
<span class='linenum'> 16</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_a<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 17</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 18</span>
<span class='linenum'> 19</span> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_b</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">arg1<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> arg2</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 20</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_b(<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg1<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>, <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg2<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>)<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 21</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 22</span>
<span class='linenum'> 23</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 24</span>
<span class='linenum'> 25</span> o <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">AutoLogger</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">new</span>
<span class='linenum'> 26</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_a
<span class='linenum'> 27</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_b<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>test<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 28</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>log_method_a
<span class='linenum'> 29</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>log_method_b<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>test<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 30</span>
<span class='linenum'> 31</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 32</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> OUTPUT #
</span><span class='linenum'> 33</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 34</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_a
</span><span class='linenum'> 35</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_b(test, 1)
</span><span class='linenum'> 36</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_a
</span><span class='linenum'> 37</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_a
</span><span class='linenum'> 38</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_a
</span><span class='linenum'> 39</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_b
</span><span class='linenum'> 40</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_b(test, 1)
</span><span class='linenum'> 41</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_b</span></span></pre>
<p>With this approach, you can see that the original methods are kept intact and are callable. You have to call the special prefixed version of them to get the logging.</p>
<p>The next solution uses a special method to define methods instead of the <tt>def</tt> keyword.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_ruby source_ruby_rails"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">AutoLogger</span></span>
<span class='linenum'> 2</span>
<span class='linenum'> 3</span> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">self.def_with_logging</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">method_name<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">&</span>block</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 4</span> define_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>method_name<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do </span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>*<span class="variable variable_other variable_other_block variable_other_block_ruby">args</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>
<span class='linenum'> 5</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>start logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 6</span> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">yield</span> <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">*</span>args
<span class='linenum'> 7</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>end logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 8</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 9</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 10</span>
<span class='linenum'> 11</span> def_with_logging<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>method_a</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do
</span><span class='linenum'> 12</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_a<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 13</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 14</span>
<span class='linenum'> 15</span> def_with_logging<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>method_b</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do </span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span><span class="variable variable_other variable_other_block variable_other_block_ruby">arg1</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">,</span> <span class="variable variable_other variable_other_block variable_other_block_ruby">arg2</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>
<span class='linenum'> 16</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_b(<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg1<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>, <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg2<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>)<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 17</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 18</span>
<span class='linenum'> 19</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 20</span>
<span class='linenum'> 21</span> o <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">AutoLogger</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">new</span>
<span class='linenum'> 22</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_a
<span class='linenum'> 23</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_b<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>test<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 24</span>
<span class='linenum'> 25</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 26</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> OUTPUT #
</span><span class='linenum'> 27</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 28</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_a
</span><span class='linenum'> 29</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_a
</span><span class='linenum'> 30</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_a
</span><span class='linenum'> 31</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_b
</span><span class='linenum'> 32</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_b(test, 1)
</span><span class='linenum'> 33</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_b</span></span></pre>
<p>Again, this solution requires the programmer to refactor a lot of existing code (rewriting all your methods using <tt>def_with_logging</tt> instead of <tt>def</tt>).</p>
<p>The third solution is more "Rails-like" by adding a method to the class itself which can be called to add logging to existing methods.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_ruby source_ruby_rails"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">AutoLogger</span></span>
<span class='linenum'> 2</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>inited</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="constant constant_language constant_language_ruby">false</span>
<span class='linenum'> 3</span>
<span class='linenum'> 4</span> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">self.do_logging_for</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby"><span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">*</span>method_names</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 5</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>method_names</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby">||=</span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[]</span>
<span class='linenum'> 6</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>method_names</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby">+=</span> method_names
<span class='linenum'> 7</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 8</span>
<span class='linenum'> 9</span> do_logging_for <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>method_a</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>method_b</span>
<span class='linenum'> 10</span>
<span class='linenum'> 11</span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">initialize</span></span>
<span class='linenum'> 12</span> <span class="keyword keyword_control keyword_control_ruby">unless</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>inited</span>
<span class='linenum'> 13</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>method_names</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>each <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do </span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span><span class="variable variable_other variable_other_block variable_other_block_ruby">method_name</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>
<span class='linenum'> 14</span> <span class="variable variable_language variable_language_ruby">self</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>class<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>class_eval <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do
</span><span class='linenum'> 15</span> method <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> instance_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>method_name<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 16</span> define_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>method_name<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do </span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>*<span class="variable variable_other variable_other_block variable_other_block_ruby">args</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>
<span class='linenum'> 17</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>start logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 18</span> method<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>bind<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="variable variable_language variable_language_ruby">self</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>call<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">*</span>args<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 19</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>end logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 20</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 21</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 22</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 23</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>inited</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="constant constant_language constant_language_ruby">true</span>
<span class='linenum'> 24</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 25</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 26</span>
<span class='linenum'> 27</span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_a</span></span>
<span class='linenum'> 28</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_a<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 29</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 30</span>
<span class='linenum'> 31</span> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_b</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">arg1<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> arg2</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 32</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_b(<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg1<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>, <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg2<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>)<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 33</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 34</span>
<span class='linenum'> 35</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 36</span>
<span class='linenum'> 37</span> o <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">AutoLogger</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">new</span>
<span class='linenum'> 38</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_a
<span class='linenum'> 39</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_b<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>test<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 40</span>
<span class='linenum'> 41</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 42</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> OUTPUT #
</span><span class='linenum'> 43</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 44</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_a
</span><span class='linenum'> 45</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_a
</span><span class='linenum'> 46</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_a
</span><span class='linenum'> 47</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_b
</span><span class='linenum'> 48</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_b(test, 1)
</span><span class='linenum'> 49</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_b</span></span></pre>
<p>Notice how most of the work is deferred to <tt>initialize</tt>. This is so we can call <tt>do_logging_for</tt> <em>before</em> we define the methods it works on.</p>
<p>The fourth approach takes the least work because it does not require the programmer to do anything special or extra to get the desired effect. It all happens automatically.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_ruby source_ruby_rails"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">AutoLogger</span></span>
<span class='linenum'> 2</span>
<span class='linenum'> 3</span> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">self.method_added</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">method_name</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 4</span>
<span class='linenum'> 5</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"> <span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> so we don't get stuck in infinite recursion
</span><span class='linenum'> 6</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>seen_methods</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby">||=</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{}</span>
<span class='linenum'> 7</span> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">return</span> <span class="keyword keyword_control keyword_control_ruby">if</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>seen_methods</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>has_key?<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>method_name<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 8</span> <span class="variable variable_other variable_other_readwrite variable_other_readwrite_class variable_other_readwrite_class_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">@@</span>seen_methods</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span>method_name<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="constant constant_language constant_language_ruby">true</span>
<span class='linenum'> 9</span>
<span class='linenum'> 10</span> method <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> instance_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>method_name<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 11</span> define_method<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>method_name<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do </span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>*<span class="variable variable_other variable_other_block variable_other_block_ruby">args</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span>
<span class='linenum'> 12</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>start logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 13</span> method<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>bind<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="variable variable_language variable_language_ruby">self</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>call<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">*</span>args<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 14</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>end logging <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>method_name<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 15</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 16</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 17</span>
<span class='linenum'> 18</span> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_a</span></span>
<span class='linenum'> 19</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_a<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 20</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 21</span>
<span class='linenum'> 22</span> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">method_b</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">arg1<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> arg2</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 23</span> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>calling method_b(<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg1<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>, <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>arg2<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>)<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 24</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 25</span>
<span class='linenum'> 26</span> <span class="keyword keyword_control keyword_control_ruby">end</span>
<span class='linenum'> 27</span>
<span class='linenum'> 28</span> o <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">AutoLogger</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">new</span>
<span class='linenum'> 29</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_a
<span class='linenum'> 30</span> o<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>method_b<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>test<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 31</span>
<span class='linenum'> 32</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 33</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> OUTPUT #
</span><span class='linenum'> 34</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span>#########
</span><span class='linenum'> 35</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_a
</span><span class='linenum'> 36</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_a
</span><span class='linenum'> 37</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_a
</span><span class='linenum'> 38</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> start logging method_b
</span><span class='linenum'> 39</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> calling method_b(test, 1)
</span><span class='linenum'> 40</span> <span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby">#</span> end logging method_b</span></span></pre>
<p><tt>Class#method_added</tt> is a callback that gets fired, well, when you think it does. The interesting thing to note here is that we can go into infinite recursion because of how we redefinite each method. When a method is a defined the callback is triggered, in the callback we re<em>define</em> the method which causes the callback to be triggered again.</p>
<p>That's it. Pretty neat what you can do with Ruby, huh?</p>
<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-6033301278162263934?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com1tag:blogger.com,1999:blog-4937488729022245645.post-86381493899343194752008-03-24T21:56:00.001-05:002008-05-18T21:13:54.344-05:00param_accessible<p>By popular (cue laughter) demand, I have added whitelisting to the popular (cue hysterical laughter) <a href="http://blog.stochasticbytes.com/2008/01/paramprotected.html"><tt>param_protected</tt> plugin</a>. It is done via the <tt>param_accessible</tt> method.</p>
<p>I have also added support to properly handle array params.</p>
<p>For more details (i.e. documentation), please see the <a href="http://www.stochasticbytes.com/doc/param_protected/README.html">README</a> file.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-8638149389934319475?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com3tag:blogger.com,1999:blog-4937488729022245645.post-14578771534787805852008-03-19T21:10:00.001-05:002008-05-18T21:24:13.306-05:00An HTML checkbox that submits when unchecked.<p>I call this... The Fake Checkbox! :)</p>
<p>See, the problem is a normal HTML checkbox only submits to the server when it's checked. If it's unchecked, nothing gets sent to the server. Sometimes I want a value (like, umm, false?) sent to the server whether it's checked or unchecked.</p>
<p>So how do we go about making a checkbox that does this? The idea is simple -- make a normal checkbox with Javascript attached to it that updates a hidden input field when checked or unchecked.</p>
<p>Making a Rails helper to do this is simple -- put this in <tt>application_helper.rb</tt>.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_ruby"><span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">fake_check_box_tag</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">name<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> checked_values<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> is_checked<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> html_options <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{}</span></span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span>
<span class='linenum'> 2</span> onchange <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> html_options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>onchange</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 3</span> checked_value <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> checked_values<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>checked</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>true<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span>
<span class='linenum'> 4</span> unchecked_value <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> checked_values<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>unchecked</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>false<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span>
<span class='linenum'> 5</span> unique_id <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> rand<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>to_s<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">-</span><span class="constant constant_numeric constant_numeric_ruby">5</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_numeric constant_numeric_ruby">5</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span>
<span class='linenum'> 6</span> poser_id <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>fake_check_box_poser_<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>unique_id<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 7</span> value_id <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>fake_check_box_value_<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>unique_id<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 8</span> onchange <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> onchange <span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby">+</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>; doFakeCheckBoxClick(this, <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>unique_id<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>, '<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>checked_value<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>', '<span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>unchecked_value<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span>')<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span>
<span class='linenum'> 9</span>
<span class='linenum'> 10</span> html_options<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>delete<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>object_id</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span>
<span class='linenum'> 11</span> html_options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>onchange</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> onchange
<span class='linenum'> 12</span> html_options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>id</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> poser_id
<span class='linenum'> 13</span>
<span class='linenum'> 14</span> html <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span>
<span class='linenum'> 15</span> html <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby">+=</span> hidden_field_tag name<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> is_checked <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby">?</span> checked_value <span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby">:</span> unchecked_value<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>id</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> value_id
<span class='linenum'> 16</span> html <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby">+=</span> check_box_tag <span class="constant constant_language constant_language_ruby">nil</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>true<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> is_checked<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> html_options
<span class='linenum'> 17</span> html
<span class='linenum'> 18</span> <span class="keyword keyword_control keyword_control_ruby">end</span></span></pre>
<p>Then you need to define this Javascript function.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_js"><span class="meta meta_function meta_function_js"><span class="storage storage_type storage_type_function storage_type_function_js">function</span> <span class="entity entity_name entity_name_function entity_name_function_js">doFakeCheckBoxClick</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_begin punctuation_definition_parameters_begin_js">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_js">me, unique_id, checked_value, unchecked_value</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_end punctuation_definition_parameters_end_js">)</span></span> <span class="meta meta_brace meta_brace_curly meta_brace_curly_js">{</span>
<span class='linenum'> 2</span> unique_id <span class="keyword keyword_operator keyword_operator_js">=</span> <span class="string string_quoted string_quoted_single string_quoted_single_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">'</span>fake_check_box_value_<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">'</span></span> <span class="keyword keyword_operator keyword_operator_js">+</span> unique_id
<span class='linenum'> 3</span> <span class="keyword keyword_control keyword_control_js">if</span> <span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span>me<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span><span class="support support_constant support_constant_dom support_constant_dom_js">checked</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span>
<span class='linenum'> 4</span> <span class="keyword keyword_operator keyword_operator_js">$</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span>unique_id<span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span><span class="support support_constant support_constant_dom support_constant_dom_js">value</span> <span class="keyword keyword_operator keyword_operator_js">=</span> checked_value<span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
<span class='linenum'> 5</span> <span class="keyword keyword_control keyword_control_js">else</span>
<span class='linenum'> 6</span> <span class="keyword keyword_operator keyword_operator_js">$</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span>unique_id<span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span><span class="support support_constant support_constant_dom support_constant_dom_js">value</span> <span class="keyword keyword_operator keyword_operator_js">=</span> unchecked_value<span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
<span class='linenum'> 7</span> <span class="meta meta_brace meta_brace_curly meta_brace_curly_js">}</span></span></pre>
<p>Now you can call it <del>just like</del> almost like the Rail's built in <tt>check_box_tag</tt> method.</p>
<pre class="textmate-source mac_classic"><span class='linenum'> 1</span> <span class="source source_ruby">fake_check_box_tag <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>person[is_female]<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span>
<span class='linenum'> 2</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"> </span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>checked</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>yes<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span>
<span class='linenum'> 3</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>unchecked</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>no<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span>
<span class='linenum'> 4</span> <span class="constant constant_language constant_language_ruby">true</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span>
<span class='linenum'> 5</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"> </span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>onchange</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>alert('checkbox clicked!')<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span></span></pre>
<p>In this example, if the checkbox is checked, the following will be true in your action:</p>
<p><tt>params[:person][:is_female] == 'yes'</tt></p>
<p>If it isn't checked, then this will be true:</p>
<p><tt>params[:person[:is_female] == 'no'</tt></p>
<p>The 3rd parameter (true) says that the checkbox will initially be checked.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-1457877153478780585?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com1tag:blogger.com,1999:blog-4937488729022245645.post-6497872856091818012008-01-21T18:49:00.000-06:002009-03-17T15:37:31.888-05:00Rail Plugin: param_protected<p>It is a Ruby on Rails plugin that provides <tt>param_protected</tt> and <tt>param_accessible</tt> methods on controllers analogous to the <tt>attr_protected</tt> and <tt>attr_accessible</tt> methods for models.</p>
<p>It is a very simple -- all it does it filter out specified parameters from a request.</p>
<h4>Why?</h4>
<hr />
<p>Good question... you can ready about why <tt>attr_protected</tt> sucks <a href="http://ambethia.com/2007/11/09/attr_protected-my-left-foot/">here</a>, or you can just read my following little rant...</p>
<p>What's the goal of <tt>attr_protected</tt>? To protect us from <em>user input</em>, not from <em>ourselves</em>. When I used <tt>attr_protected</tt>, I had to refactor <em>tons</em> of code in models, controllers and tests (that already worked well) to not use the mass attribute setters.</p>
<p>Was this massive code refactoring really worth the protection from the very few places were I do something like:</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby"><span class="support support_class support_class_ruby">User</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">new</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>params<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span></span></pre>
<p>or</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby"><span class="support support_class support_class_ruby">User</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>update_attributes<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>params<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span></span></pre>
<p>Truth of the matter, I was hardly ever passing params (or a subset thereof) to a mass attribute setter. So no, it wasn't worth the massive refactoring job.</p>
<h4>Installation</h4>
<hr />
<p><tt>git clone git://github.com/cjbottaro/param_protected.git vendor/plugins/param_protected</tt></p>
<h4>Usage</h4>
<hr/>
<pre class="textmate-source mac_classic"><span class="source source_ruby"><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">UsersController<span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby"> <span class="punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby"><</span> ApplicationController</span></span></span>
param_protected <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user_id</span>
<span class="keyword keyword_control keyword_control_ruby">end</span>
<span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">AccountController<span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby"> <span class="punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby"><</span> ApplicationController</span></span></span>
param_accessible <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>account_id</span>
<span class="keyword keyword_control keyword_control_ruby">end</span></span></pre>
<p><tt>param_protected</tt> is used to blacklist and <tt>param_accessible</tt> is used to whitelist.</p>
<p>You can give it an array of param names to filter:</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby">param_protected <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user_id</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>some_other_param</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span></span></pre>
<p><tt>param_protected</tt> and <tt>param_accessible</tt> are both just before filters, so the usual <tt>:only</tt> and <tt>:except</tt> arguments can be used:</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby">param_protected <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user_id</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>only</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>some_action</span>
param_protected <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user_id</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>only</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>some_action</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>another_action</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span>
param_protected <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user_id</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>except</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>some_action</span>
param_protected <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user_id</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>except</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>some_action</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>another_action</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span></span></pre>
<p>You can protect nested params also (removes <tt>params[:user][:id]</tt> and <tt>params[:user][:password])</tt>:</p>
<pre class="textmate-source mac_classic"><span class="source source_ruby">param_protected <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>id</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>password</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span></span></pre>
<p>You can get all crazy with that much like how <tt>ActiveRecord::Base#find</tt>'s <tt>:include</tt> argument works.
<pre class="textmate-source mac_classic"><span class="source source_ruby">param_accessible <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>account_name</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>user</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>id</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>password</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>address</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> <span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>city</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>state</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>zip</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]]</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">}</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span></span></pre>
<h4>Caveats (IMPORTANT!!!!)</h4>
<hr />
<p>Because <tt>param_protected</tt> is really a before filter (uses <tt>prepend_before_filter</tt>), <em>you must take special care to ensure that it runs before any of your other before filters!!</em> If it is not, some of your before filters might have access to some params they shouldn't.</p>
<h4>Tests</h4>
<hr />
<p><tt>rake test</tt> should work (from the plugin's root dir), though it's far from comprehensive.</p>
<h4>Documentation</h4>
<hr />
Please see the <a href="http://www.stochasticbytes.com/doc/param_protected/README.html">README</a> for usage instructions and examples.
<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-649787285609181801?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com5tag:blogger.com,1999:blog-4937488729022245645.post-90041552169725258032007-12-01T15:55:00.000-06:002008-05-19T10:27:37.328-05:00Directory Project plugin for Kate<p>This is a plugin for Kate that mimics TextMate's directory tree view and find files features. In other words, it's a simple project managing plugin where a directory defines a project. See the "Features" section below for screenshots and the "Settings" sections for an explanation of each option.</p>
<h4>Prerequisites</h4>
<hr />
<p>This plugin requires that Kate (obviously) and <a href="http://paul.giannaros.org/pate/">Pate</a> be installed. If you are having trouble installing Pate on an Ubuntu system, please see <a href="http://blog.stochasticbytes.com/2007/11/installing-pate-for-kate.html">this post</a>.</p>
<h4>Installation</h4>
<hr />
<pre>git clone git://github.com/cjbottaro/kate_directory_project.git
cd directory_project
./install</pre>
<p>If that doesn't work, all you need to do <tt>mkdir -p ~/.kde/share/apps/kate/pyplugins/directory_project</tt> and copy <tt>directory_project.py</tt> into it.</p>
<h4>Features</h4>
<hr />
<p style="text-align: center;">Tree view of whatever directory is currently opened.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_qt0OXJwg4QA/R1Ha--IkOqI/AAAAAAAAAJQ/qvYSnREQqT8/s1600-R/tree.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_qt0OXJwg4QA/R1Ha--IkOqI/AAAAAAAAAJQ/jdWptmpOpDQ/s400/tree.png" alt="" id="BLOGGER_PHOTO_ID_5139129425172118178" border="0" /></a>
<p style="text-align: center;">Search-as-you-type find files dialog.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_qt0OXJwg4QA/R1HbvOIkOrI/AAAAAAAAAJY/x-4z5AL-YAM/s1600-R/finder.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_qt0OXJwg4QA/R1HbvOIkOrI/AAAAAAAAAJY/CFAk64-emJ4/s400/finder.png" alt="" id="BLOGGER_PHOTO_ID_5139130254100806322" border="0" /></a>
<p style="text-align: center;">Useful configuration options.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_qt0OXJwg4QA/R1Hc0uIkOsI/AAAAAAAAAJg/K2TSZH4Sed0/s1600-R/settings.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_qt0OXJwg4QA/R1Hc0uIkOsI/AAAAAAAAAJg/XTJLNAsUmPU/s400/settings.png" alt="" id="BLOGGER_PHOTO_ID_5139131448101714626" border="0" /></a>
<br/>
<p style="text-align: center;">Tree browser and find files dialog stay in sync with filesystem via KDirWatch. (no picture)</p>
<h4>Settings</h4>
<hr />
<p>
There are two types of settings: project specific and global. Global options are applied to all directory projects while project specific settings are different for each one. Directory Project remembers the project specific settings between projects via an ini file in <tt>~/.kde/share/apps/kate/pyplugins/directory_project/directory_project.conf</tt>
</p>
<p>Probably the most important setting is the <strong>search type</strong> setting. It dictates how the find files dialog generates matches.</p>
<p>
Search type <strong>exact</strong> only hits exact matches. For instance, searching for <em>doc_test</em> will yield the following matches (matching text highlighted):<br/>
<tt><span style="background-color:yellow;">doc_test</span>.rb</tt><br/>
<tt>email_<span style="background-color:yellow;">doc_test</span>.rb</tt>
</p>
<p>
Search type <strong>character</strong> matches by character, preserving the order of the characters. Spaces are ignored in the query string for this search type. This search type is the default behavior in TextMate. Searching for <em>doc test</em> yields:<br/>
<tt><span style="background-color:yellow;">doc</span>ument_<span style="background-color:yellow;">test</span></tt><br/>
<tt><span style="background-color:yellow;">d</span>ashb<span style="background-color:yellow;">o</span>ard_<span style="background-color:yellow;">c</span>ontroller_<span style="background-color:yellow;">test</span>.rb</tt>
</p>
<p>
Search type <strong>word</strong > matchs by word, preserving the order of the words. Words are space separated in the query string. This is the default search type for Directory Project. Searching for <em>doc test</em> yields:<br/>
<tt><span style="background-color:yellow;">doc</span>ument_<span style="background-color:yellow;">test</span>.rb</tt><br/>
<tt><span style="background-color:yellow;">doc</span>ument_controller_<span style="background-color:yellow;">test</span>.rb</tt>
</p>
<p>
The <strong>name filters</strong> settings is a space separated list of file name pattern matches. Any file that <em>does not</em> match one of these patterns will not show up in Directory Project's tree browser or find files dialog. The default setting is <tt>*</tt> which matches all files. If you only want to match Ruby and HTML files, you can change the name filters to <tt>*.rb *.html</tt>
</p>
<p>
The <strong>Ignore Files/Directories</strong> is a list of files and directories names that will be ignored by Directory Project. Adding a directory here will stop Directory Project from including anything below that directory.
</p>
<h4>TODO</h4>
<hr />
<p>Make an option to have the find files dialog search on the relative path instead of just the file name, so you can distinguish between <tt>app/views/emails/index.html</tt> and <tt>app/views/documents/index.html</tt> by searching for <tt>email index</tt>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-9004155216972525803?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com5tag:blogger.com,1999:blog-4937488729022245645.post-48007063314760029302007-11-14T18:05:00.001-06:002008-09-26T13:55:45.951-05:00Installing Pate for Kate<h4>UPDATE</h4>
<p>Like an idiot, I lost the patches that I made (the links below are broken). Thanks to Dennis in the comments for making new patches. As far as I can tell, they only work with pate-0.5, not pate-0.5.1. Download the patch <a href="http://dl.getdropbox.com/u/167916/stochasticbytes/pate-0.5-ubuntu.diff">here</a>. To apply the patch, run the following command from inside the pate source directory:</p>
<tt>patch -p1 < pate-0.5-ubuntu.diff</tt>
<hr/>
<h4>Intro</h4>
<p>You need to do some hacking to get Pate installed on a (K)ubuntu 7.10 system.</p>
<h4>Background</h4>
<hr />
<p><a href="http://paul.giannaros.org/pate/">Pate</a> is a really cool plugin for <a href="http://www.kate-editor.org/">Kate</a> (which is a text editor for my <a href="http://www.kde.org/">favorite desktop environment</a>). It is a Kate plugin that allows you to write other Kate plugins in Python (instead of C++). It also comes with a few Python-written plugins, mainly to demonstrate what you can do with it.</p>
<p>I had a very hard time installing Pate. The reason being that the author is a Suse user and his configure script <del>only works?</del> is tailored for Suse. I'm an Ubuntu user; specifically Kubuntu 7.10 Gutsy Gibbon.</p>
<h4>Installation Process</h4>
<hr />
<p>You need to install development headers/libraries for Kate, Sip, KDE Python bindings, QT Python bindings, etc.
<pre>sudo aptitude install cmake sip4 python-sip4-dev python-kde3-dev \
python-qt-dev kate-plugins kdelibs-dev kdebase-dev</pre>
If I'm missing anything, please let me know and I'll update this.</p>
<h5>Pate-0.5</h5>
<pre>cd PATE_SRC
wget http://www.stochasticbytes.com/pate/pate-0.5-ubuntu-patches.tar.gz
tar xzf pate-0.5-ubuntu-patches.tar.gz</pre>
<p>Now <tt>configure && cd build && make && sudo make install</tt> should work as expected.</p>
<p>Here is a <a href="http://www.stochasticbytes.com/pate/pate-0.5-ubuntu-patches.tar.gz">link</a> to my Pate-0.5 patches.</p>
<h5>Pate-0.5.1</h5>
<p>This version isn't available (yet) via the main Pate webpage, but here's a <a href="http://paul.giannaros.org/stuff/Pate-0.5.1.tar.gz">link</a> for you.</p>
<pre>cd PATE_SRC
wget www.stochasticbytes.com/pate/pate-0.5.1-ubuntu-patches.tar.gz
tar xzf pate-0.5.1-ubuntu-patches.tar.gz</pre>
<p>Now <tt>configure && cd build && make && sudo make install</tt> should work as expected.</p>
<p>Here is a <a href="http://www.stochasticbytes.com/pate/pate-0.5.1-ubuntu-patches.tar.gz">link</a> to my Pate-0.5.1 patches.</p>
<h4>Why?</h4>
<hr />
<p>Why did I go through the trouble of making a blog post about this rather than submit my changes back to the author? Two reasons:
<ol><li>It's an excuse to make a blog post!</li><li>The author and the kwrite-devel mailing list didn't seem too interested in my plight.</li></ol></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-4800706331476002930?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com27tag:blogger.com,1999:blog-4937488729022245645.post-18514274159357164722007-10-22T12:35:00.000-05:002008-05-19T22:18:47.873-05:00migration_izzle<p>Managing migration version numbers in Rails among multiple developers using the same database is a pain in the ass. You know the drill, you svn up, create a migration, try to run db:migrate but low and behold, the db version is already 10 versions above your migration's.</p>
<p>This plugin offers a simple solution: create and manage a "history" table that records which migrations have and have not been run and modify <tt>rake db:migrate</tt> to behave accordingly.</p>
<p>For documentation, installation and usage instructions, please see the <a href="http://github.com/cjbottaro/migration_izzle/tree/master">migration_izzle github</a> page (scroll down).<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-1851427415935716472?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com3tag:blogger.com,1999:blog-4937488729022245645.post-82954056720761268472007-10-21T19:54:00.000-05:002008-05-19T12:29:11.310-05:00Better AppConfig Plugin for Rails<p>There are <a href="http://www.google.com/search?q=AppConfig+plugin+rails">plenty</a> of "AppConfig" plugins for Rails already out there, so why did I make one? Three reasons:</p>
<ul>
<li>Break the config files out into different files, one for each environment plus a shared common one.</li>
<li>Allows for nested sections and preserves object member notation for them.</li>
<li>Allows for lists (arrays).</li>
</ul>
<h4>Installation</h4>
<hr/>
<pre>git clone git://github.com/cjbottaro/app_config.git vendor/plugins/app_config</pre>
<h4>Usage</h4>
<hr/>
<p>See the <a href="http://github.com/cjbottaro/app_config/tree/master">README</a> on github (scroll down on the page).</p>
<h4>Tests</h4>
<hr/>
<p>All the unit tests should pass.</p>
<pre>cd RAILS_ROOT/vendor/plugins/app_config
rake test</pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4937488729022245645-8295405672076126847?l=blog.stochasticbytes.com'/></div>Christopher J. Bottarohttp://www.blogger.com/profile/14116593743589959438noreply@blogger.com1