def self.source_root
File.join(File.dirname(__FILE__), 'templates')
end
This means that you can call Class.source_root on a class and it will return it's path name with 'templates' appended on the end. So say you had
Class User
def self.source_root
File.join(File.dirname(__FILE__), 'templates')
end
end
In the directory application/model/
If you call
User.source_root
It returns
"application/model/templates"
Use irb to see what it does. You can debug variables and test what they do.
It's a class method so you can create a class in irb and test what it does.
Run irb like so :-
irb(main):001:0> def self.source_root
irb(main):002:1> File.join(File.dirname(FILE), 'templates')
irb(main):003:1> end
=> nil
irb(main):004:0> class Foo
irb(main):005:1> def self.source_root
irb(main):006:2> File.join(File.dirname(FILE), 'templates')
irb(main):007:2> end
irb(main):008:1> end
=> nil
irb(main):009:0> Foo.source_root
=> "./templates"
irb(main):010:0>
irb(main):010:0> FILE
=> "(irb)"
irb(main):011:0> File.dirname(FILE)
=> "."
Related
Why won't my module load properly when I include it in my presenter class?
My class methods and module methods are not available when loading from rails. The module works when loading out of rails in a single file.
app/presenters/body_parts/method_wrapper.rb
module BodyParts
def self.included(klass)
klass.extend ClassMethods # => Car
end # => :included
module ClassMethods
def set_wheels(*args)
x, *wheel_args = args # => [3], [3]
puts "Wheels class method called with: #{x.to_s}" # => nil, nil
#wheels |= x # => true, true
end # => :set_wheels
class MethodWrapper
attr_reader :klass # => nil
def initialize(klass)
#klass = klass
end # => :initialize
def wrap(method_name)
puts "Wrapping a method"
wrapper_callback(result)
end # => :wrap
end # => :wrap
end # => :wrap
private # => BodyParts
def wrapper_callback(result)
"Wrapped a #{result} in the call back"
end # => :wrapper_callback
end # => :wrapper_callback
app/presenters/car_presenter.rb
class CarPresenter
include BodyParts # => Car
set_wheels 3 # => true
def brand
'Car Brand' # => "Car Brand"
end # => :brand
set_wheels 3 # => true
def title # policy set to 2 for title methods because of the above
'Car Title'
end # => :title
end # => :title
car_presenter = CarPresenter.new # => #<CarPresenter:0x00fe4ed9300>
car_presenter.brand # => "Car Brand"
# >> Wheels class method called with: 3
# >> Wheels class method called with: 3
Binding.pry from CarsPresenter in Rails
[1] pry(CarPresenter)> set_wheels 3
NameError: undefined local variable or method `set_wheels' for CarPresenter:Class
from (pry):12:in `<class:CarPresenter>'
[2] pry(CarPresenter)> BodyParts
=> BodyParts
[3] pry(CarPresenter)> self
=> CarPresenter
Due to the way const loading works in rails, a module BodyParts should be defined in the top level of presenters directory, i.e. in app/presenters/body_parts.rb.rb.
Rails expects app/presenters/body_parts/method_wrapper.rb to define const BodyParts::MethodWrapper,
Read mode in rails guides.
Why does the Test.foo work, but Test2.foo? fail.
It seems it works without the '?', but I would prefer to have the ? to follow conversation that it's a boolean.
syntax error, unexpected tOP_ASGN
Works:
class Test
def foo
#foo ||= true # => true
end # => :foo
end # => :foo
FAILS:
class Test2
def foo?
#foo? ||= true # => true
end # => :foo
end # => :foo
? symbol is allowed at the end of a method name but #foo is an instance variable, not a method. And ? is not allowed in variables names
My objective is to dynamically load a set of methods to an ActiveRecord model instance based on an attribute that's set:
class Book < ActiveRecord::Base
after_initialize do |cp|
self.class.include "#{cp.subject}".constantize
end
end
I then have the following concerns:
module Ruby
extend ActiveSupport::Concern
def get_framework
'rails'
end
end
module Python
extend ActiveSupport::Concern
def get_framework
'django'
end
end
Then, when I run these separately, I get the correct framework string:
python_book = Book.create(:subject => 'python', :id => 1)
python_book.get_framework -> 'django'
ruby_book = Book.create(:subject => 'ruby', :id => 2)
ruby_book.get_framework -> 'rails'
My problem is that when I have both of the books returned in a query, the Concern is included is the last in the result set and is not picking up the correct Concern methods.
Books.all.order(:id => 'asc').collect do |book|
puts book.get_framework
end
# Result
['rails', 'rails']
I am assuming that this is because the 'include' is happening at the class level and not the instance level. Would love some help as to how to clean this up and make this work.
Use .extend
to add instance methods to a instances of Book instead.
Extends in action:
module Greeter
def say_hello
"Hello"
end
end
irb(main):008:0> a = Object.new
=> #<Object:0x00000101e01c38>
irb(main):009:0> a.extend(Greeter)
=> #<Object:0x00000101e01c38>
irb(main):010:0> a.say_hello
=> "Hello"
irb(main):011:0> Object.new.say_hello
NoMethodError: undefined method `say_hello' for #<Object:0x00000101e196d0>
class Book < ActiveRecord::Base
after_initialize do |cp|
self.extend subject.constantize
end
end
I want to create a custom method, which I have defined in my questions_controller.rb file, as so:
def self.ping
#question = Question.first
#question.update(:amplify => #question.amplify + 1)
end
Now the problem is how do I call this method? Do I need to define a route first? How can I reference this from the console?
Thanks in advance.
I'd suggest to move it to your model:
question.rb
def self.ping
question = Question.first
question.update(:amplify => question.amplify + 1)
end
and define custom route, routes.rb
post '/ping' => 'questions#ping', as: 'ping'
questions_controller.rb
def ping
Question.ping
end
then you can reference it from console:
Question.ping
Please read this http://www.railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/
class Foo
def self.bar
puts 'class method'
end
def baz
puts 'instance method'
end
end
Foo.bar # => "class method"
Foo.baz # => NoMethodError: undefined method ‘baz’ for Foo:Class
Foo.new.baz # => instance method
Foo.new.bar # => NoMethodError: undefined method ‘bar’
Instead of
question.update(:amplify => question.amplify + 1)
You can use
question.increment!(:amplify)
I've made this test class to experiment with callbacks not in AR. But for some reason I have to manually call them. Which just seems pointless, in a way.
class TestClass
include ActiveSupport::Callbacks
define_callbacks :save
set_callback :save, :before, :speak
set_callback :save, :after, :bark
def save
puts 'saving...'
end
def other_it
run_callbacks :save do
puts 'saving...'
end
end
def speak
puts "hi"
end
def bark
puts "ruff"
end
end
It seems like I wouldn't have to specify the run_callback method in the :save method, but I apparently have to. What am I missing? See this output:
ruby-1.8.7-p352 :016 > t = TestClass.new
ruby-1.8.7-p352 :017 > t.save
saving...
=> nil
ruby-1.8.7-p352 :018 > t.other_it
hi
saving...
ruff
=> nil
The save callbacks are not run in the save method, unless I call them manually.