I've got workers, workers has many posts. I want to be able to search for a worker, displaying all his posts, then narrow down to the date the posts where made. I can search by name of the worker but when I try to search for date aswell it just displays all posts for that worker (if the date exists in one post).
what I'm trying to run with:
controller:
#q = Worker.ransack(params[:q])
#workers = #q.result.order(name: :asc).includes(:posts).uniq
view:
<%= search_form_for #q do |f| %>
<%= f.label :name_cont %>
<%= f.search_field :name_cont %>
<%= f.label :posts_date_start %>
<%= f.search_field :posts_date_start %>
<%= f.submit %>
<% end %>
<% #workers.each do |worker| %>
<% worker.posts.group_by { |t| t.date.to_time.beginning_of_month }.each do |month, posts| %>
<some table header logic>
<% posts.each do |post| %>
<table content>
Unless you created a custom predicate of start, that will not work.
From your group_by statement I can see that your posts has a date field. If you wanted posts only for the date specified you would use the eq predicate
<%= f.search_field :posts_date_eq %>
If you need to massage your user input, I would look into making a custom predicate you can look at how to do that here -> creating custom predicates
EDIT
To test parsing your date field string into a date put
begin
params[:q][:posts_date_eq] = Date.parse(params[:q][:posts_date_eq])
rescue
# no param present
end
before your search object
#q = Worker.ransack(params[:q])
I solved it like this
instead of
<% worker.posts.group_by { |t| t.date.to_time.beginning_of_month }.each do |month, posts| %>
I did
<% Post.search_post(params[:search_post]).search_post_present(params[:search_post_present]).where(worker_id: worker.id).order(date: :asc).group_by { |t| t.date.to_time.beginning_of_month }.each do |month, posts| %>
that pointed to a search hepler in post.rb
def self.search_post(search_post)
if search_post
where('date LIKE ?', "%#{search_post}%")
else
all
end
end
I then overlapped the forms for both ransack and this search, so both are run with the same submit button, and that worked just fine.
Related
I'm trying to create a timeline for #challenges. For those challenges that have a :deadline I want them to be organized on the timeline according to their :deadline and for those challenge that have a :date_started I want them to be organized on the timeline according to their :date_started.
If a challenge has a :deadline then date_started is nil and vice versa.
example
2016
February
CHALLENGE 1 (Deadline: 1st)
CHALLENGE 2 (Date_Started: 3rd)
CHALLENGE 3 (Deadline: 18th)
controller
#challenges = current_user.challenges
#challenges_timeline = #challenges.group_by { |t| t.deadline.beginning_of_year + t.date_started.beginning_of_year }
view
<% #challenges_timeline.sort.each do |year, challenges| %>
<%= year.strftime('%Y') %>
<% challenges.group_by { |t| t.deadline.beginning_of_month + t.date_started.beginning_of_month }.sort.each do |month, challenges| %>
<%= month.strftime('%B') %>
<% for challenge in challenges %>
<% if challenge.deadline.present? %>
<%= challenge.deadline %>: <%= challenge.action %>
<% end %>
<% if challenge.date_started.present? %>
<%= challenge.date_started %>: <%= challenge.action %>
<% end %>
<% end %>
<% end %>
<% end %>
Change your schema:
If the two dates negate each other, perhaps you should have just one date field, and another field to show whether the date is the beginning or the end. That would allow you to group on the database level, saving some processing time.
Add instance method
A simple instance method such as
def timeline_date
deadline || date_started
end
would allow simple grouping such as
challenges.group_by { |c| c.timeline_date.beginning_of_month }
Use || directly in the group_by block.
I have spent hours on this single problem, I am desperate for help.
The below html displays the correct car name and the car.manufacture_id displays the correct manufacture id, except I need to display manufacture.name and can not figure out how to do that. How do I display car.manufacture.name?
search.html.erb
<% #cars.each do |car| %>
<%= car.manufacture_id %>
<%= link_to car.name, manufacture_path(car.manufacture_id) %>
<% end %>
search_controller.rb
def search
if params[:q].nil?
#cars = []
#manufactures = []
else
#cars = Car.search params[:q]
#manufactures = Manufacture.search params[:q]
end
end
What do your car and manufacture models looks like, can you show the code for them? The schemas would help too. If your models are setup right car.manufacture.name should have worked.
If you do
<% #manufactures.each do |manufacture| %>
<%= manufacture.id %>
<%= manufacture.name %>
<% end %>
Does this work?
Also this might work, if the manufacturers are being found by Manufacture.search params[:q]
<%= #manufactures.find(car.manufacture_id).name %>
or if they are not
<%= Manufacture.find(car.manufacture_id).name %>
I have created a simple appointment system, and I now need to display something inside a loop if there's two or more appointments with the same date and time. The appointments are displayed in order of time, so they're just appearing one after the other.
Controller
def index
#todays_apps = current_user.appointments.order(time ASC)
end
View
<% #todays_apps.each do |app| %>
<%= app.business_name %>
<%= app.business_address %>
<%= app.time %>
<% end %>
I'm looking to display a message or icon the appointment shares a date and time with another appointment. Tried a collection of things with no luck.
You can group your collection by time and modify your iteration accordingly. You can group it like
#todays_apps.group_by(&:time)
The outcome will be something like
=> { timestamp1 => [app1,app2], timestamp2 => [app3], timestamp3 => [app4]}
Or you can try a quick hacky way like:
<% previous_time = nil %>
<% #todays_apps.each do |app| %>
<%= app.business_name %>
<%= app.business_address %>
<%= 'Your message or class or anything' if previous_time == app.time %>
<%= previous_time = app.time %>
<% end %>
Try Like this:
controller:
def index
#appointments = current_user.appointments.order("time ASC")
#todays_apps = #appointments.group_by(&:time)
end
View:
<% #todays_apps.each do |time, appointments| %>
<%= time %>
<% appointments.each do |appointment| %>
<%= appointment.business_name %>
<%= appointment.business_address %>
<% end %>
<% end %>
It will list all the appointments for particular time.
Thanks
I have these two inputs:
<%= search_form_for #search, url: search_path, method: :post do |f| %>
<%= f.text_field :thing_false %>
<%= f.text_field :thing_null %>
<% end %>
and when they're both set to "t", I get this query executed:
SQL: SELECT "stuffs".* FROM "stuffs" WHERE (("stuffs"."thing" = 'f' AND "stuffs"."thing" IS NULL))
How do I make it so I get this executed?
SQL: SELECT "stuffs".* FROM "stuffs" WHERE (("stuffs"."thing" = 'f' OR "stuffs"."thing" IS NULL))
The ransack documentation doesn't really address this. This is the closest example that I can find:
>> User.search(:first_name_or_last_name_cont => "Rya").result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%'
OR "users"."last_name" LIKE '%Rya%')
If you don't want the user to have to select the "any" option, you can make it so that the search always uses "OR" by adding something like this in your controller:
#search = User.search(params[:q])
#search.combinator = "or"
#users = #search.result
You can also create different groupings of search fields and specify the appropriate combination within the grouping. The controller could have something like:
#search = User.search(params[:q])
(0..1).each do |index|
#search.build_grouping unless #search.groupings[index]
#search.groupings[index].combinator = "or"
end
#users = #search.result
And the view could have something like:
<%= search_form_for #search do |f| %>
<% #search.groupings.each.with_index do |grouping,index| %>
<%= f.grouping_fields grouping do |g| %>
<% if index == 0 %>
<%#= fields for first grouping here %>
<% end %>
<% if index == 1 %>
<%#= fields for second grouping here %>
<% end %>
<% end %>
<% end %>
<%= f.submit "Search" %>
<% end %>
The RansackDemo page is a good place to play around with the different search options. There is a Simple Mode and an Advanced Mode. The source code is available on github and the views there give some indication of how to put together the groupings and conditions.
Additional info is also available in RailsCast 370.
throw this under your search_form_for tag. This is assuming that you're using f:
<%= f.combinator_select %>
it'll generate a select with two options. ALL or ANY. ANY will use an OR clause. ALL will use an AND clause.
I was making a travel vacation application. Searching of places is based on categories from select dropdown.
But I am not able to understand the program logic. I am able to load the content in the database. but can't filter based on certain categories.
I made a scaffold called listing and included certain parameters.
In the database it has a row of 5 columns, namely, place, description, image_url, price, category.
Now, if I create another controller, search, I am not able to load a row based on a category from the select dropdown.
Search_controller.rb
def index
#categories = Listing.find_by_sql("SELECT category FROM listings GROUP BY category").map &:category
#list = params[:category].blank? ? Listing.all : Listing.find_all_by_category(params[:category])
end
index.html.erb
<% form_tag(:action => :index) do %>
<%= select_tag "category", options_for_select(#categories) %>
<%= submit_tag "Filter" %>
<% end %>
<table>
<% #list.each do |list| %>
<tr>
<td><%= list.place %></td>
</tr>
<% end %>
</table>
It does not show the select option.
Also, I tried to do this without select form
Search_controller.rb
def index
#list = Listing.select(:category).map(&:category).uniq
end
Index.html.erb
<% #list.each do |r| %>
<%= r.place %>
<% end %>
It says: undefined method `place' for "sunny":String (where "sunny" is a category)
Basically, how do you get the row based on a certain column value. And, will the logic also apply to two select dropdowns?
I know I am close, but somethings not right. Please assist me.
Thanks a lot.
You are missing = before form_tag. Should be:
<%= form_tag(:action => :index) do %>
<%= select_tag "category", options_for_select(#categories) %>
<%= submit_tag "Filter" %>
<% end %>