Can anyone please have a look what I'm doing wrong?
It's Rails 3:
class Ad < ActiveRecord::Base
belongs_to :postingtemplate
scope :active, (lambda do |ad|
Item.exists?(:postingtemplate => ad.postingtemplate_id)
end)
end
It's a scope inside Ad model, and is supposed to return all ads, for which Item exists where item.postingtemplate == ad.postingtemplate_id
UPDATE
Broke it into two scopes and it worked :)
class Ad < ActiveRecord::Base
belongs_to :postingtemplate
scope :active, where(:postingtemplate_id => Postingtemplate.active)
end
class Postingtemplate < ActiveRecord::Base
has_many :ads
scope :active, where(:id => Item.all.collect{|x| x.postingtemplate}.uniq)
end
if anyone knows a better way - feel free to tell
You can do it with a join
scope :active, lambda { |ad| joins(:postingtemplate => :items).where(:postingtemplate => {:postingtemplate_id => ad.postingtemplate_id}) }
Maybe this will work too:
scope :active, lambda { |ad| joins(:postingtemplate => :items).where(:postingtemplate => ad.postingtemplate) }
Related
When I try to write nested relation, I got bellow warning and can't get company data.
Unused Eager Loading detected
User => [:company]
Remove from your finder: :includes => [:company]
I write bellow code.
When I check about sql. it looks like to make relation with user and company.
But this controller result can't get company data.
Do you know how to resolve this issue?
controller/product.rb
def products
Product
.sale_date_between(params[:from], params[:to])
.organization(current_user.company_id)
.order('sale_date DESC')
end
models/product.rb
belongs_to :user
scope :with_user, -> { includes(:user, {user: :company}) }
scope :sale_date_between, ->(from, to) { where('sale_date_date >= ?', from).where('sale_date_date <= ?', to) }
scope :company, ->(id) { with_user.where(users: { company_id: id }) }
models/user.rb
has_many :products
models/company.rb
belongs_to :user, foreign_key: 'company_id'
I have post model
class Post < ActiveRecord::Base
acts_as_voteable
end
and Vote model
class Vote < ActiveRecord::Base
scope :for_voter, lambda { |*args| where(["voter_id = ? AND voter_type = ?", args.first.id, args.first.class.name]) }
scope :for_voteable, lambda { |*args| where(["voteable_id = ? AND voteable_type = ?", args.first.id, args.first.class.name]) }
scope :recent, lambda { |*args| where(["created_at > ?", (args.first || 2.weeks.ago)]) }
scope :descending, order("created_at DESC")
belongs_to :voteable, :counter_cache=>true,:polymorphic => true,:touch=>true
belongs_to :voter, :polymorphic => true
attr_accessible :vote, :voter, :voteable
# Comment out the line below to allow multiple votes per user.
validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]
end
when I get the post voters with these method
<% #post.voters_who_voted.each do |voter|%>
<%= voter.name %>
<% end %>
I load my database
how can I select only the user name and user id from these array?
update I changed my code I am using thumbs_up gem I pasted less code first to simplify the question
What do you mean by "load database"? If you want to select only id and name columns, then use #post.users.select([:id, :name]).each ...
Or is it about this problem (according to code that you provided)?
UPD.
voters_who_voted loads all voters and returns array https://github.com/bouchard/thumbs_up/blob/master/lib/acts_as_voteable.rb#L113. You have to add own association to Post model:
has_many :voters, :through => :votes, :source => :voter, :source_type => 'User'
It's just example, perhaps voters will clash with already existing method, if any.
Then use it here instead of voters_who_voted
did you try collect method ??
names = #post.users.collect(&:name)
ids = #post.user.collect(&:id)
If you want it to be related you can make a HASH with it. Id's mapped to the names.
Given the following code:
user_decorator.rb
Refinery::User.class_eval do
has_many :employees, :class_name => 'Refinery::Employee'
scope :active_employees,
lambda {
joins(:employees).merge(::Refinery::Employee.active)
}
end
employee.rb
module Refinery
class Employee < ActiveRecord::Base
belongs_to :user, :class_name => 'Refinery::User'
scope :active, where(:retired => false)
end
end
running rails console...
> ::Refinery::User.active_employees
=> [ .......... lots of records etc ]
> user = ::Refinery::User.where(:username => 'test').first
=> #<Refinery::User .... etc etc>
> user.active_employees
NoMethodError: undefined method `active_employees' for #<Refinery::User:0x000000051330f8>
What am I doing wrong?
A scope is related to the model, and not to an instance of that model.
If you want to do that, you have to create a method that does the same.
At least, I think so...
I'm trying to figure out how to pull data from multiple tables and making sense of it.
I have events, occurrences and venues tables.
Here are the models/associations so far:
models/event.rb:
class Event < ActiveRecord::Base
has_many :occurences, :dependent => :destroy
belongs_to :price
belongs_to :venue
validates_presence_of :venue
end
models/venue.rb:
class Venue < ActiveRecord::Base
has_many :events, :dependent => :destroy
end
models/occurence.rb:
class Occurence < ActiveRecord::Base
belongs_to :event
scope :today, lambda { where("occurence.datetime_start <= ? AND datetime_end >= ?", Time.now.end_of_day, Time.now) }
scope :this_week, lambda { where("occurence.datetime_start <= ? AND datetime_end <= ?", Time.now.end_of_day, Time.now.at_end_of_week) }
scope :next_week, lambda { where("occurence.datetime_start > ? AND datetime_end < ?", Time.now.at_end_of_week, Time.now.at_end_of_week + 1.weeks) }
scope :this_month, lambda { where("occurence.datetime_start <= ? AND datetime_end >= ?", Time.now.end_of_day, Time.now.at_end_of_month) }
scope :next_month, lambda { where("occurence.datetime_start >= ? AND datetime_end <= ?", Time.now.at_beginning_of_month + 1.months, Time.now.at_end_of_month + 1.months) }
end
What I'd like to show in my view/events/index.html.erb is a table of all events happening today and I like to do something like:
<% #events.today.each do |event| %>
and display all the events that match the .today scope.
I tried moving the scope to the event model to no avail. Should I move the scopes to the event model? So far my searches have lead me to
"Using scope to return results within multiple DateTime ranges in ActiveRecord"
and
"Multiple scope in rails 3.0" but I can't really make anything out of it.
Can anyone point me in the right direction? Should I create a new function in my event model?
class Event < ActiveRecord::Base
has_many :occurences, :dependent => :destroy
belongs_to :price
belongs_to :venue
validates_presence_of :venue
scope :today, lambda {
joins(:occurences).where("datetime_start <= ? AND datetime_end >= ?", Time.now.end_of_day, Time.now)
}
end
If you want your syntax to work like:
#events.today
Then the scope would have to be in the Event model.
If you're OK with:
#event.occurences.today
then you're OK now, i.e.:
#events = Event.all
#events.each do |ev|
ev.occurences.today.each do |oc|
end
end
I have a simple parent object having many children. I'm trying to figure out how to use a named scope for bringing back just parents with specific numbers of children.
Is this possible?
class Foo < ActiveRecord::Base
has_many :bars
named_scope :with_no_bars, ... # count of bars == 0
named_scope :with_one_bar, ... # count of bars == 1
named_scope :with_more_than_one_bar, ... # count of bars > 1
end
class Bar < ActiveRecord::Base
belongs_to :foo
end
I'm hoping to do something like Foo.with_one_bar
I could write methods on the parent class for something like this, but I'd rather have the power of the named scope
class Foo < ActiveRecord::Base
has_many :bars
# I don't like having the number be part of the name, but you asked for it.
named_scope :with_one_bar, :joins => :bars, :group => "bars.foo_id", :having => "count(bars.foo_id) = 1"
# More generically...
named_scope :with_n_bars, lambda {|n| {:joins => :bars, :group => "bars.foo_id", :having => ["count(bars.foo_id) = ?", n]}}
named_scope :with_gt_n_bars, lambda {|n| {:joins => :bars, :group => "bars.foo_id", :having => ["count(bars.foo_id) > ?", n]}}
end
Called like so:
Foo.with_n_bars(2)
I would use the counter cache for this. Therefore you need the following migration:
class AddBarCount < ActiveRecord::Migration
def self.up
add_column :foos, :bars_count, :integer, :default => 0
Foo.reset_column_information
Foo.all.each do |p|
p.update_attribute :bars_count, p.bars.length
end
end
def self.down
remove_column :foos, :bars_count
end
end
Than you need too change you Bar model like this:
class Bar < ActiveRecord::Base
belongs_to :foo, :counter_cache => true
end
Now the count of bars is cached in the foo model, that will speed up your queries for the count of bars.
Your named_scopes then have too look like this:
#rails 2
named_scope :with_no_bars, :conditions => { :bars_count => 0 }
named_scope :with_one_bar, :conditions => { :bars_count => 1 }
named_scope :with_more_than_one_bar, :conditions => ["bars_count > 1"]
#rails 3 & ruby 1.9+
scope :with_no_bars, where(bars_count: 0)
scope :with_one_bar, where(bars_count: 1)
scope :with_more_than_on_bar, where("bars_count > 1")
#rails 4* & ruby 1.9+
scope :with_no_bars, -> { where(bars_count: 0) }
scope :with_one_bar, -> { where(bars_count: 1) }
scope :with_more_than_one_bar, -> { where("bars_count > 1") }
That way you can save time counting bars for each foo every time you make such a request.
I got this idea watching the railscast about counter cache: http://railscasts.com/episodes/23-counter-cache-column
* What's new in Active Record [Rails 4 Countdown to 2013]