paginate_by_sql and Rails3.0.0Beta4 - pagination

I am trying to port an existing rails app running rails 2.3.8 to
3.0.0beta4.
I currently use this paginate_by_sql hack
module ActiveRecord
class Base
def self.find_by_sql_with_limit(sql, offset, limit)
sql = sanitize_sql(sql)
add_limit!(sql, {:limit => limit, :offset => offset})
find_by_sql(sql)
end
def self.count_by_sql_wrapping_select_query(sql)
sql = sanitize_sql(sql)
count_by_sql("select count(*) from (#{sql}) as x")
end
end
end
The add_limit! method has been removed from ActiveRecord::Base class.
Are there any work arounds for this? Any alternatives to doing
pagination by SQL in Rails 3.0.0?
Thanks

I know this is old, but I just stumbled across a similar issue and hopefully can help someone else. To fix this, make sure you are using the Rails 3 compatible version of will_paginate by adding
gem "will_paginate", "~> 3.0.pre2"
to your Gemfile

hmm, fwiw, this seems to work.
module ActiveRecord
class Base
def self.find_by_sql_with_limit(sql, offset, limit)
sql = sanitize_sql(sql)
find_by_sql(sql + " LIMIT #{offset},#{limit}")
end
def self.count_by_sql_wrapping_select_query(sql)
sql = sanitize_sql(sql)
count_by_sql("select count(*) from (#{sql}) as x")
end
end
end
You can save it in Application Controller. It has to be loaded first before any ActiveRecord class is loaded, so ApplicationController would be a good place.

Related

Rails cucumber uninitialized constant User (NameError)

I'm starting with BDD (cucumber + capybara + selenium chromedriver) and TDD (rspec) with factory_bot and I'm getting an error on cucumber features - step_definitions.
uninitialized constant User (NameError)
With TDD, everything is ok, the factory bot is working fine. The problem is with the cucumber.
factories.rb
FactoryBot.define do
factory :user_role do
name {"Admin"}
query_name {"admin"}
end
factory :user do
id {1}
first_name {"Mary"}
last_name {"Jane"}
email {"mary_jane#gmail.com"}
password {"123"}
user_role_id {1}
created_at {'1/04/2020'}
end
end
support/env.rb
require 'capybara'
require 'capybara/cucumber'
require 'selenium-webdriver'
require 'factory_bot_rails'
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome)
end
Capybara.configure do |config|
config.default_driver = :selenium
end
Capybara.javascript_driver = :chrome
World(FactoryBot::Syntax::Methods)
And the problem is happening here
support/hooks.rb
Before '#admin_login' do
#user = create(:user)
end
step_definitions/admin_login.rb
Given("a registered user with the email {string} with password {string} exists") do |email, password|
#user
end
I don't know why, but I can't access the user using cucumber and factory_bot.
Anybody could help me please?
I think I need to configure something on the cucumber.
What do you think guys?
First of all Luke is correct about this being a setup issue. The error is telling you that the User model cannot be found which probably means Rails is not yet loaded. I can't remember the exact details of how cucumber-rails works but one of the things it does is to make sure that each scenario becomes an extension of a Rails integration test. This ensures that all of the Rails auto-loading has taken place and that these things are available.
Secondly I'd suggest you start simpler and use a step to create your registered user rather than using a tag. Using tags for setup is a Cucumber anti-pattern.
Finally, and more controversially I'd suggest that you don't use factory-bot when cuking. FactoryBot uses a separate configuration to create model objects directly in the datastore. This bypasses any application logic around the creation of these objects, which means the objects created by FactoryBot are going to end up being different from the objects created by your application. In real life object creation involves things like auditing, sending emails, conditional logic etc. etc. To use FactoryBot you either have to duplicate that additional creation logic and behavior or ignore it (both choices are undesirable).
You can create objects for cuking much more effectively (and quicker) by using the following pattern.
Each create method in the Rails controller delegates its work to a service object e.g.
UserController
def create
#user = CreateUserService.new(params).call
end
end
Then have your cukes use a helper module to create things for you. This module will provide tools for your steps to create users, using the above service
module UserStepHelper
def create_user(params)
CreateUserService.new(default_params.merge(params))
end
def default_params
{
...
}
end
end
World UserStepHelper
Given 'there is a registered user' do
#registered_user = create_user
end
and then use that step in the background of your feature e.g.
Background:
Given there is a registered user
And I am an admin
Scenario: Admin can see registered users
When I login and view users
Then I should see a user
Notice the absence of tagging here. Its not desirable or necessary here.
You can see an extension of this approach in a sample application I did for a CukeUp talk in 2013 here https://github.com/diabolo/cuke_up/commits/master. If you follow this commit by commit starting from first commit at the bottom you will get quite a good guide to setting up a rails project with cucumber in just the first 4 or 4 commits. If you follow it through to the end (22 commits) you'll get a basic powerful framework for creating and using model objects when cuking. I realize the project is ancient and that obviously you will have to use modern versions of everything, but the principles still apply, and I use this approach in all my work and having been doing so for at least 10 years.
So if you're using rails, it's probably advised to use cucumber-rails over cucumber. This is probably an issue where your User models have not been auto-loaded in.
Cucumber auto-loads all ruby files underneath features, with env.rb first, it's almost certainly an issue with load order / load location

nodejs gremlin update if exist or else create

I am using nodejs gremlin against AWS neptune, the requirement is to update properties if vertice exist, or else, create a new vertice, i tried below
g.V().has('event','id','1').
fold().
coalesce(unfold(),
addV('event').property('id','1'))
but I got 'unfold is not defined' error, how do I resolve this?
You probably just need to import unfold() properly. Some common imports for working with Gremlin can be found here but in your case I think you just need to do:
const __ = gremlin.process.statics
and then refer to unfold() as __.unfold() - or just import unfold() as a function explicitly to use it as you were using it.

