Multiple namespaces on Rails ActiveAdmin issues - ruby

I'm using active_admin and having issues setting up multiple namespaces.
Relevant files:
config/initializers/active_admin.rb:
config.load_paths = [File.join(Rails.root, "app", "active_admin")]
config.default_namespace = :superadmin
config.namespace :superadmin do |superadmin|
superadmin.site_title = "superadmin"
superadmin.authentication_method = :authenticate_superadmin_user!
end
config.namespace :admins do |admins|
admins.site_title = "admins"
admins.authentication_method = :authenticate_admin_user!
end
Then I have two subfolders, /admins and /superadmin:
app/active_admin/superadmin/dashboard:
ActiveAdmin.register_page "Dashboard" do
...
app/active_admin/superadmin/product_product.rb:
ActiveAdmin.register Product::Product, as: Product do
...
So far, so good.
Now, I can't seem to figure out how to add a dashboard for admins (or any other pages/models) without it blowing up.
If I go to localhost:3000/admins, I get the error uninitialized constant Admins::DashboardController.
I've tried adding:
app/active_admin/admins/dashboard.rb:
ActiveAdmin.register_page "Dashboard do
...
(which does nothing)
And namespaced:
app/active_admin/admins/dashboard.rb:
ActiveAdmin.register_page "Dashboard, namespace: "admins" do
...
which gives the error:
Invalid route name, already in use: 'admins_root'
You may have defined two routes with the same name using the `:as` option,
or you may be overriding a route already defined by a resource
with the same naming
I've also tried adding the subfolders in the load_paths:
config.load_paths = [
File.join(Rails.root, "app", "active_admin"),
File.join(Rails.root, "app", "active_admin", "admins"),
File.join(Rails.root, "app", "active_admin", "superadmin")
]
Please note that I've looked at the following, but none seem to actually work...
http://activeadmin.info/docs/1-general-configuration.html#namespaces
2 Namespaces of activeadmin
How to use multiple Active Admin instances for Complete Separate Models
EDIT:
I've also tried to remove config.default_namespace and the only thing that did was break localhost:3000/superadmin so that it has the error:
uninitialized constant Superadmin::DashboardController

Related

ExecJS: keeping the context between two calls

I'm currently trying to use ExecJS to run Handlebars for one of the product I work on (note: I know the handlebars.rb gem which is really cool and I used it for some times but there is issues to get it installed on Windows, so I try another homemade solution).
One of the problem I'm having is that the Javascript context is not kept between each "call" to ExecJS.
Here the code where I instantiate the #js attribute:
class Context
attr_reader :js, :partials, :helpers
def initialize
src = File.open(::Handlebars::Source.bundled_path, 'r').read
#js = ExecJS.compile(src)
end
end
And here's a test showing the issue:
let(:ctx) { Hiptest::Handlebars::Context.new }
it "does not keep context properly (or I'm using the tool wrong" do
ctx.js.eval('my_variable = 42')
expect(ctx.js.eval('my_variable')).to eq(42)
end
And now when I run it:
rspec spec/handlebars_spec.rb:10 1 ↵
I, [2015-02-21T16:57:30.485774 #35939] INFO -- : Not reporting to Code Climate because ENV['CODECLIMATE_REPO_TOKEN'] is not set.
Run options: include {:locations=>{"./spec/handlebars_spec.rb"=>[10]}}
F
Failures:
1) Hiptest::Handlebars Context does not keep context properly (or I'm using the tool wrong
Failure/Error: expect(ctx.js.eval('my_variable')).to eq(42)
ExecJS::ProgramError:
ReferenceError: Can't find variable: my_variable
Note: I got the same issue with "exec" instead of "eval".
That is a silly example. What I really want to do it to run "Handlebars.registerPartial" and later on "Handlebars.compile". But when trying to use the partials in the template it fails because the one registered previously is lost.
Note that I've found a workaround but I find it pretty ugly :/
def register_partial(name, content)
#partials[name] = content
end
def call(*args)
#context.js.call([
"(function (partials, helpers, tmpl, args) {",
" Object.keys(partials).forEach(function (key) {",
" Handlebars.registerPartial(key, partials[key]);",
" })",
" return Handlebars.compile(tmpl).apply(null, args);",
"})"].join("\n"), #partials, #template, args)
end
Any idea on how to fix the issue ?
Only the context you create when you call ExecJS.compile is preserved between evals. Anything you want preserved needs to be part of the initial compile.

