modules=MenuModule.all(:order => "module_seq")
modules.each do |m|
groups=m.menu_groups.all(:order => "group_seq")
groups.each do |g|
items=g.menu_items.all(:order => "item_seq")
items.each do |i|
puts i.name
end
end
end
UPDATE
How to use include with order ?
Something like MenuModule.find(:all,:include => {:menu_groups(:order => "group_seq"), :menu_items(:order => "item_seq")},:order => "module_seq")
Is it possible ?
See: http://www.arraystudio.com/as-workshop/nested-include-activerecord-option.html
MenuModule.all(:include => [{:menu_groups, :menu_items}], :order => 'module_seq,modules.group_seq,modules.groups.item_seq')
If the item_seq is not what you want to sort on, you probably can sort using the ruby sort method. The mysql order clause in a nested join only will order by one constrain in the join, as far as I am aware.
Related
Is it possible to make a Model query in rails with an include statement, but to have the "include" only if another condition occurs?
I have this code:
#families = Family.find(:all,
:conditions => family_conditions,
:select => 'families.id,families.name',
:include => families_include_array)
So the include should be there only if the families_include_array is not null.
You should add your query in an if statement
if families_include_array.is_nil?
#families = Family.find(:all,:conditions => family_conditions, :select => 'families.id,families.name')
else
#families = Family.find(:all,:conditions => family_conditions, :select => 'families.id,families.name', :include => families_include_array)
end
Or you can create your SQL request as string and send it to SQL with ActiveRecord::Base.connection.execute
UPDATE
Or you can try to override the find method
def self.find(*args)
records = super
# Manipulate records
end
I have a join table, which have 3 parameters. I want to update it, using a where-clause, something like this: (which obviously is not correct)
Grid.update(:page_id => #page_id,:thing_id => #thing_id,:number => #number ).where(:page_id => #page_id, :number => #number ).first
I need to find the record with mathing page_id and number, and then update the thing_id.
Thanks!
Jakob
Grid.where(:page_id => #page_id, :number => #number).first.
update_attributes(:page_id => ...,: thing_id => ..., :number => ...)
I am working on a Rails 2.3.9 app and my question involves both a self referencial relationship and a named_scope. This application allows users to log and share workouts. A workout can be public or private and that is designated by #workout.public == 1.
I allow users to 'follow' people. So on a current_user's dashboard I display all public workouts from users that current_user follows with the following code:
/dashboard/index.html.erb
<% current_user.friends_workouts.each do |workout| %>
<%= link_to (workout.title), workout %> <br/>
by <%= link_to (workout.user.username), workout.user %> - <%= time_ago_in_words(workout.created_at)%> ago</p>
<% end %>
user.rb
def friends_workouts
#friends_workouts ||= Workout.current.public_workouts.find_all_by_user_id(self.friends.map(&:id), :order => "created_at DESC", :limit => 3)
end
workout.rb
named_scope :public_workouts, :conditions => {:public => 1 }, :order => "created_at DESC"
I now want to add a condition to this scope as I am adding another level of sharing. Users can associate to a "box" (a gym really) through a "membership" model. So if the current_user belongs_to the same "box" as a user they follow, they should not only see the workouts marked public but also workouts where #workout.box_only == 1.
How can I affect the above to include all public workouts from followed users AND workouts from followed users where #workout.box_only == 1 and #workout.user.membership.box_id == current_user.membership.box_id. I know that syntax is incorrect but you get my point (hopefully).
UPDATE:
It also needs to be considered that :public_workouts is being called from pages that don't require a logged_in? user so in that case if the scope is trying to reference current_user it will throw an error.
UPDATE 2:
:user has_many :memberships
I believe something like the following should do it for you:
named_scope :public_workouts,
:joins => ", user, membership"
:conditions =>
"workouts.public = 1 or
membership.box_id = #{current_user.membership.box_id}",
:group => "workouts.id",
:order => "workouts.created_at DESC"
You would have to play around with this for a bit. The hard part every time I try something like this is to get the OR conditions correct. You want to get all public and those where the joined membership.box_id matches regardless of public being 1.
Edit: Admittedly this is perhaps not the most ruby way of building a query and I haven't tested it properly but something like below could also be made to work.
def self.public_workouts
query = Workout.joins(:user => { :membership })
if current_user
query.where('memberships.box_id = ? or workouts.public = 1', current_user.membership.box_id) unless current_user.membership.box_id.nil?
else
query.where('workouts.public = 1')
end
query.group('workouts.id')
query.order("workouts.created_at DESC")
return query
end
Edit2
Another alternative could be to create two separate scopes and create a class method that combines the two scopes. This class method would then be used in the view.
named_scope :box_workouts,
:joins => ", user, membership"
:conditions => "memberships.box_id = #{current_user.membership.box_id}"
:group => "workouts.id",
:order => "workouts.created_at DESC",
:select "workouts"
named_scope :public_workouts,
:conditions => :public => 1
:order => "workouts.created_at DESC"
def self.public_box_workouts
return box_workouts.merge(public_workouts).limit(3) if current_user
return public_workouts.limit(3)
end
Edit3 Not so hard, I believe something like below will work.
def self.box_and_public_workouts(user)
return public_workouts if user.nil? or user.memberships.blank?
return public_workouts + box_workouts(user.memberships.map(&:box_id))
end
named_scope :box_workouts, lambda { |box_ids| { :conditions => ['box_id IN (?)', box_ids], :order => 'created_at DESC' } }
Apologies for taking so long. I was missing confused with how the "old" way of querying the database. I went right for Rails3 :)
Anyway, I didn't want to commit anything so I tried to fork it to send a pull request but github is being rude to me tonight. Might just copy from here then.
Using RoR 2.3.8.
Here's my controller code:
class CitiesController < ApplicationController
def show
#city = City.find(params[:id])
#shops = Shop.search #city.name, {
:conditions => {:country => #city.country && (:city => #city.name || :state => #city.state)},
:page => params[:page],
:per_page => 100
}
end
end
The :conditions => {:country => #city.country && (:city => #city.name || :state => #city.state)} obviously doesn't work because I am just trying to explain what I wanna achieve.
:city and :state will be columns from Spots table, not Cities table. I want results to return either one of them fulfills the condition. But have no clue how to do it.
Thanks.
Tass has got it right - with your TS search call, it should look something like this:
def show
#city = City.find(params[:id])
#shops = Shop.search "#{#city.name} #country #{#city.country} (#city #{#city.name} | #state #{#city.state})",
:match_mode => :extended,
:page => params[:page],
:per_page => 100
}
end
You'll note I've set the match mode - Thinking Sphinx will do this automatically if you're using the :conditions argument - but when constructing the query manually, you need to set it yourself.
Place your raw search to Sphinx - you should find the correct method in the TS docu. A reference for raw search. You probably want something like
"#city_country #{#city.country} (#city_name #{#city.name} | #city_state #{#city.state})"
(I'm not sure how TS names the indexes. Check that.)
I have read the following rails guide : http://guides.rails.info/active_record_querying.html
in there exemple a client has many orders and orders belong to clients.
They explain how to find a lot of stuff from client. But if i want all orders from yesterday, with the corresponding client name, how do i retrieve the client from an order?
# controller
#orders = Order.all(:include => :client,
:conditions => ["created_at = ?", Date.today-1])
# view
<% #orders.each do |order| %>
<%= order.client.name %>
<% end %>
Edit:
If you have an specific order id, you can do your search like
#order = Order.first(id, :include => :client)
and access the client the same way
#order.client.name
today = Date.today
yesterday = today - 1.days
orders = Order.find(:all, :include => :client, :conditions => ["created_at >= :yesterday AND created_at <= :today", {:yesterday => yesterday, :today => today}])
You can now iterate orders and do order.client to retrieve the Client object. The :include => :client will make RoR automatically include the it in the query (rather than lazy loading).
You can do something like this:
orders = Order.all(:conditions => ["DATE(created_at) = DATE(?)",
:include => :client,
Time.now - 1.day])
client = orders.first.client