undefined method `query_parameters' in Active Admin show/panel/table_for

I have something very similar working in another model, so there must be something minor that I'm overlooking.
I have a model Request that has_many RequestState(s), which in return has_one.
ActiveAdmin.register Request do
show do |ad|
...
panel "Request States" do
table_for ad.request_states do
column :id
column :actor_id
column :state
column :created_at
end
end
end
end
When I try to load the page, I get:
NoMethodError in Admin::Requests#show
undefined method `query_parameters' for #<Request:0x000001062040c0>
and it's complaining about each of the "column" lines.
The underlying data seems fine since the following and similar work correctly from the rails console:
Request.find(37).request_states.pluck(:id)
I had the same problem in ActiveAdmin 1.0, and solved it without renaming my Rails model. I just renamed the resource within ActiveAdmin:
ActiveAdmin.register Request, as: "BookRequest" do ...
This also forced me to rename my path helpers, e.g., admin_request_path became admin_book_request_path everywhere. Much less intrusive than renaming the Rails model though.
See https://activeadmin.info/2-resource-customization.html#rename-the-resource
Request is a reserved Class by Rails. I think you have to use something else class name.
http://api.rubyonrails.org/classes/ActionDispatch/Request.html
But not sure, because it's namespaced...
I was getting this issue and, for me at least, it turned out to be the assignment of #request in a before_filter called in my ApplicationController:
def newsletter
#request = NewsletterRequest.new
end
Changed the #request to #newsletter_request and avoided the collision.

Can't access delete method on Slick query

This is very very very frustrating. I have been trying to pick up Slick for a while, and obstacles just keep coming. The concept of Slick is really awesome, but it is very difficult to learn, and unlike Scala, it doesn't have "beginner", "intermediate", and "advanced" style where people in all stages can use it easily.
I'm using Play-Slick (Slick 2.0.0) https://github.com/freekh/play-slick, following its Multi-DB cake example: https://github.com/freekh/play-slick/tree/master/samples/play-slick-cake-sample/app
For some reason, first, ddl does not belong to TableQuery, unlike the claim in the document: "The TableQuery‘s ddl method creates DDL". This shows through the scaladoc: http://slick.typesafe.com/doc/2.0.0/api/#scala.slick.lifted.TableQuery There is no ddl method there.
Second, my slick.lifted.Query can't generate delete method. It works fine with list, but not with delete.
val S3Files = TableQuery[S3Files]
S3Files.where(_.url === url).delete
This wouldn't work...then I tried:
val query = (for(s <- S3Files if s.url === url) yield s)
query.list //this works
query.delete //ehh?? can't find the method
val query2 = (for(s <- S3Files if s.url === url))
query2.delete //still won't work
Well...since Slick uses a very complicated (at least to newbies) implicit type conversion system, I don't really know what went wrong.
I tried it by simply adding
Cats.ddl.create
Cats.filter(_.name===cat.name).delete
to play-slick-cake-sample/app/controllers/Application.scala. Works fine for me.
Looks like you are using the wrong imports. Look at https://github.com/freekh/play-slick/blob/master/samples/play-slick-sample/app/controllers/Application.scala and mimic the imports.
slick 0.8.1 and slick 2.1.0 and I had the same Issue.
The reason why delete is not available on the Query is cause the play-slick Query does not contain a equivalent method of the delete method from slick Query.
I solved this Problem by changing to the original slick Driver
//import play.api.db.slick.Config.driver.simple._ //play-slick extensional Driver
import slick.driver.PostgresDriver.simple._ //original slick Driver

subsonic query problem

I'm using subsonic 2.2 in an app. I'm running a little complicated query in I have used both "And" and "Or" for a field, I'm little confused about how it is going to be translated into sql statement
MytableCollection col = DB.Select().From("mytable").Where("prop1").IsEqualTo(obj.prop1)
.And("prop2").IsEqualTo(obj.prop2)
.And("prop3").IsEqualTo(obj.prop3)
.Or("prop1").IsEqualTo(1)
.ExecuteAsCollection<MytableCollection>();
I want to perform query like this.
select * from mytable where (prop1=obj.prop1 or prop1=1) and prop2=obj.prop2 and prop23=obj.prop3
As Andra says you can use AndExpression. This should do what you want:
MytableCollection col = DB.Select().From(Mytable.Schema)
.Where(Mytable.Columns.Prop2).IsEqualTo(obj.prop2)
.And(Mytable.Columns.Prop3).IsEqualTo(obj.prop3)
.AndExpression(Mytable.Columns.Prop1).IsEqualTo(obj.prop1)
.Or(Mytable.Columns.Prop1).IsEqualTo(1)
.ExecuteAsCollection<MytableCollection>();
N.B. using MyTable.Schema and MyTable.Columns will catch a lot of issues at compile time if you rename tablees and will save errors caused by mistyping
Something that is REALLY useful to know about is also the following two methods to call in your query building:
.OpenExpression()
and
.CloseExpression()
Mix those bad buoys and you have a lot better control over knowing where things start and finish
you can use expression in subsonic 2.2.
MytableCollection col = new Select(Mytable.Schema)
.WhereExpression("prop1").IsEqualTo(obj.prop1).Or("prop1").IsEqualTo(1)
.AndExpression("prop2").IsEqualTo(obj.prop2)
.AndExpression("prop3").IsEqualTo(obj.prop3)
.ExecuteAsCollection<MytableCollection>();

Resources