Shibboleth authentication in Rails

I am having a struggle getting this to work so I've created a hell-world Rails app to try and get this to work.
Here's the repo with the code that is not working: https://github.com/pitosalas/shibtry
Here's what I've done starting from an empty Rails application:
I've added two gems to gem files:
gem 'omniauth-shibboleth'
gem 'rack-saml'
I got the shibboleth meta data from my university's web site and converted it using shib_conv.rb into the corresponding YAML: ./config.yml
I've updated routes adding get '/auth/:provider/callback', to: 'sessions#create'
I've put a breakpoint at SessionController#create
I've added initializers: omniauth.rb:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :shibboleth, {
:shib_session_id_field => "Shib-Session-ID",
:shib_application_id_field => "Shib-Application-ID",
:debug => true,
:extra_fields => [
:"unscoped-affiliation",
:entitlement
]
}
end
I've added rack_sam.rb initializer:
Rails.application.config.middleware.insert_after Rack::ETag, Rack::Saml,
{ :metadata => "#{Rails.root}/config/metadata.yml"}
Now, run the server and go to http://0.0.0.0:3000/auth/shibboleth and I get an error:
undefined method `[]' for nil:NilClass'
which is traced back to this line in rack-saml/misc/onelogin_setting.rb line 13 which is:
settings.idp_sso_target_url = #metadata['saml2_http_redirect']
in other words, looking for the metadata hash for that key. It happens that in my metadata.yml file that key is present, but by the time I get to this onelogin_setting.rb line 13, #metadata is nil (it should contain the contents of the file) and consequently that key doesn't exist.
And that's where, for now, the trail dries up.
I bypassed Shibboleth totally. My goal was to allow login to my universities authentication system specifically to allow students to log in with their student login, which is fronted by google apps. So this was much easier: https://developers.google.com/identity/sign-in/web/
Looks like you forgot to add your config file to the initializer:
Rails.application.config.middleware.insert_after Rack::ETag, Rack::Saml,
{
:metadata => "#{Rails.root}/config/metadata.yml",
:config => "#{Rails.root}/config/rack-saml.yml"
}
And the saml_idp setting in the rack-saml.yml must match the key for the idp_lists entry in your metadata.yml

Ruby: add new fields to YAML file

I've been searching around for a bit and couldn't find anything that really helped me. Especially because sometimes things don't seem to be consistant.
I have the following YAML that I use to store data/ configuration stuff:
---
global:
name: Core Config
cfg_version: 0.0.1
databases:
main_database:
name: Main
path: ~/Documents/main.reevault
read_only: false
...
I know how to update fields with:
cfg = YAML.load_file("test.yml")
cfg['global']['name'] = 'New Name'
File.open("test.yml", "w"){ |f| YAML.dump(cfg, f) }
And that's essentially everybody on the internet talks about. However here is my problem: I want to dynamically be able to add new fields to that file. e.g. under the "databases" section have a "secondary_db" field with it's own name, path and read_only boolean. I would have expected to do that by just adding stuff to the hash:
cfg['global']['databases']['second_db'] = nil
cfg['global']['databases']['second_db']['name'] = "Secondary Database"
cfg['global']['databases']['second_db']['path'] = "http://someurl.remote/blob/db.reevault"
cfg['global']['databases']['second_db']['read_only'] = "true"
File.open("test.yml", "w"){ |f| YAML.dump(cfg, f) }
But I get this error:
`<main>': undefined method `[]=' for nil:NilClass (NoMethodError)
My question now is: how do I do this? Is there a way with the YAML interface? Or do I have to write stuff into the file manually? I would prefer something via the YAML module as it takes care of formatting/ indentation for me.
Hope someone can help me.
Yo have to initialize cfg['global']['database']['second_db'] to be a hash not nil. Try this cfg['global']['database']['second_db'] = {}

Nanoc + Bower = Error - Found 2 content files for

