Rails Module not loading for presenter - ruby-on-rails

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.

Related

syntax error, unexpected tOP_ASGN error with "?" in variable name

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

Dynamically including a Rails Concern

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

In Rails 3, want to get the HTML output of calling a controller's action

Is it possible for me to call a controllers action programatically and get the HTML output?
Here's a rails2 example that might get you a bit closer
lib/render_url_to_string.rb
if !defined?(ActionController::Integration::Session)
require "action_controller/integration"
end
class Rack::Lint
def call(*args)
#app.call(*args)
end
end
module RenderURLToString
def self.included(base)
base.send(:include, RenderURLToString::InstanceMethods)
base.extend( RenderURLToString::ClassMethods)
end
module ClassMethods
# This method sets the default hostname to render templates
# with. Use this to ensure the output urls in your templates
# are getting the right host.
#
def set_default_render_hostname(host)
RenderURLToString::Settings.hostname = host
end
end
module InstanceMethods
# This method renders a given URL within your site to a string.
# Invoke the method with the form
# render_url_to_string("/path/to/resource.ext")
# The method supports the following optional parameters, passed in
# as a symbol hash.
#
# :headers => A hash of HTTP headers
# Defaults to nil
# :params => A hash of URL parameters, or a string of URL
# parameters "?foo=bar&baz=bo"
# Defaults to nil
# :method => A symbol or string representing which HTTP method
# to use. Must be :get, :post, :put or :delete
# Defaults to :get
# :environment => A request environment to pass to the Dispatcher.
# You will rarely need to use this option; if you
# are calling the method inside of a Rails template
# or controller, the method will use the
# current request, extracting the relevant parts
# for its own use.
# :host => The host name to use for resolving URL creation
# Defaults to www.example.com
#
#
# The method returns an array with two elements. The first
# element is the integer status code (200, 404, 500) of the
# attempt to process the URL, and the second element is the
# string result of the body processed. An example return value of
# a successful request would be:
# [200, "<html><head><title>Foo!</title></head><body></body></html>"]
#
# whereas an example of a failed request would be:
# [500, "<html><head><title>The request failed</title><body></body></html>"]
#
# Examples:
#
# Renders the url /foo/bar.baz
# render_url_to_string("/foo/bar.baz")
#
# Renders the url /foo/bar.baz?wocca=wocca!
# render_url_to_string("/foo/bar.baz", :params => { :wocca => "wocca!" }
#
# Renders the url /foo/bar.baz with form parameter wocca = whoopiepie
# render_url_to_string("/foo/bar.baz",
# :params => { :wocca => "whoopiepie" }
# :method => :post)
#
# Renders the url /foo/bar.baz with form parameter wocca =
# whoopiepie and host set to "www.yahoo.com"
# render_url_to_string("/foo/bar.baz",
# :host => "www.yahoo.com",
# :params => { :wocca => "whoopiepie" }
# :method => :post)
#
def render_url_to_string(url, *args)
options = args.extract_options!
method = (options.delete(:method) || :get)
if method.is_a?(String)
method = method.downcase.to_sym
end
headers = options.delete(:headers)
params = options.delete(:params)
environment =
raise "Invalid method, must be GET, POST, PUT or DELETE" unless [ :get, :post, :put, :delete ].include?(method)
app = RenderURLToString::Settings.app
reset_host = app.host
if host = (options.delete(:host) || RenderURLToString::Settings.hostname)
app.host = host
end
if e = options.delete(:environment)
RenderURLToString::Settings.set_current_app_environment(e)
elsif self.respond_to?(:request) && request.env
RenderURLToString::Settings.set_current_app_environment(request.env)
else
RenderURLToString::Settings.set_current_app_environment(ENV)
end
status = app.send(method.to_sym, url, params, headers)
app.host = reset_host
return [status, RenderURLToString::Settings.app.body]
end
end
private
class Settings
IGNORED_ENVIRONMENT_KEYS = ["REQUEST_PATH", "action_controller.request.request_parameters", "PATH_INFO", "rack.request", "rack.routing_args", "rack.multithread","rack.request.query_hash","REQUEST_METHOD", "action_controller.request.query_parameters", "action_controller.rescue.request", "rack.request.query_string", "action_controller.rescue.response","rack.input", "QUERY_STRING", "rack.errors", "REQUEST_URI", "SCRIPT_NAME"]
def self.app=(app)
#app = app
end
def self.app
unless #app
# We don't want to deadlock the server when trying
# to process this internal request
# THIS IS MUCKING WITH INTERNAL RAILS REQUEST DISPATCHING LOGIC
# AND AS SUCH SHOULD NOT BE MESSED WITH UNLESS YOU
# PLAN ON FIXING BUGS IN THE FUTURE
dispatcher = ActionController::Dispatcher.new(self.stringio)
dispatcher.instance_eval do |instance|
def set_my_env(e)
#my_env = {}
e.each do |k, v|
#my_env[k] = v unless IGNORED_ENVIRONMENT_KEYS.include?(k)
end
end
def call(e)
#env = e.merge(#my_env)
self.dispatch
end
end
#app = ActionController::Integration::Session.new(dispatcher)
end
#app
end
def self.set_current_app_environment(env)
self.app.application.set_my_env(env)
end
def self.hostname=(host)
#host = host
end
def self.hostname
#host
end
def self.stringio
StringIO.new
end
end
end

Ruby on Rails calling ActiveRecord model from within ActionController plugin module

I've a got a method in ActiveRecord::User:
def create_user_from_json(user)
#user=User.new(user)
if #user.save!
#user.activate!
end
end
And I'm trying to call it in a plugin's module method. The plugin is json-rpc-1-1. Here is the relevant code:
class ServiceController < ApplicationController
json_rpc_service :name => 'cme', # required
:id => 'urn:uuid:28e54ac0-f1be-11df-889f-0002a5d5c51b', # required
:logger => RAILS_DEFAULT_LOGGER # optional
json_rpc_procedure :name => 'userRegister',
:proc => lambda { |u| ActiveRecord::User.create_user_from_json(u) },
:summary => 'Adds a user to the database',
:params => [{:name => 'newUser', :type => 'object'}],
:return => {:type => 'num'}
end
The problem is the code in the proc. No matter whether I call ActiveRecord::User.create_user_from_json(u) or ::User.create_user_from_json(u) or User.create_user_from_json(u) I just get undefined method 'create_user_from_json'.
What is the proper way to call a User method from the proc?
I think this needs to be a class method instead of an instance method, declare it like this:
def self.create_user_from_json(user)
...
end

What does this line of Rails 3 Do?

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)
=> "."

Resources