Rails model with other model as instance variable - ruby-on-rails-3

I am building a Rails application that contains Developers who have Applications. Both Developers and Applications are objects whose contents come from an external API. Thus, both of these models are hand-written and do not take advantage of ActiveModel, ActiveResource, etc.
I am trying to determine how to instantiate the Application object as an instance variable of the Developer object.
I have the following code within my Developer.initialize() function:
#apps = Array.new
data['applications'].each do |app|
#apps << Application.new(app)
end
The code is fairly self explanatory. Both developer.rb (which is where Developer is defined) and application.rb (which is where Application is defined) lie in the app/models directory. My developers controller instantiates a Developer object by calling Developer.new.
The line of code within the do block produces the following error:
uninitialized constant Developer::Application
app/models/developer.rb:24:in `initialize'
app/controllers/developers_controller.rb:11:in `new'
app/controllers/developers_controller.rb:11:in `show'
So it looks like Rails is trying to instantiate a Developer::Application, whereas I want to instantiate the Application object defined in application.rb within the app/models directory. Is there some way for this to be done?

You have to require the necessary files. In my case, from within the Developer class, I needed the following line: require 'application.rb' and everything worked fine.

Related

Getting uninitialized constant (NameError) inside decorators when running rspec tests via rake

In my app I use an engine (blogit) to which I want to add some changes / behaviours.
I followed the guides on how to override engine controllers/models and added the following:
The Code
In config/initializer/blogit.rb
# Requires extension ruby files in lib/blogit.
Dir[Rails.root.join("lib/blogit/*.rb")].each {|f| require f}
In lib/blogit/engine.rb
module Blogit
class Engine < ::Rails::Engine
isolate_namespace Blogit
config.to_prepare do
Dir.glob(Rails.root + "app/decorators/**/blogit/*_decorator*.rb").each do |c|
require_dependency(c)
end
end
end
end
In app/decorators/controllers/blogit/comments_controller_decorator.rb
Blogit::CommentsController.class_eval do
def create
Rails.logger.info "decorated controller action"
# ... overridden stripped ...
end
end
In app/decorators/models/blogit/comment_decorator.rb
Blogit::Comment.class_eval do
belongs_to :user
end
To be mentioned:
I have also created a migration to add a user reference to the comments model, since my app uses devise and I only want logged_in users to be able to comment. (Therefore I don't need the standard behaviour, so I'm going to override it.)
The Problem
If I run rake I get the weird error:
/Users/Kassi/.rvm/rubies/ruby-1.9.3-p392-railsexpress/bin/ruby -S rspec ./spec/controllers/home_controller_spec.rb ./spec/models/user_spec.rb
/Users/Kassi/demo/app/decorators/controllers/blogit/comments_controller_decorator.rb:3:in `<top (required)>': uninitialized constant Blogit::CommentsController (NameError)
However, if I run the first line that rake mentions by hand (.../ruby -S ...), all tests are being run successfully.
In my project I'm using guard with spork. Running guard will also let the tests pass without any error.
The app itself runs fine, i.e. it starts without errors and I'm able to comment as I want. My decorator action code is being executed.
So what's different when running rake?
Why does it break?
Note:
Adding require "blogit" or require "blogit/comments_controller" doesn't help. It actually can't find the controller using require.
A Demo Application
Since this problem is part of a bigger project, I created a new app from scratch for testing purposes that contains only the relevant stuff: basic rails app, rspec, devise, blogit and the decorators.
It can be found here: https://github.com/kassi/decorator_demo_rspec (git://github.com/kassi/decorator_demo_rspec.git)
Another repo using testunit (which is working!) can be found here: https://github.com/kassi/decorator_demo_testunit (git://github.com/kassi/decorator_demo_testunit.git)
Instead of performing the require statements yourself, you can try activesupport-decorators that does it for you.

Use Ruby Extension (.bundle) in Rails Applications

I have a built a Ruby Extension for C/Objective-C and now would like to use it in a Ruby on Rails web application but everytime I try to require it, WEBrick crashes! What I have is:
I have a Ruby Class: MyRubyObject which is tied to a C class (MyExtension).
MyRubyObject has been defined with one method: myRubyMethod which is tied to a function in my C class, MyExtension: myextensionmethod which just returns a string.
myextensionmethod essentailly calls another library which performs a load of work (multiple threads and what not) but finally returns a string
after compiling everything I get a MyRubyObject.bundle file. Using IRB, I can:
require './MyRubyObject'
p = MyRubyObject.new
p.myRubyMethod
=> "Result!"
This all works absolutely fine and now I want to use it in a RoR app
I put the MyRubyObject.bundle in lib in my RoR app and then from a controller class I do a require ./lib/MyRubyObject.bundle and WEBrick crashes!!!!
Any help would be greatly appreciated!!!
Cheers
I found a solution where from here: ruby-ldap gem not work in rails3 app, but work in rails console whereby I
Put a 'require File.expand_path('../../lib/MyRubyObject', __FILE__)' in config/environment.rb file (after 'require File.expand_path('../application', __FILE__)')
Then in my controller file I just put a require 'MyRubyObject' and was then able to instantiate normally: p = MyRubyObject.new ...
So I presume this was a related issue to WEBrick loading things in an incorrect order based upon the above link but I will keep an eye on this as we'll move servers most likely and this issue may pop it's ugly head up again!
Hope this helps others!
Thanks

