Rails form - search engine - sql

I try to create simple search engine but I meet some problmes. I have several search_field in my form and if either is empty should returns all objects. Otherwise when it has any content it should be selected by that content. Below is my sample form:
<%= form_for :product, url: products_path, method: :get do |form| %>
<%= form.search_field :brand %>
<%= form.search_field :model %>
<%= form.search_field :price_from %>
<%= form.search_field :price_to %>
<%= form.submit 'Submit' %>
<% end %>
my model method:
def self.search(search)
where(brand: search[:brand]).where(model: search[:model]).where("price >= ?", search[:price_from]).where("price <= ?", search[:price_to])
end
But the above piece of code is wrong because if I leave some field empty it is treated directly as empty string instead of ignore this field and final result is not correct.
Summary this form should work similarly to filter on online store

You'd could do something like this
def self.search(search)
results = all
results = results.where(brand: search[:brand]) if search[:brand]
results = results.where(model: search[:model]) if search[:model]
results = results.where("price >= ?", search[:price_from]) if search[:price_from]
results = results.where("price <= ?", search[:price_to]) if search[:price_to]
return results
end
Good luck.

Related

How to Pass Hash parameter of Boolean attribute from view?

I am using Meta-search Gem to search from table by below controller action. I am Using The Rails version 3.2.9.
class FeedEntriesController < ApplicationController
def index
#search = FeedEntry.search(params[:is_star])
#feed_entries = #search.page(params[:page])
#app_keys = AppKey.all
end
end
feed_entries table contain is_star:boolean attribute. So, I just want to pass the hash parameter is_star == true into the params[:is_star] from view using form_for or link_to . I tried using the below way.
In Views/feed_entries/index.html.erb
<%= link_to "Stared", {:controller => "feed_entries", :action => "index", :is_star => true }%>
but the above way is now worked, So I decided to make use of form_for in the below way,
<%= form_for(#is_star) do |f|%>
<%= f.hidden_field :is_star_is_true %>
<%= f.submit "Search" %>
<% end %>
But, nothing is worked, please someone help me resolve this problem.
true and false when passed as a string is parsed as their truthy value when used in a boolean column. This is also true for 0, 1, '0' and '1'
>> m = Model.new
>> m.active = 'false'
>> m.active? # false
>> m.active = 'true'
>> m.active? # true
Knowing this, you can pass 'true' as the value of the hidden_field
<%= f.hidden_field :is_start, value: 'true' %>
You can pass in the value of the parent in the view where the form is being rendere ultimately with something like <%=params[:is_start] = 1 %> . I am not sure how the layout of the app is setup. Also make sure to attr_accessible :is_start
Update: I may have understood your problem wrong. So try this as well
<%= f.hidden_field :is_star, value: 'true' %>
Or you could have a radio button ?
<%= f.radio_button :is_star, value: 'true' %>

Rails: two (or more) instances of same collection_select?

I've got a collection_select instance in a form, and I'm wondering if it's possible to have two or more instances in the same form. They'd be built from the same model, and they would save as if they were checkboxes constructed in an Article.all.each loop. To have these work
<%= f.collection_select("article_ids", Article.where(:page => 1), :id, :name) %>
<%= f.collection_select("article_ids", Article.where(:page => 2), :id, :name) %>
<%= f.collection_select("article_ids", Article.where(:page => 3), :id, :name) %>
in the form is pretty much what I'm after. It's essentially a multiple select but spread over a couple of selects. The field already accepts multiple results, but when I save the form as it is above it only records the option from the final select. Any thoughts?
Cheers!
<%= select_tag "article_ids[]",options_from_collection_for_select(Article.all.collect{|i| [i.name,i.id]),:multiple => true %>
When select multiple options in select list just give article_ids[] , it will store all ids in this array then after you write query how you would store in database.
If set the select tag is multiple true then you will select multiple options other wise you get only one selected value.
or just read below link
http://api.rubyonrails.org/?q=collection%20select
If you want to give f.select then you must give like this
<%= f.collection_select :article_id, Article.all, :id , :name %>
I just went with checkboxes to solve this, because it's truly the stuff of nightmares.
<% #articles.each do |a| %>
<%= check_box_tag("doc[article_ids][]", a.id, #doc.articles.include?(a.id), :class => "article_chooser") %> <a id="<%= a.id %>" class="name"><%= a.name %></a><br />
<% end %>

How to create own block helper with two or more nested children?

I'd like to to something nested like that in my views:
<%= helper_a do |ha| %>
Content for a
<%= ha.helper_b do |hb| %>
Content for b
<%= hb.helper_c do |hc| %>
Content for c
... and so on ...
<% end %>
<% end %>
<% end %>
To get for example this:
<tag_a>
Content for a
<tag_b class="child_of_tag_a">
Content for b
<tag_c class="nested_child_of_tag_a child_of_tag_b">
Content for c
</tag_c>
</tag_b>
</tag_a>
This means, each level has access to some information of the level above (that's why they are nested and not completely autonomous methods)
I know how to create a simple helper:
def helper_a(&block)
content = capture(&block)
content_tag :tag_a, content
end
And I know I can pass my arguments to the capture to use them in the view, so something like this to get live up the |ha| of my example
def helper_a(&block)
content = capture(OBJECT_HERE, &block)
content_tag :tag_a, content
end
But where do I define this OBJECT_HERE, especially the class for it, and how can this go on nested with multiple levels capturing each block?
I came up with a couple solutions, but I'm far from being an expert in the Rails templating system.
The first one is using an instance variable :
def helper_a(&block)
with_context(:tag_a) do
content = capture(&block)
content_tag :tag_a, content
end
end
def helper_b(&block)
with_context(:tag_b) do
content = capture(&block)
content_tag :tag_b, content
end
end
def helper_c(&block)
with_context(:tag_c) do
content = capture(&block)
content_tag :tag_c, content
end
end
def with_context(name)
#context ||= []
#context.push(name)
content = yield
#context.pop
content
end
which is used this way :
<%= helper_a do %>
Content for a
<%= helper_b do %>
Content for b
<%= helper_c do %>
Content for c
... and so on ...
<% end %>
<% end %>
<% end %>
And the other solution, which passes the context at each step :
def helper_a(context = [], &block)
context = capture(context.push(:tag_a), &block)
content_tag(:tag_a, content)
end
def helper_b(context = [], &block)
context = capture(context.push(:tag_b), &block)
content_tag(:tag_b, content)
end
def helper_c(context = [], &block)
context = capture(context.push(:tag_c), &block)
content_tag(:tag_c, content)
end
which is used this way :
<%= helper_a do |context| %>
Content for a
<%= helper_b(context) do |context| %>
Content for b
<%= helper_c(context) do |context| %>
Content for c
... and so on ...
<% end %>
<% end %>
<% end %>
But I'd really advise against using either of these solutions if all you're doing is CSS styling and/or Javascript manipulation. It really complicates the helpers, is likely to introduce bugs, etc.
Hope this helps.

Any possible way to set radio_button_tag values by a database set value

I have a radio_button_tag in a form, which holds various values for a persons current availability:
Mike Donnall o Available o Out of office o Vacation
So originally you open the form, and select a value, this then sets the value in the Status table for that Person.
However, there's also functionality to re-open the form and update his present status, perhaps from Vacation to Available.
My question is, is there anyway at all that radio button :checked can be modified to accept a custom method, I have found something in a similar posting, but I want the value foe that radio button to be set to the value in the DB.
My code so far, a stab in the dark perhaps:
View:
<% #people.each do |p| %>
<% #statuses.each do |s| %>
<%= "#{p.name}" %>
<%= "#{s.status_name}" -%><%= radio_button_tag ['person', p.id], ['status',
s.id], checked?(p.id) %>
<% end %>
<% end %>
Helper:
def checked?(person)
#person = person
#status = Status.find_by_sql(['select status_id from statuses where person_id = ?, #person])
if #result
return true
end
As you can see Im a bit lost here, but I understand that the method should return the value of the checkbox that needs to be checked, but Im wondering because its a checked functionality, would it only be limited to being a true or false?
So for a persons.status.id check if its true or false.
It seems from your helper's SQL that you the following relationship setup between People and Statuses:
class Person < ActiveRecord::Base
has_one :status
end
class Status < ActiveRecord::Base
belongs_to :person
end
You can access one given person status like this:
person = Person.first
person_status = person.status
Using that knowledge, your desired view outcome becomes quite simple:
<% #people.each do |p| %>
<p><%= "#{p.name}" -%>
<% #statuses.each do |s| %>
<%= "#{s.status_name}" -%>
<%= radio_button_tag ['person', p.id],
['status', s.id],
(p.status == s) ? true : false %>
<% end %>
<% end %>
You can of course extract the logic to a helper, but that doesn't seem necessary.
On a personal note, this isn't the way I'd present the information to user, it' too heavy on information in one line. I suggest you put the person's name in a p tag, and use a ul tag for the statuses.

Group and count in Rails

I have this bit of code and I get an empty object.
#results = PollRoles.find(
:all,
:select => 'option_id, count(*) count',
:group => 'option_id',
:conditions => ["poll_id = ?", #poll.id])
Is this the correct way of writing the query? I want a collection of records that have an option id and the number of times that option id is found in the PollRoles model.
EDIT: This is how I''m iterating through the results:
<% #results.each do |result| %>
<% #option = Option.find_by_id(result.option_id) %>
<%= #option.question %> <%= result.count %>
<% end %>
What do you get with this:
PollRoles.find(:all,:conditions=>["poll_id = ?",#poll.id]).collect{|p| p.option_id}
You want to use this function to do things like this
PollRoles.count(:all, :group => 'option_id') should return a hash mapping every option_id with the number of records that matched it.