Ruby Dynamic Nested Namespacing - ruby-on-rails-3

Given two model that are namespaced as
SomeModule::V1::Api
SomeModule::V2::Api
I want to make a call in my controller like:
api = SomeModule::V1::Api
but have the "V1" portion be a variable, so that I can swap between versions.
Any ideas on how to make that happen?

v = 'V1'
"SomeModule::#{v}::Api".constantize
=> SomeModule::V1::Api
Example:
module SomeModule
module V1; end
module V2; end
end
class SomeModule::V1::Api
def self.foo; 'V1 foo'; end
end
class SomeModule::V2::Api
def self.foo; 'V2 foo'; end
end
v = 'V1'
puts "SomeModule::#{v}::Api".constantize.foo
=> V1 foo
v = 'V2'
puts "SomeModule::#{v}::Api".constantize.foo
=> V2 foo

If you don't want to use #constantize (which is a part of ActiveSupport), you can do it with Plain Old Ruby:
version = "V1"
SomeModule.const_get(version).const_get("Api")
# => SomeModule::V1::Api

Related

Sorbet: check for a class that includes a target module

Sorbet's T.class_of can be used to match descendant classes, but not classes that include a module:
module X; end
class A; end
class B < A; include X; end
B.ancestors # => [B, X, A, Object, PP::ObjectMixin, Kernel, BasicObject]
sig { params(x: T.class_of(A)).void }
def is_a(x); end
is_a(A) # => ok
is_a(B) # => ok
sig { params(x: T.class_of(X)).void }
def is_b(x); end
is_b(X) # => ok
is_b(B) # => error
According to https://sorbet.org/docs/class-of, this is because B is not an
instance of X's singleton_class:
B.is_a?(A.singleton_class) # => true
B.is_a?(B.singleton_class) # => true
B.is_a?(X.singleton_class) # => false
But no alternative suggestion is provided. Is there a way to type check based on the contents of a class' ancestors? i.e. something like class_of that can be used to check for a class mixing in a module?

Post with params in Phoenix (with no Ecto)?

I'm trying to create a REST API using Phoenix with no Ecto or brunch.
What's the syntax for creating a post function in the router/controller with parameters, but not using Ecto?
For example in Ruby/Sinatra it would look something like this:
post "/v1/ipf" do
#weight1 = params[:weight1]
#weight2 = params[:weight2]
#weight3 = params[:weight3]
#weight4 = params[:weight4]
#goal1_percent = params[:goal1_percent]
#goal2_percent = params[:goal2_percent]
# etc...
end
Update
Based on Nick's answer, here's what I ended up with:
rest_api/web/router.ex:
defmodule RestApi.Router do
use RestApi.Web, :router
pipeline :api do
plug :accepts, ["json"]
end
scope "/", RestApi do
pipe_through :api
scope "/v1", V1, as: :v1 do
get "/ipf", IPFController, :ipf
end
end
end
rest_api/web/controllers/v1/ipf_controller.ex:
defmodule RestApi.V1.IPFController do
use RestApi.Web, :controller
import IPF
def ipf(conn, params) do
{weight1, _} = Integer.parse(params["weight1"])
{weight2, _} = Integer.parse(params["weight2"])
{weight3, _} = Integer.parse(params["weight3"])
{weight4, _} = Integer.parse(params["weight4"])
{goal1_percent, _} = Float.parse(params["goal1_percent"])
{goal2_percent, _} = Float.parse(params["goal2_percent"])
results = IPF.ipf(weight1, weight2, weight3, weight4, goal1_percent, goal2_percent)
render conn, results: results
end
end
rest_api/web/views/v1/ipf_view.ex:
defmodule RestApi.V1.IPFView do
use RestApi.Web, :view
def render("ipf.json", %{results: results}) do
results
end
end
Ecto and Brunch don't really have anything to do w/Phoenix handling a POST. Brunch is a web asset build tool, and Ecto is a database layer.
To add this new route, you just need to add an entry in the router for the new route:
post "/v1/spf", SPFController, :spf
And then create the controller:
defmodule MyModule.SPFController do
def spf(conn, params) do
# do whatever
end
end
That's it.

Rails helper method method not works in PDF if sending as an attachment