How can I have a model called Admin with ActiveAdmin?

I've tried installing ActiveAdmin into a rails app that already has an Admin model* and it all works, until I try to run any code (e.g. run specs, or run the rails server) which needs to access the Admin class -- then it fails as if the problem is with my Admin class:
foo/app/models/admin.rb:1:in `<top (required)>': Admin is not a class (TypeError)
from bar/.rvm/gems/ruby-1.9.2-p320/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251:in `require'
*In my case I used --skip-users so I could reuse my Admin model, but it happens whether you do this or not. It also happens if you do:
rails generate active_admin:install Admin
How can I get ActiveAdmin to coexist with a model (or other class) called Admin
It took me a while to work this out (on a previous project I gave in and just renamed the model).
There have been some patches proposed, but actually there is a perfectly good config option that fixes this:
Edit the initializer at config/initializers/active_admin.rb so that the default_namespace is different (you could skip the default_namespace with config.default_namespace = false, but I haven't tried this).
I chose admin_ui for this:
config.default_namespace = :admin_ui
There may be more subtlety for this so you can (if you want) keep the /admin/ route rather than have admin_ui but this was good enough for me -- the official docs on this are at http://activeadmin.info/docs/1-general-configuration.html#namespaces, but don't mention this reason to change the namespace.

Rails 3: Choose and run a Mechanize script from inside Rails action.

My application scrapes information from various sites using Mechanize. Naturally, each site requires custom Mechanize code. Each site is stored in my database, including the url to scrape and the string name of an .rb file containing that site's Mechanize code. For this case, let's assume the scripts are available in the assets folder.
I would like to call http://example.com/site/:id, then have the show action dynamically choose which Mechanize script to run (say, #site.name + ".rb" ). The script will massage the data into a common model, so all sites can use the same show template.
I can't find a way to dynamically load a .rb script within an action and obtain the result. It may be easier to have the scripts return a JSON string, which I can parse before passing on to the template, but I can't see a solution for that either. Ideally, the script will run in the action's scope. The ugly solution is an enormous if-else chain (testing the site name to determine which code block to run), but there must be a better way.
Any suggestions would be greatly appreciated, as would any general solutions to running different code dependent upon the properties of database objects.
If you have all the code in your app already why are you eval'ing Ruby code?
Create classes like:
class GoogleSpider < Spider; end
class NewYorkTimesSpider < Spider; end
class SomeOtherSpider < Spider; end
And the site class will hold the class name that will be used, so you would be able to easily do something like this in your controller action:
def show
#site = Site.find(params[:id])
# name contains SomeOtherSpider
#process_output = #site.name.constantize.new.process
# do something with the output here
end
And then you don't need to mess around evaluating Ruby code, just call the class needed. You can even make them all singletons or keep them all in a hash for faster access.

Rails sitemap generator, undefined method post_path?

I am using the following gem:
https://github.com/kjvarga/sitemap_generator
I have a posts model and have used post_path(post) in other parts of the application as it is based on Enki.
However in the sitemap file:
Post.all.each do |post|
sitemap.add post_path(post), :lastmod => post.updated_at
end
This returns the error when running the rake task rake sitemap:refresh:
rake aborted!
undefined method `post_path' for #<SitemapGenerator::Interpreter:0x279efd0>
And:
Post.all.each do |post|
sitemap.add posts_path(post), :lastmod => post.updated_at
end
Returns no errors. Can anyone shed any light on this or do I need to provide more of the code?
sitemap_generator actually includes all the helper methods in the create block, so you should be able to access posts_path.
I had a similar problem, and my answer also made me feel stupid. I was storing sitemap.rb in config/initializers, when it should be stored in the config/ directory. That meant it was running on startup and failing because the url helpers weren't properly loaded (and, incidentally, when I called rake sitemap:refresh, the sitemap was being generated twice - once in the initializer and again as the rake task!)
I feel a bit stupid on this one, it was simply because post_path was a helper and not accessible, so I simply had to move it into the method directly.