I'm using nanoc to generate an static site.
Recently I added Bower to manage front end dependencies.
When I add Bootstrap via Bower I place the package in /assets/bower/
The Bootstrap package contains multiple files, including:
bootstrap/js/tests/vendor/qunit.css
bootstrap/js/tests/vendor/qunit.js
My Rules file has these rules:
route '/assets/*' do
extension = item[:extension]
if extension == 'coffee'
extension = 'js'
end
item.identifier.chop + '.' + extension
end
compile '*', :rep => :spec do
if !item[:spec_files].nil? && !item.binary?
filter :erb
layout 'spec'
end
end
route '*', :rep => :spec do
if !item[:spec_files].nil? && !item.binary?
'/specs' + #item.identifier[0..-2] + '.html'
end
end
compile '*' do
if !item.binary?
filter :erb
layout_name = item[:layout] || 'default'
layout layout_name
end
end
route '*' do
if item.binary?
item.identifier.chop + '.' + item[:extension]
else
item.identifier[0..-2] + '.html'
end
end
When running nanoc I get the following error:
RuntimeError: Found 2 content files for
content/assets/bower/bootstrap/js/tests/vendor/qunit; expected 0 or 1
I tried adding 2 new 'empty' rules for the /assets/bower/ folder but still getting the error.
route '/assets/bower/*' do
end
compile '/assets/bower/*' do
end
Any suggestions?
Later edit:
Looks like nanoc supports a static datasource that also takes in consideration the file extension.
https://github.com/nanoc/nanoc-site/blob/master/content/docs/troubleshooting.md
Still not sure if I can use both data sources in parallel.
Unfortunately, you can't have two files in the same directory with the same name before the last extension. For nanoc 4.0 it'll be rewritten to change that.
You can definitely have multiple data sources used at once, but that means you can't apply filters to the qunit files, only redirect the output.
Do you explicitly have to be able to organise files the same as Bower installs them? It might be a better idea to split them up into scripts and styles if you can, anyway - you'll almost certainly be filtering based on filetype, anyway, and that means in Rules you can just go
compile '/whatever-path/scripts/' do
filter :concatenate
filter :uglify_js
end
rather than
compile '/whatever-path/ do
case item[:extension]
when 'js'
filter :uglify_js
when 'scss'
filter :sass
end
end

How to mock/stub the config initializer hash in rails 3

Environment : Rails 3.1.1 and Rspec 2.10.1
I am loading all my application configuration through an external YAML file. My initializer (config/initializers/load_config.rb) looks like this
AppConfig = YAML.load_file("#{RAILS_ROOT}/config/config.yml")[RAILS_ENV]
And my YAML file sits under config/config.yml
development:
client_system: SWN
b2c_agent_number: '10500'
advocacy_agent_number: 16202
motorcycle_agent_number: '10400'
tso_agent_number: '39160'
feesecure_eligible_months_for_monthly_payments: 1..12
test:
client_system: SWN
b2c_agent_number: '10500'
advocacy_agent_number: 16202
motorcycle_agent_number: '10400'
tso_agent_number: '39160'
feesecure_eligible_months_for_monthly_payments: 1..11
And I access these values as, For example AppConfig['feesecure_eligible_months_for_monthly_payments']
In one of my tests I need AppConfig['feesecure_eligible_months_for_monthly_payments'] to return a different value but am not sure how to accomplish this. I tried the following approach with no luck
describe 'monthly_option_available?' do
before :each do
#policy = FeeSecure::Policy.new
#settlement_breakdown = SettlementBreakdown.new
#policy.stub(:settlement_breakdown).and_return(#settlement_breakdown)
#date = Date.today
Date.should_receive(:today).and_return(#date)
#config = mock(AppConfig)
AppConfig.stub(:feesecure_eligible_months_for_monthly_payments).and_return('1..7')
end
.....
end
In my respective class I am doing something like this
class Policy
def eligible_month?
eval(AppConfig['feesecure_eligible_months_for_monthly_payments']).include?(Date.today.month)
end
....
end
Can someone please point me in the right direction!!
The method that is being called when you do AppConfig['foo'] is the [] method, which takes one argument (the key to retrieve)
Therefore what you could do in your test is
AppConfig.stub(:[]).and_return('1..11')
You can use with to setup different expectations based on the value of the argument, ie
AppConfig.stub(:[]).with('foo').and_return('1..11')
AppConfig.stub(:[]).with('bar').and_return(3)
You don't need to setup a mock AppConfig object - you can stick your stub straight on the 'real' one.

Resources