Ruby: automatically wrapping methods in event triggers
There are a several ways to do it with the help of metaprogramming magic. For example, you can define a method like this:
def override_public_methods(c)
c.instance_methods(false).each do |m|
m = m.to_sym
c.class_eval %Q{
alias #{m}_original #{m}
def #{m}(*args, &block)
puts "Foo"
result = #{m}_original(*args, &block)
puts "Bar"
result
end
}
end
end
class CustomBaseObject
def test(a, &block)
puts "Test: #{a}"
yield
end
end
override_public_methods(CustomBaseObject)
foo = CustomBaseObject.new
foo.test(2) { puts 'Block!' }
# => Foo
Test: 2
Block!
Bar
In this case, you figure out all the required methods defined in the class by using instance_methods
and then override them.
Another way is to use so-called 'hook' methods:
module Overrideable
def self.included(c)
c.instance_methods(false).each do |m|
m = m.to_sym
c.class_eval %Q{
alias #{m}_original #{m}
def #{m}(*args, &block)
puts "Foo"
result = #{m}_original(*args, &block)
puts "Bar"
result
end
}
end
end
end
class CustomBaseObject
def test(a, &block)
puts "Test: #{a}"
yield
end
include Overrideable
end
The included
hook, defined in this module, is called when you include
that module. This requires that you include
the module at the end of the class definition, because included
should know about all the already defined methods. I think it's rather ugly :)
link_to method and click event in Rails
You can use link_to_function
(removed in Rails 4.1):
link_to_function 'My link with obtrusive JavaScript', 'alert("Oh no!")'
Or, if you absolutely need to use link_to
:
link_to 'Another link with obtrusive JavaScript', '#',
:onclick => 'alert("Please no!")'
However, putting JavaScript right into your generated HTML is obtrusive, and is bad practice.
Instead, your Rails code should simply be something like this:
link_to 'Link with unobtrusive JavaScript',
'/actual/url/in/case/javascript/is/broken',
:id => 'my-link'
And assuming you're using the Prototype JS framework, JS like this in your application.js
:
$('my-link').observe('click', function (event) {
alert('Hooray!');
event.stop(); // Prevent link from following through to its given href
});
Or if you're using jQuery:
$('#my-link').click(function (event) {
alert('Hooray!');
event.preventDefault(); // Prevent link from following its href
});
By using this third technique, you guarantee that the link will follow through to some other page—not just fail silently—if JavaScript is unavailable for the user. Remember, JS could be unavailable because the user has a poor internet connection (e.g., mobile device, public wifi), the user or user's sysadmin disabled it, or an unexpected JS error occurred (i.e., developer error).
save an active records array
a.each(&:save)
This will call B#save
on each item in the array.
Difference between after_create, after_save and after_commit in rails callbacks
You almost got it right. However there is one major difference between after_commit
and after_create
or after_save
i.e.
In the case of after_create
, this will always be before the call to save (or create) returns.
Rails wraps every save inside a transaction and the before/after create callbacks run inside that transaction (a consequence of this is that if an exception is raised in an after_create the save will be rolled back). With after_commit
, your code doesn't run until after the outermost transaction was committed. This could be the transaction rails created or one created by you (for example if you wanted to make several changes inside a single transaction). Originally posted here
That also means, that if after_commit
raises an exception, then the transaction won't be rolled back.
From M-Dahab's comment:after_commit
would run after create, update and destroy. But, you can use on:
option to specify which you are interested in. after_commit :some_method, on: :create
or even after_commit :some_method, on: [:create, :destroy]
or use a block like after_commit(on: :update) do run_method() end
.
Related Topics
How to Understand the #Dup and #Clone Operate on Objects Which Referencing Other Objects
How to Get Multiple-Line User Input in Ruby
How to Implement Editing/Formating Text Area in Rails
Ruby Popen3 -- How to Repeatedly Write to Stdin & Read Stdout Without Re-Opening Process
Can Anyone Explain This Array Declaration to Me
Ruby Open-Uri Can't Open Url (M1 MAC)
How to Find the Most Recently Modified Folder in a Directory Using Ruby
Pass Arguments by Reference to a Block with the Splat Operator
How to Pass Value from One Resource to Another Resource in Chef Recipe
Gitlab: Invocation of Gitlab-Shell
Ruby File Reading Parallelisim
How to Send Custom Invitation Using Devise_Invitable
How to Run Rails App in a Completely Isolated Instances of Chrome
Regex for Matching All Words Between a Set of Curly Braces
Why Doesn't Array Override the Triple Equal Sign Method in Ruby