eric-guo / where-or Goto Github PK
View Code? Open in Web Editor NEWWhere or function backport from Rails 5 for Rails 4.2
License: MIT License
Where or function backport from Rails 5 for Rails 4.2
License: MIT License
I was pretty eager to utilize this gem, but have run into a snag.
# User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :wikis
# has_many :wikis, through: :collaborators
has_many :collaborators
has_many :collaborated_wikis, through: :collaborators, source: :wiki
after_initialize :init
def init
self.role ||= 'standard'
end
def admin?
role == 'admin'
end
def premium?
role == 'premium'
end
def standard?
role == 'standard'
end
def publicize_wikis
self.wikis.each { |wiki|
wiki.update_attributes(private: false)
wiki.collaborators.delete_all
}
end
end
# Wiki.rb
class Wiki < ActiveRecord::Base
belongs_to :user
has_many :collaborators
has_many :users, through: :collaborators
has_paper_trail :only => [:title, :body]
has_permalink
after_initialize :init
def init
self.private = false if self.private.nil?
end
def candidates
User.where.not(id: self.users).where.not(id: self.user).where.not(role: 'admin')
end
scope :public_wikis, -> { where(private: false) }
end
# Collaborator.rb
class Collaborator < ActiveRecord::Base
belongs_to :user
belongs_to :wiki
end
# wiki_policy.rb
class WikiPolicy < ApplicationPolicy
def index?
true
end
def show?
super && ( (!record.private) || (record.user == user || user.in?(record.users)) || (user.present? && user.admin?) )
end
def edit?
show?
end
def destroy?
user.present? && (record.user == user || user.admin?)
end
def private?
user.present? && ((user.premium? && (record.user == user || record.new_record?)) || user.admin?)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
wikis = []
if user.present? && user.admin?
wikis = scope.all
elsif user.present? && user.premium?
# Here lies the issue - Incompatible relations
wikis = scope.public_wikis.or(user.wikis).or(user.collaborated_wikis)
else
wikis = scope.public_wikis
end
wikis
end
end
end
So User has_many wikis that they own, and has_many collaborated wikis through collaborator. Wiki's has many users through collaborator. When I try:
wikis = scope.public_wikis.or(user.wikis).or(user.collaborated_wikis)
I get an error from user.collaborated_wikis, which should return the relation of wikis related to this user. user.wikis works the same, by providing the wikis owned by user through collaborators. If I take out the collaborated_wikis call, even though scope.public_wikis and user.wikis are of different classes (ActiveRecord_Relation vs ActiveRecord_Associations_CollectionProxy, respectively) they play well together. If you look at the class of user.collaborated_wikis, it is that of ActiveRecord_Associations_CollectionProxy. Going into the rails console, I can see that the result of user.collaborated_wikis is a list of all the wikis that the user collaborates on, so I know the HMT relation works, I just can't figure out why the gem is saying that the structures are incompatible. Any ideas?
I just installed where-or gem in a brand new Rails 4.2 application and when I try to run my specs I got the following error:
bundler: failed to load command: rspec (/bundle/bin/rspec)
Bundler::GemRequireError: There was an error while trying to load the gem 'where-or'.
Gem Load Error is: nil is not a symbol
Backtrace for gem load error is:
/bundle/gems/where-or-0.1.4/lib/where-or.rb:95:in `private'
/bundle/gems/where-or-0.1.4/lib/where-or.rb:95:in `<module:QueryMethods>'
/bundle/gems/where-or-0.1.4/lib/where-or.rb:28:in `block in <top (required)>'
/bundle/gems/activesupport-4.2.7.1/lib/active_support/lazy_load_hooks.rb:38:in `instance_eval'
/bundle/gems/activesupport-4.2.7.1/lib/active_support/lazy_load_hooks.rb:38:in `execute_hook'
/bundle/gems/activesupport-4.2.7.1/lib/active_support/lazy_load_hooks.rb:28:in `block in on_load'
/bundle/gems/activesupport-4.2.7.1/lib/active_support/lazy_load_hooks.rb:27:in `each'
/bundle/gems/activesupport-4.2.7.1/lib/active_support/lazy_load_hooks.rb:27:in `on_load'
/bundle/gems/where-or-0.1.4/lib/where-or.rb:16:in `<top (required)>'
/usr/local/bundle/gems/bundler-1.13.6/lib/bundler/runtime.rb:91:in `require'
/usr/local/bundle/gems/bundler-1.13.6/lib/bundler/runtime.rb:91:in `block (2 levels) in require'
/usr/local/bundle/gems/bundler-1.13.6/lib/bundler/runtime.rb:86:in `each'
/usr/local/bundle/gems/bundler-1.13.6/lib/bundler/runtime.rb:86:in `block in require'
/usr/local/bundle/gems/bundler-1.13.6/lib/bundler/runtime.rb:75:in `each'
/usr/local/bundle/gems/bundler-1.13.6/lib/bundler/runtime.rb:75:in `require'
/usr/local/bundle/gems/bundler-1.13.6/lib/bundler.rb:106:in `require'
...
Looking at lib/where-or.rb:95 it seems that something is wrong as there are 2 times private
and the first time, there is method definition on the same line.
Something like, in case your notes are too far away and you are feeling especially low on coffee:
gem build where-or.gemspec
gem push where-or-0.1.2.gem
Thanks!
class Post < ActiveRecord::Base
has_many :comments
default_scope -> { where(deleted_at: nil) }
end
class Comment < ActiveRecord::Base
belongs_to :post, -> { unscope(where: :deleted_at) }
end
Eager-loading an unscoped association generates an empty WHERE clause in combination with the where-or
gem:
irb(main):001:0> Comment.includes(:post)
Comment Load (0.2ms) SELECT "comments".* FROM "comments"
Post Load (0.9ms) SELECT "posts".* FROM "posts" WHERE () AND "posts"."id" IN (1)
ActiveRecord::StatementInvalid: SQLite3::SQLException: near ")": syntax error: SELECT "posts".* FROM "posts" WHERE () AND "posts"."id" IN (1)
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.11/lib/sqlite3/database.rb:91:in `initialize'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.11/lib/sqlite3/database.rb:91:in `new'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.11/lib/sqlite3/database.rb:91:in `prepare'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/sqlite3_adapter.rb:284:in `block in exec_query'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract_adapter.rb:484:in `block in log'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract_adapter.rb:478:in `log'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/sqlite3_adapter.rb:281:in `exec_query'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract/database_statements.rb:356:in `select'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract/database_statements.rb:32:in `select_all'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract/query_cache.rb:70:in `select_all'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/querying.rb:39:in `find_by_sql'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/relation.rb:639:in `exec_queries'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/relation.rb:515:in `load'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/relation.rb:243:in `to_a'
from .rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/relation/delegation.rb:46:in `to_ary'
... 27 levels...
Compared to stock ActiveRecord:
irb(main):001:0> Comment.includes(:post)
Comment Load (1.2ms) SELECT "comments".* FROM "comments"
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" IN (1)
=> #<ActiveRecord::Relation [#<Comment id: 1, post_id: 1, body: "Lorem ipsum", deleted_at: nil, created_at: "2016-09-29 08:45:52", updated_at: "2016-09-29 08:45:52">]>
Using Rails v4.2.7.1. Where-or v0.1.2 and master exhibit the same behavior.
Rails: 4.2.7.1
Ruby: 2.2.5p319
I have the following line
return query.where(scope_hash.inject(query) { |query, (scope_name, ids)| query.or(query.public_send(scope_name, ids)) })
Currently I am getting Relation passed to #or must be structurally compatible
. In doing some research, I came across rails/rails#24055, wherein the proposed solution is rails/rails#24055 (comment). When comparing where-or.rb
to the github link, it seems the change is implemented; however, I wanted to get a second opinion. Is there anything that can be done to the gem? Or does my issue lie within my own code?
When chaining .or
with .all
I would expect the result to be .all
.
With where-or gem:
> Post.where(id: 1).or(Post.all).to_sql
=> "SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"id\" = 1 ORDER BY name ASC"
In Rails 5:
> Post.where(id: 1).or(Post.all).to_sql
=> "SELECT \"posts\".* FROM \"posts\""
I installed the gem and immediately hit this error
I am using rails-4.2.10
TypeError: Cannot visit ActiveRecord::Relation::WhereClause
See https://github.com/myabc/where-or-example and https://gist.github.com/bf4/84cff9cc6ac8489d769e#gistcomment-1593871 for a reproduction.
Hi, are there any plans to introduce tests in to this library? Would love to see that before dropping this into our project. Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.