Kaminari and Mongoid 'undefined method page' when model defined in separate gem - ruby

I have a simple logging application consisting of ruby scripts and a "read-only" Rails application that reads from the MongoDB documents. To keep the models consistent they both use a common gem where the Mongoid documents have been defined.
The problem I'm having is that Mongoid documents that are defined in the gem are not getting the Kaminari decoration. In other words (simplified as much as possible).
# User is a Mongoid document defined in the Rails app (i.e. standard behavior)
require 'kaminari'
class UsersController < ApplicationController
def index
User.page(params[:pg]) # works great
end
end
but
# SharedLogging::LogEntry is a Mongoid document defined in a separate gem
require 'kaminari'
class LogEntriesController < ApplicationController
def index
SharedLogging::LogEntry.page(params[:pg]) # undefined method 'page' for ...
end
end
I think the solution is to do something in /config/initializers/kaminari_config.rb to force the pagination to be applied to the shared models but I haven't been able to stumble across the correct solution.
Alternately, I've also tried adding Kaminari as a dependency in the shared gem, but no luck there.

It seems to be resolved with the same solution described here: https://github.com/collectiveidea/delayed_job_mongoid/issues/10
In my kaminari_config.rb I've added the following lines:
SharedLogging::LogEntry.send(:include, Kaminari::MongoidExtensions::Document)
SharedLogging::LogEntry.send(:include, Kaminari::MongoidExtensions::Criteria)
The first line is required if I do SharedLogging::LogEntry.page(params[:pg]) the second if I apply a scope first (e.g. SharedLogging::LogEntry.by_date(params[:dt]).page(params[:pg]) ).
The biggest problem is that I need both lines for each model in my gem; and there are a lot of models.

Rather than manually extending, use Kaminari's hooks initializer. There are details in another answer I posted:
undefined method page for #<Array:0xc347540> kaminari "page" error. rails_admin

Related

Using Test::Unit::Data

I am trying to create some data driven API tests using Test::Unit for ruby. The eventual intention is to read a series of test cases in from a .csv file. In looking for something that would be the equivalent of #dataprovider for testng, I found a class called Data which looks like exactly what I need.
http://www.rubydoc.info/github/test-unit/test-unit/Test/Unit/Data/ClassMethods
However, when I tried to create a test case to try to get it working, I get an error saying
"initial_test.rb:4:in <class:InitialTest>': undefined methoddata' for InitialTest:Class (NoMethodError)
"
code I was running:
require "test/unit"
class InitialTest < Test::Unit::TestCase
data("true" => [true],
"false" => [false])
def test_true_is_true(data)
value = data
assert(false, "FAIL!")
end
end
I can't seem to find any mention of the Data class outside of the documentation. Has anyone used this class? Am I missing something?
I'm not familiar with this module in particular, but since data is defined as an instance method on Test::Unit::Data and Test::Unit::Data is a Module, this works:
class YourTest < Test::Unit::TestCase
include Test::Unit::Data
data(…)
end
This said, you're going to want to take a closer look at the docs you linked since your example usage is looking like copy-pasta.
Turns out that the problem was that I was using an older version of Ruby that did not include the class I was trying to use. Updating to a newer version solved the problem.

