This is my loop. On my region page I show all the cities with there activities, events etc
- #cities.each do |city|
%li
%h4.h6.icon_mappoint
= link_to city.name, region_city_path(#region, city)
%ul
- city.events.each do |thing|
%li
= link_to event.name, region_city_event_path(#region, city, event)
%ul
- city.activities.each do |activity|
%li
= link_to activity.name, region_city_activity_path(#region, city, activity)
Each event and activity model has a attribute in the DB called active. (boolean). And want to show only the active events and activities in the view.
My controller looks like this now.
def show
#region = Region.find(params[:id])
#cities = #region.cities
end
Models
region has_many cities
city has_many events, activities
How can I show only the active events, activities in the each loop?
If you add a scope to your Event and Activity models
scope :active, where(:active => true)
you can write your views like
city.events.active.each do |thing|
and
city.activities.active.each do |activity|
Instead of city.events.each use city.events.select { |x| x.active }.each.
Related
I do have a more elaborate index method in my events controller
def index
if params[:q]
params[:q][:combinator] = "and"
params[:q][:groupings] = []
split_geo = params[:q][:address_or_city_or_state_or_country_or_continent_cont_all].split((/(,\s*)+/))
split_geo.map! do |a|
I18n.transliterate a
end
split_geo.each_with_index do |word, index|
params[:q][:groupings][index] = { address_or_city_or_state_or_country_or_continent_cont_all: word }
end
end
#q = Event.ransack(params[:q])
#pagy, #events = pagy(#q.result(distinct: true))
end
In my events index page I have:
<h2>Upcoming Events</h2>
<br>
<%== pagy_bootstrap_nav(#pagy) %>
<br>
<div class="event-list-wrapper">
<% #events.upcoming_events.each do |event| %>
<%= render 'event', event: event %>
<% end %>
</div>
When I remove my upcoming_events scope, the records will display correctly.
In my event.rb model I have:
scope :upcoming_events, -> { where('event_start_date > ?', Time.now).or(where('event_end_date > ?', Date.yesterday)) }
Am I missing something in order to get pagy with work with my event scope?
I have four loops in my haml document for testing purposes with the only difference being the order of the elements.
Am I somehow able to put the logic in my controller and list the whole 'insidyness' of the loop only once in my haml document?
Currently I have everything duplicated 4 times and ya know, that feels bad. :)
For instance:
- #loop.where(featured: true).order("RANDOM()").limit(4).each do |item|
%li
%h1 This is an example
- #loop.order(:cached_votes_up => :desc).limit(4).each do |item|
%li
%h1 This is an example
- #loop.order(:impressions_count => :desc).limit(4).each do |item|
%li
%h1 This is an example
- #loop.order("created_at DESC").limit(4).each do |item|
%li
%h1 This is an example
Controller:
def index
#loop = Item.all
end
I would like to reduce my Haml Code to something like this and move the rest in the Controller:
- #loop.each do |item|
%li
%h1 This is an example
Thanks in advance for each answer!
You can't render the view multiple times but you could do something like this.
def index
#loops = [
Item.where(featured: true).order("RANDOM()"),
Item.order(:cached_votes_up => :desc),
Item.order(:impressions_count => :desc),
Item.order("created_at DESC")
]
end
And then in the template
- #loops.each do |loop|
- loop.limit(4).each do |item|
%li
%h1 This is an example
in Item model class:
scope :featured_with_random_order_desc, ->(limit_value) { where(featured: true).order("RANDOM()").limit(limit_value) }
scope :by_cached_votes_order_desc, ->(limit_value) { order(:cached_votes_up => :desc).limit(limit_value) }
scope :by_impression_count_order_desc, ->(limit_value) { order(:impressions_count => :desc).limit(limit_value) }
scope :by_created_at_desc, ->(limit_value) { order("created_at DESC").limit(limit_value) }
In your views:
- #loop.featured_with_random_order_desc(4).each do |item|
%li
%h1 This is an example
- #loop.by_cached_votes_order_desc(4).each do |item|
%li
%h1 This is an example
- #loop.by_impression_count_order_desclimit(4).each do |item|
%li
%h1 This is an example
- #loop.by_created_at_desc.limit(4).each do |item|
%li
%h1 This is an example
You can go one more step further and create variable for each loop in your controller:
def index
#loop_featured = Item.featured_with_random_order_desc(4)
#loop_cached_votes = Item.by_cached_votes_order_desc(4)
#loop_impression_counts = Item.by_impression_count_order_desclimit(4)
#loop_by_created = Item.by_created_at_desc(4)
end
and use them in view:
- #loop_featured.each do |item|
%li
%h1 This is an example
- #loop_cached_votes.each do |item|
%li
%h1 This is an example
- #loop_impression_counts.each do |item|
%li
%h1 This is an example
- #loop_by_created.each do |item|
%li
%h1 This is an example
You can use union_scope from ActiveRecord
#item.rb
include ActiveRecord::UnionScope
scope :by_random, -> { where(featured: true).order("RANDOM()").limit(4) }
scope :by_cached_votes, ->{ order(:cached_votes_up => :desc).limit(4) }
scope :by_impression_count, ->{ order(:impressions_count => :desc).limit(4) }
scope :by_created_at, ->{ order("created_at DESC").limit(4) }
scope: all_conditions, -> { union_scope(by_random, by_cached_votes,by_impression_count,by_created_at}
your controller
#item = Item.all_conditions
your view:
- #loop.all_conditions.each do |item|
I'm a beginner trying out some aspects pertaining to enrollments in my rails app. Users have many enrollments; enrollments belong to a lesson; enrollments have many word_expositions and scrambled_words.
I wrote a helper method in the lessons controller to produce a list of enrolled users, to display in each lesson show page:
helper_method :enrolled_users
def enrolled_users
lesson = Lesson.find(params[:id])
enrollments = lesson.enrollments
enrolled_users = enrollments.map { |enrollment| enrollment.user }
end
I am now trying to implement a completed_expos helper so that I can indicate next to each user whether they have completed the expositional component of my app. What I have is:
helper_method :completed_expos
def completed_expos
lesson = Lesson.find(params[:id])
completed_expos = enrolled_users.map do |user|
current_enrollment = lesson.enrollment_for(user)
all_expos = current_enrollment.word_expositions
all_expos.all? { |expos| expos.completed == true }
end
end
I would like to add a notice next to each listed user regarding whether they completed the expos. So what I tried is:
<% enrolled_users.each do |user| %>
<ul>
<li><%= user.username %></li>
<% if completed_expos.include?(user) %>
completed
<% end %>
</ul>
<% end %>
but the effect is that, although enrolled users are listed, there is no indication as to expo completion in those places where it should list it. How can I go about selecting this subgroup of users?
From what I can get from your code is that your "completed_expos" method will always return an array of Boolean values (true, false) rather than a list of users, so it could never include the user you specify.
I guess what you might want to do was to use select instead of map.
enrolled_users.select do |user|
current_enrollment = lesson.enrollment_for(user)
all_expos = current_enrollment.word_expositions
all_expos.all? { |expos| expos.completed == true }
end
Also, let me say that you don't need to assign the values in each of your methods to a variable with the same name as the method. Eg.
def enrolled_users
lesson = Lesson.find(params[:id])
enrollments = lesson.enrollments
enrolled_users = enrollments.map { |enrollment| enrollment.user }
end
Could be
def enrolled_users
lesson = Lesson.find(params[:id])
enrollments = lesson.enrollments
enrollments.map { |enrollment| enrollment.user }
end
The problem is the helper wasn't returning a user, as to map it into the array:
helper_method :completed_expos
def completed_expos
lesson = Lesson.find(params[:id])
completed_expos = enrolled_users.map do |user|
current_enrollment = lesson.enrollment_for(user)
all_expos = current_enrollment.word_expositions
user if all_expos.all? { |expos| expos.completed == true }
end
end
My url paths are this
/locale/country/
/locale/country/region/
models:
class Region
belongs: country
end
class Country
has_many: regions
end
a foreign-key country_id in regions table
This is a part of a nav partial in the layout file.
//block region
- if params[:region].present?
%ul.thumbnails
- #region.tags.find_each(:conditions => "active_house = true") do |a|
%li.span2
.thumbnail
- a.attachments.limit(1).each do |b|
= image_tag(b.file.url)
.caption
%p
#{link_to a.h1, tag_country_region_houses_path(#country, #region, a.name), :class => 'btn-nav', class: active_class?(tag_houses_path(a.name))}
//block country
- else
%ul.thumbnails
- #country.tags.find_each(:conditions => "active_house = true") do |a|
%li.span2
.thumbnail
- a.attachments.limit(1).each do |b|
= image_tag(b.file.url)
.caption
%p
#{link_to a.h1, tag_country_houses_path(#country, a.name), :class => 'btn-nav', class: active_class?(tag_houses_path(a.name))}
When the visitor is on the path /local/country i want show block country and when the vistor is on /locale/country/region i want to show block region.
I thought if params[:region].present? will do the trick. But no....how can i realize this?
Before the line
- if params[:region].present?
In your view, try ptinting the lines,
- p params[:region]
- p params[:region].present?
that could give you some clue about the behaviour.
Try doing this:
if params.has_key?(:region)
or if it exists but contains a nil you could test it:
unless params[:region].nil?
Is it not supposed to be
class Region
belongs_to: country
end
instead of
class Region
belongs: country
end
Cheers
I have Awards and Categories, joined with Awards_Categories
I have 2 Categories.
I need to find all the Awards that have Category.id = 1, but not Category.id =2. Some categories have one or the other, some have just one. I want a list of the Awards that have category 1 but not category 2.
I have a scope:
scope :in_categories, lambda { |categories|
joins(:categories).
where(:awards_categories => { :category_id => categories } ).
select("DISTINCT awards.*")
}
And this works with a query like:
#awardsall = Award.in_categories([1 && 2]).order("name ASC")
I have tried
#awards_store = Award.in_categories([1]).order("name ASC")
With:
<% #awards_store.each do |store| %>
<li><%= link_to store.name, award_path(store), :title => store.info %> |
<% store.categories.each do |cat| %>
<%= cat.id%>
<% end %>
</li>
<% end %>
EDIT---
I know the block is not what I need. it is just my attempt at finding a way to make it work.
And while this lists all the awards, and all the award categories its still grabbing awards that have category.id = 2 because some awards have both
any ideas?
Sorry, didn't test it, but the main idea is to count the rows in the connecting table.
scope :in_categories, lambda { |*categories|
joins(:categories).
where(:awards_categories => { :category_id => categories } ).
where("(select count(distinct category_id) from awards_categories where category_id in (?)) = ?", categories, categories.size)
}
and use it this way:
#awardsall = Award.in_categories(1, 2).order("name ASC")
#awards_store = Award.in_categories(1).order("name ASC")
If you have a model for awards_categories, then it will look better:
scope :in_categories, lambda { |*categories|
joins(:categories).
where(:awards_categories => { :category_id => categories } ).
where("#{AwardCategory.where(:category_id => categories).count("distinct category_id").to_sql}=#{categories.size}")
}