call before methods in model on ruby
You can do this with prepend
. prepend
is like include
in that it adds a module to the ancestors of the class, however instead of adding it after the class it adds it before.
This means that if a method exists both in the prepended module and the class then the module implementation is called first (and it can optionally call super
if it wants to call the base class).
This allows you to write a hooks module like so:
module Hooks
def before(*method_names)
to_prepend = Module.new do
method_names.each do |name|
define_method(name) do |*args, &block|
puts "before #{name}"
super(*args,&block)
end
end
end
prepend to_prepend
end
end
class Example
extend Hooks
before :foo, :bar
def foo
puts "in foo"
end
def bar
puts "in bar"
end
end
In real use you would probably want to stash that module somewhere so that each call to before
doesn't create a new module but that is just an inplementation detail
before and after method call on models in ruby on rails, do thing
If you really want to wrap every method call (or even the ones defined by the target class itself), you can define a module that does 2 things,
- Get all the instance_methods and wraps them with your custom code
- Override the
method_added
method call and wrap every new method that is added with the same custom code
A good example using this strategy is answered here. You can customize this to take additional except
configuration and exclude those methods.
The meta-programming going on here is to rewrite each method as it is injected into the instance.
Another option is to wrap only specific method calls with your custom code, if you know which ones you'll need to cache. It will be less overhead and cleaner implementation.
For implementation, you can use the same meta-programming approach as described in the first example. One more approach can be to add an alias to the original method and rewrite the method to include your hook. Something like,
def add_before_hook(method_name)
class_eval do
without = :"#{method_name}_without_before_each_method"
alias_method without, method_name
define_method method_name do |*args, &block|
puts 'called before'
send without, *args, &block
end
end
end
The problem with the second approach is that it pollutes your method namespace by adding a duplicate method for each of your instance methods.
How to call method before index and new from model
You can pass a lambda, in this case {@interests = Widget.interests current_user}
, into before_action
to achieve what you want.
app/controllers/widgets_controller.rb
class WidgetsController < ApplicationController
before_action(only: [:show]) {@interests = Widget.interests current_user}
def show
# do something with @interests
end
end
app/models/widget.rb
class Widget < ActiveRecord::Base
def self.interests(user)
City.joins("INNER JOIN property_of_interests ON property_of_interests.city_id = cities.id").where(:property_of_interests => {:user_id => user})
end
end
Rails call back before every calling a method before every static method
Try this
class A
def self.hello
print "how are"
end
def self.before_stuff
print "you"
end
begin
print "hello,"
end
end
A.hello
Call a model method in a Controller
To complete davidb's answer, two things you're doing wrong are:
1) you're calling a model's function from a controller, when the model function is only defined in the model itself. So you do need to call
Project.form_search
and define the function with
def self.form_search
2) you're calling params from the model. In the MVC architecture, the model doesn't know anything about the request, so params is not defined there. Instead, you'll need to pass the variable to your function like you're already doing...
Ruby on Rails: Calling Model method in view
It seems that paypal_url
is a private method and you are trying to call it from outside of its class.
In your Order
class you probably have the keyword private
. Every method below that keyword will be declared private (as opposed to public) and an error will be thrown if you try to call it from outside the class. Private methods can only be called from within the class where they are defined. So try moving the definition of paypal_url
so that it appears before private
in your class.
You can read more about how this works here, and about the reasons behind it here.
Related Topics
How to Perform Vector Addition in Ruby
Ruby 1.9 Doesn't Support Unicode Normalization Yet
Rake Aborted! Stack Level Too Deep
I = True and False in Ruby Is True
How to Best Handle Per-Model Database Connections with Activerecord
Ruby - Test Whether Database Connection Is Possible
Why Does Hash.New({}) Hide Hash Members
Understanding Ruby Splat in Ranges and Arrays
How to Shorten a Uuid to a Specific Length
Error Installing Ruby 2.6.7 on MAC Os - How to Resolve
You May Have Encountered a Bug in the Ruby Interpreter or Extension Libraries
How to Round a Float to a Specified Number of Significant Digits in Ruby
How to Require File from 'Gem' Which Are Not Under 'Lib' Directory
How to Use Mongodb Ruby Driver to Do a "Group" (Group By)
Why Is Uri.Escape() Marked as Obsolete and Where Is This Regexp::Unsafe Constant
Rails 3.2.8 - How to Get the Week Number from Rails
Trying to Compare Two Text Files, and Create a Third Based on Information