Want help regarding 'module' usage in ruby project (using 3rd party gem of 'ruby-jmeter'

I am trying to create performance automation framework for my company . Beinbg newbie to ruby field , I thought to keep it simple . Here is structure for performance framewrok
I do have multiple ruby files , as request.rb,payload.rb etc in 'common' folder(as these are containing some utilities) and then my test in test.rb (under one of 'TestFlows->SimpleFlow->test.rb) .
See above structure for more detail
Exact Code , which I am having right now under those files are
request.rb
require 'ruby-jmeter' #(Consider any 3rd party gem )
require 'rubygems'
module Company #Note that i am using same module name 'company'
module Request
def self.send_request()
visit '192.148.1.2' # this is function defined under ruby-jmeter
end
end
end
payload.rb
require 'ruby-jmeter' #(Consider any 3rd party gem )
require 'rubygems'
module Company #Note that i am using same module 'company'
module Payload
def self.get_payload()
------- Again some 'ruby-jmeter' function calls
end
end
end
etc files as well
Test.rb
require 'ruby-jmeter' #(Consider any 3rd party gem )
require 'rubygems'
require 'require_all' #(gem to load all files from folder)
require_all '../../common/'
module Company #Note that i am using same module 'company'
test name:'GooglePerformanceTest' do
defaults domain: 'http://google.com' ,protocol: http
threads name: 'NoOfUsers',scheduler: false,continue_forever:
false, count: 2 do
Request.send_request()
end
end #end of testPlan
view_results_tree
puts "JMX FILE IS GONNA SAVED #
"+Dir.pwd+"/CreatedJMeter_DB2Navigation.jmx"
end.jmx(file: Dir.pwd+"/CreatedJMeter_DB2Navigation.jmx")
end
When I run this programme , it goes to above , I am getting errors of those (3rd party ruby gem's function undefined).
Can anyone point me out my problem regarding above structure & suggest me proper way to do this ?
edit :
I am getting below error
Test.rb:3:in `send_request': undefined method `visit ' for
company::Request:Module (NoMethodError)
Edit
Have defined my changes here & it is working fine
Facing issues while calling method of module(having object of class , contained in another ruby file)
I'm assuming you're using the gem hosted at this repository: https://github.com/flood-io/ruby-jmeter, latest release version (2.13.8).
Looking through the source code and examples, there are a couple things to think about.
The 'visit' method is an alias for a method called 'get' defined here
.
That is an object method, for an object of class RubyJmeter::ExtendedDSL. You are using module methods, and should probably consider making an object and calling the method on that.
obj = RubyJmeter::ExtendedDSL.new
obj.visit '192.148.1.2' # 'visit' is a method alias for 'get'
However, the examples listed by the gem developer follow a different pattern, calling 'visit' from within a closure (the do..end code block, known simply as a 'block' in Ruby). You could rewrite your code to build test plans and run them in this fashion.
It's not clear from what you post why you are using modules. Typically, you use 'include' within a Module or Class to mix in the gem's methods into your namespace. But since you're attempting to use module methods, I'm not sure mixing in object methods will be fruitful.
Since I can't see how your Test.rb file is run, I can't say for sure that your test code is loading your own modules. Typically a 'load' or 'include' statement would be used to load the code you wrote in request.rb and payload.rb
Personally, I'd try to follow the pattern shown by the developer of RubyJmeter; as a second approach, I'd write a class that inherits from RubyJemeter's subclass and extend its behavior to suit. My test code would initialize an object and call its methods directly. (Your Mileage May Vary.)
Updated to add: if you want your module method to stand in place of the object method mentioned, you can simply call the latter inside your method:
def self.send_request()
RubyJmeter::ExtendedDSL.new.visit '192.148.1.2'
end
Doing this essentially creates a disposable object, which is destroyed after the :visit method returns its data.
P.S. Always capitalize your class and module names. It's a Ruby best practice and your module name 'company' will raise warnings from the interpreter.

How to test a gem with RSpec that extends ActiveRecord models?

I am moving some code we use into a gem. The code allows you to create breadcrumbs on ActiveRecord models like so:
Parent < ActiveRecord::Base
has_breadcrumbs
end
My question is - how do I use Rspec in my gem to mock/stub these abstract AR objects? So essentially, I need to create 'fake' active record objets, add my has_breadcrumbs to them, then use these mocked records in my specs.
In my spec_helper.rb I'm including:
require 'rubygems'
require 'rails/all'
require 'rspec/rails'
I need to test that the gem is working correctly by ensuring my has_breadcrumbs is responding correctly and allowing me to apply settings against AR models. However, I'm finding this tricky since I don't have a DB instead I need to mock these objects somehow.
Some code examples would be great to give me an idea on what's the best practice for this sort of thing.

Injecting a scope through an association extension in Rails 2.3.17

I'm upgrading from Rails 2.3.5 to 2.3.17 and have come across a pretty obscure problem. I use the following extensions to inject a scope within an association accessor, and provider a custom builder:
module XYZFilterExtension
def in_context(context)
if proxy_owner.context == :abc && context != :admin
scoped(:conditions => {:startup => false})
else
scoped({})
end
end
end
module OtherExtension
def build_with_component_instance(attributes = nil)
attributes ||= {}
attributes.reverse_merge!(:parent_id => proxy_owner.component_instance.id)
instance = build
instance.build_component_instance
instance.attributes = attributes
instance
end
end
has_many :pages, :extend => [ABCExtension, OtherExtension]
In Rails 2.3.5 I could call:
Something.pages.in_context(:abc).build_with_component_instance
and I'd get a Page object (And it's associated component_instance, the build is complicated because it's a polymorphic association being built from the other direction).
Now I get:
undefined method `build_with_component_instance' for #<Class:0x1151dcae8>
Inspecting the scope, the only difference that I could find is that calling proxy_scope on the scope created by in_context() returns the Page model in 2.3.17 and the scope in 2.3.5.
I'm not sure where to go from here. I can't extract the scope out into a module to include in each model because I need to make a decision based on the proxy_owner in the association.
Update: It appears the problem is around extension methods not being available within the context of a scope. Pretty strange but I guess it kind of makes sense. Unfortunately both my scope definition and the build extension require knowledge of their association context. Any ideas welcome :)
I ended up not finding a way to work around this. In the end I had to avoid the bug in the specific situation in which it occurred. Fortunately it was only in a couple of places in the app.

Kaminari and Capybara conflict

I seem to have some sort of conflict between the page method of capybara and the page method of Kaminari.
That's what I guessed, anyway, here is the error :
Failure/Error: before { sign_in_as user }
ActionView::Template::Error:
wrong number of arguments (1 for 0)
# ./app/models/feed.rb:9:in `microposts'
[Rest of the backtrace]
The code sample :
class Feed
def microposts(opts = { urgent: false })
urgent = opts[:urgent]
p Microposts.where(id: 1).page # <Capybara::Session>
p Microposts.where(id: 1).page(1) # Error
end
end
If I remove the pagination, the test works fine.
I don't understand how this is possible, I guess Capybara is adding the "page" method to the Object scope, but as Kaminari add its page method to ActiveRecord::Base (if I recall correctly) it should override Capybara's one.
I did not see anyone having this kind of trouble, how is it possible ?
Thanks.
I had the same problem with Capybara 2.x
My feature specs are in the spec/feature directory. I realised from reading the Capybara documentation that there is no need to include the Capybara::DSL in your spec_helper if your using the features directory. It's already included.
There is a warning given if you include Capybara::DSL in the spec_helper that it will pollute the global namespace and this is exactly why it's a bad idea!
Check out this rspec-rails page on Capybara for details
This is a little bit of a hack but I was able to work around the problem (where Capybara 'pollutes' the object space) by undef-ing the method in my spec:
# Capybara adds a 'page' method to the Object class which conflicts with the Kaminari scope
# Remove it here to allow things to work
Object.send :undef_method, :page
I have traced back where this is happening and essentially:
The #page method comes from Capybara::DSL
The Capybara::DSL method is included into the Object class via RSpec's #configure.include method (see lib/capybara/rspec.rb).
RSpec then includes it into the 'group', however I believe this is where it drops into Object.
The solution here might just be to change the name of the method in Capybara, but I guess thats not a decision I'm willing to make :)

Resources