Hi i have create a PDF conversion in my rails application using Prawn and it working fine.
Now i am sending that PDf in an email attachment. Now problem is that i can send PDF attachment if i do not use any helper method, but when i use my format_currency method in PDf file it gives error on instance_eval method. here is my code sample:
format currency code:
module ApplicationHelper
def format_currency(amt)
unit = 'INR'
country = current_company.country
if !country.blank? && !country.currency_unicode.blank?
unit = country.currency_unicode.to_s
elsif !country.blank?
unit = country.currency_code.to_s
end
number_to_currency(amt, :unit => unit+" ", :precision=> 2)
end
end
My controller code :
pdf.instance_eval do
#company = current_company
#invoice = invoice
#invoice_line_items = invoice_line_items
#receipt_vouchers = receipt_vouchers
eval(template) #this evaluates the template with your variables
end
the error message i got :
undefined method `format_currency' for #<Prawn::Document:0x7f89601c2b68>
with this code i can send attachment successfuly if i don't use helper method but i need to use that method.
I have fixed this issue in a different manner, i have created a new currency_code method in my company model and called that in my format_currency helper method and it is working for me fine:
Here is what i have done :
def currency_code
unit = 'INR'
if !country.blank? && !country.currency_unicode.blank?
unit = country.currency_unicode.to_s
elsif !country.blank?
unit = country.currency_code.to_s
end
unit
end
and used it in my format_currency helper :
def format_currency(amt)
unit = current_company.currency_code
number_to_currency(amt, :unit => unit+" ", :precision=> 2)
end
and in my controller i have added a variable for currency and used it in my pdf file:
pdf.instance_eval do
#company = current_company
#invoice = invoice
#invoice_line_items = invoice_line_items
#receipt_vouchers = receipt_vouchers
#currency = current_company.currency_code # new added variable for currency
eval(template) #this evaluates the template with your variables
end

Rails 3: Pass options to model method

This is my Model (Subscription) Method:
def activation_codes(options = {})
if options[:first]
self.group.group_codes.first
else
self.group.group_codes
end
end
I am trying to call to this method in this fashion:
sub = Subscription.where(:subscription_limit => -1).first
sub.activation_codes {:first}
For some reason the elseis being evaluated.
You need to pass Hash to method activation_codes in order to make it work as expected, like:
sub.activation_codes({:first => 'some value'})
but you're currently passing Symbol instead.

Undefined Method `authorize_from_request' using OAuth and Twitter Gem in Ruby on Rails 3

Im getting the following error:
undefined method `authorize_from_request'
Based on the documenation here: http://oauth.rubyforge.org/rdoc/classes/OAuth/Consumer.html
That method doesnt exist, but I saw this method used here:
http://teachmetocode.com/screencasts/oauth-with-the-twitter-gem/ and
so I'm guessing it was deprecated some time ago, but I can't seem to
find its replacement and was wondering what other way could I go about
solving this issue?
Thanks in Advance!
Controller Code:
class TwitterController < ApplicationController
def index
end
def login
oauth_request_token = oauth.get_request_token(:oauth_callback => "http://gnome.local/twitter/finalize")
session[:request_token] = oauth_request_token.token
session[:request_secret] = oauth_request_token.secret
redirect_url = oauth_request_token.authorize_url
redirect_url = "http://" + redirect_url unless redirect_url.match(/^http:\/\//)
redirect_to redirect_url
end
def finalize
oauth.authorize_from_request(session[:request_token], session[:request_secret], params[:oauth_verifier])
#client = Twitter::Client.new(oauth).verify_credentials
session[:request_token] = nil
session[:request_secret] = nil
oauth_access_token = oauth.get_access_token
#oauth_token = session[:oauth_token] = oauth_access_token.token
session[:oauth_secret] = oauth_access_token.secret
end
def client
oauth.authorize_from_access(session[:auth_token])
end
def oauth
#oauth ||= OAuth::Consumer.new(APP_CONFIG[:twitter][:consumer_key], APP_CONFIG[:twitter][:consumer_secret], :site => "http://api.twitter.com", :request_endpoint => "http://api.twitter.com", :sign_in => true);
end
end
(Original Post: http://groups.google.com/group/oauth-ruby/browse_thread/thread/614b27e4f5d80fab)
Got the same problem, the solution is to use according to the (old) Twitter gem:
request_token.get_access_token(oauth_verifier: params[:oauth_verifier])