Hi All,
I am still trying to get the hang of passing information to controller.
I want to extend the rails getting started tutorial for searching.
(http://wiki.rubyonrails.com/rails/pages/GettingStartedWithRails).
The index page would be the main search form passing the parameters
to a view
controller and displayed with a view.rhtml page.
I have started with something from a blog that looked promising.
http://blog.teksol.info/articles/2005/10/31/building-the-sql-where-
clause-dynamically-in-rails
Here is what I have started with but not sure how to get the values into
the conditions correctly.
Thanks for any suggestions
Processing FriendsController#view (for 127.0.0.1 at 2005-11-30
00:14:11) [POST]
Parameters: {"commit"=>"Search",
"action"=>"view",
"controller"=>"friends",
"person"=>{"city"=>"",
"name"=>"Dave",
"state"=>""}}
friends_controller.rb
def view
#initialize the conditions array: [''1=1'']. This is to
prevent a
problem later on when Rails
#evaluates the conditions option to find .condition. (from blog)
conditions = [''1=1'']
puts @params[:person][''name''] if
@params[:person][''name''] #
works fine get name
conditions << ''name = :name'' if
@params[:person][''name''] # what
is needed here?
conditions << ''city = :city'' if
@params[:person][''city'']
conditions << ''state = :state'' if
@params[:person][''state'']
@person = Person.find(:first, :conditions => [conditions.join(''
AND ''), params])
puts conditions
end
index.rhtml
<%= start_form_tag :action => ''view'' %>
<p><label for="person_name">Name</label><br/>
<%= text_field ''person'', ''name''
%></p>
<p><label for="person_city">City</label><br/>
<%= text_field ''person'', ''city''
%></p>
<p><label
for="person_state">State</label><br/>
<%= text_field ''person'', ''state''
%></p>
<%= submit_tag "Search" %>
<%= end_form_tag %>
Am Mittwoch, den 30.11.2005, 00:54 -0800 schrieb David Watts:> Hi All, > > I am still trying to get the hang of passing information to controller. > I want to extend the rails getting started tutorial for searching. > (http://wiki.rubyonrails.com/rails/pages/GettingStartedWithRails). > The index page would be the main search form passing the parameters > to a view > controller and displayed with a view.rhtml page. > > I have started with something from a blog that looked promising. > http://blog.teksol.info/articles/2005/10/31/building-the-sql-where- > clause-dynamically-in-rails > > Here is what I have started with but not sure how to get the values into > the conditions correctly. > > Thanks for any suggestions > > Processing FriendsController#view (for 127.0.0.1 at 2005-11-30 > 00:14:11) [POST] > Parameters: {"commit"=>"Search", "action"=>"view", > "controller"=>"friends", "person"=>{"city"=>"", "name"=>"Dave", > "state"=>""}} > > friends_controller.rb > > def view > #initialize the conditions array: [''1=1'']. This is to prevent a > problem later on when Rails > #evaluates the conditions option to find .condition. (from blog) > conditions = [''1=1''] > puts @params[:person][''name''] if @params[:person][''name''] # > works fine get name > conditions << ''name = :name'' if @params[:person][''name''] # what > is needed here? > conditions << ''city = :city'' if @params[:person][''city''] > conditions << ''state = :state'' if @params[:person][''state''] > @person = Person.find(:first, :conditions => [conditions.join('' > AND ''), params]) > puts conditions > endThis is untested: def view conditions = [[]] params[:person].each do |key_value| key, value = key_value unless value.blank? conditions.first << "#{key} = ?" conditions << value end end conditions.first.join('' AND '') @person = conditions.size > 1 ? Person.find(:first, :conditions => conditions) : nil end> index.rhtml > > <%= start_form_tag :action => ''view'' %> > > <p><label for="person_name">Name</label><br/> > <%= text_field ''person'', ''name'' %></p> > > <p><label for="person_city">City</label><br/> > <%= text_field ''person'', ''city'' %></p> > > <p><label for="person_state">State</label><br/> > <%= text_field ''person'', ''state'' %></p> > > <%= submit_tag "Search" %> > > <%= end_form_tag %> > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Hello David ! 2005/11/30, David Watts <davewatts@pennysaverusa.net>:> def view > #initialize the conditions array: ['1=1']. This is to prevent a > problem later on when Rails > #evaluates the conditions option to find .condition. (from blog) > conditions = ['1=1'] > puts @params[:person]['name'] if @params[:person]['name'] # > works fine get name > conditions << 'name = :name' if @params[:person]['name'] # what > is needed here? > conditions << 'city = :city' if @params[:person]['city'] > conditions << 'state = :state' if @params[:person]['state'] > @person = Person.find(:first, :conditions => [conditions.join(' > AND '), params]) > puts conditions > endThis is your error: @person = Person.find(:first, :conditions => [conditions.join(' AND '), params]) You need to do this: @person = Person.find(:first, :conditions => [conditions.join(' AND '), params[:person]]) Notice I used params[:person], and not plain params. Rails is attempting to search for a key by name :state, but there are none in params. It is stored as params[:person][:state]. Also, you might get an error because you have too many parameters in the params Hash vs what you are using in the conditions. You'll have to initialize a new Hash with just the values you need: def view conditions = ['1=1'] values = Hash.new if params[:person][:city] then conditions << 'city = :city' values[:city] = params[:person][:city] end @people = Person.find(:all, :conditions => [conditions.join(' AND '), values]) end BTW, that blog you refer to is mine :) Happy to see it is of some help to someone. Bye ! -- François Beausoleil http://blog.teksol.info/ _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Thanks,
The list has been very kind and patient with my questions.
Now for the but....
I was able to get the search to work for one value (params[:person]
[:name]).
As soon as I added a second one it blows up doooh....
What is needed to remove the blank conditions?
What I have now is:
def view
#initialize the conditions array: [''1=1''].
conditions = [''1=1'']
values = Hash.new
if params[:person][:name] then
conditions << ''name = :name''
values[:name] = params[:person][:name]
end
if params[:person][:city] then
conditions << ''city = :city''
values[:city] = params[:person][:city]
end
puts conditions
@person = Person.find(:first, :conditions => [conditions.join(''
AND ''), values])
end
Giving me:
Which makes sense it should not find anything
Parameters: {"commit"=>"Search",
"action"=>"view",
"controller"=>"friends",
"person"=>{"city"=>"",
"name"=>"dave",
"state"=>""}}
Person Load (0.001174) SELECT * FROM people WHERE (1=1 AND name
= ''dave'' AND city = '''') LIMIT 1
Rendering friends/view
ActionView::TemplateError (You have a nil object when you didn''t
expect it!
The error occured while evaluating nil.name) on line #4 of app/views/
friends/view.rhtml:
1: <h1>Listing Found</h1>
2:
3: <p>
4: <%= @person.name %><br />
5: <%= @person.street1 %><br />
6: <%= @person.street2 %><br />
7: <%= @person.city %><br />
Thanks Again for your patience
> This is your error:
> @person = Person.find(:first, :conditions => [conditions.join(''
AND
> ''), params])
>
> You need to do this:
> @person = Person.find(:first, :conditions => [conditions.join(''
AND
> ''), params[:person]])
>
> Notice I used params[:person], and not plain params. Rails is
> attempting to search for a key by name :state, but there are none in
> params. It is stored as params[:person][:state].
>
> Also, you might get an error because you have too many parameters in
> the params Hash vs what you are using in the conditions. You''ll
have
> to initialize a new Hash with just the values you need:
>
> def view
> conditions = [''1=1'']
> values = Hash.new
>
> if params[:person][:city] then
> conditions << ''city = :city''
> values[:city] = params[:person][:city]
> end
>
> @people = Person.find(:all, :conditions => [conditions.join(''
AND
> ''), values])
> end
>
> BTW, that blog you refer to is mine :) Happy to see it is of some
> help to someone.
>
> Bye !
> --
> François Beausoleil
> http://blog.teksol.info/
> _______________________________________________
> Rails mailing list
> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
Am Mittwoch, den 30.11.2005, 16:08 -0800 schrieb David Watts:> Thanks, > > The list has been very kind and patient with my questions. > > Now for the but.... > > I was able to get the search to work for one value (params[:person] > [:name]). > As soon as I added a second one it blows up doooh.... > > What is needed to remove the blank conditions?I refere you to my post from yesterday to this subject. Following method handles your problem. By the way, this is a little bit more generic than your approach. def view conditions = [[]] params[:person].each do |key_value| key, value = key_value unless value.blank? conditions.first << "#{key} = ?" conditions << value end end conditions.first.join('' AND '') @person = conditions.size > 1 ? Person.find(:first, :conditions => conditions) : nil end Try to analyse and understand it. You will see.> What I have now is: > > def view > #initialize the conditions array: [''1=1'']. > conditions = [''1=1''] > values = Hash.new > > if params[:person][:name] then > conditions << ''name = :name'' > values[:name] = params[:person][:name] > end > if params[:person][:city] then > conditions << ''city = :city'' > values[:city] = params[:person][:city] > end > > puts conditions > @person = Person.find(:first, :conditions => [conditions.join('' > AND ''), values]) > end > > Giving me: > Which makes sense it should not find anything > > Parameters: {"commit"=>"Search", "action"=>"view", > "controller"=>"friends", "person"=>{"city"=>"", "name"=>"dave", > "state"=>""}} > Person Load (0.001174) SELECT * FROM people WHERE (1=1 AND name > = ''dave'' AND city = '''') LIMIT 1 > Rendering friends/view > > > ActionView::TemplateError (You have a nil object when you didn''t > expect it! > The error occured while evaluating nil.name) on line #4 of app/views/ > friends/view.rhtml: > 1: <h1>Listing Found</h1> > 2: > 3: <p> > 4: <%= @person.name %><br /> > 5: <%= @person.street1 %><br /> > 6: <%= @person.street2 %><br /> > 7: <%= @person.city %><br /> > > Thanks Again for your patience > > > This is your error: > > @person = Person.find(:first, :conditions => [conditions.join('' AND > > ''), params]) > > > > You need to do this: > > @person = Person.find(:first, :conditions => [conditions.join('' AND > > ''), params[:person]]) > > > > Notice I used params[:person], and not plain params. Rails is > > attempting to search for a key by name :state, but there are none in > > params. It is stored as params[:person][:state]. > > > > Also, you might get an error because you have too many parameters in > > the params Hash vs what you are using in the conditions. You''ll have > > to initialize a new Hash with just the values you need: > > > > def view > > conditions = [''1=1''] > > values = Hash.new > > > > if params[:person][:city] then > > conditions << ''city = :city'' > > values[:city] = params[:person][:city] > > end > > > > @people = Person.find(:all, :conditions => [conditions.join('' AND > > ''), values]) > > end > > > > BTW, that blog you refer to is mine :) Happy to see it is of some > > help to someone. > > > > Bye ! > > -- > > François Beausoleil > > http://blog.teksol.info/ > > _______________________________________________ > > Rails mailing list > > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > http://lists.rubyonrails.org/mailman/listinfo/rails > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
How do you handle LIKE ? -- Posted via http://www.ruby-forum.com/.
Am Donnerstag, den 01.12.2005, 11:58 +0100 schrieb Christer Nilsson:> How do you handle LIKE ? >See this line ''conditions.first << "#{key} = LIKE ?"'': def view conditions = [[]] params[:person].each do |key_value| key, value = key_value unless value.blank? conditions.first << "#{key} LIKE ?" conditions << value end end conditions.first.join('' AND '') @person = conditions.size > 1 ? Person.find(:first, :conditions => conditions) : nil end You could even do a more open search, if you surround the search values with ''%'': def view conditions = [[]] params[:person].each do |key_value| key, value = key_value unless value.blank? conditions.first << "#{key} LIKE ?" conditions << "%#{value}%" end end conditions.first.join('' AND '') @person = conditions.size > 1 ? Person.find(:first, :conditions => conditions) : nil end
I have just written a better (IMHO) way to build the where clause
dynamically. The following Where class will hopefully help you out:
class Where
# Utility class to dynamically create the where clause
# for a rails find method. Initialize expects a nested
# array like: [[:project, 3], [:month, 7], [:user, 0]]
# where each nested array contains a symbol of the column
# name and a value to query for. Lets say that you have
# this hash in your +params+ :
# params = { :person => {:name => "dave" :city =>
"Yakima"}}
# You can use this class to build the where clause like so:
# where = Where.new([ [:user, params[:person][:name]], [:city,
params[:person][:city]] ])
# MyModel.find(:all, :conditions => where.build_where_clause)
def initialize(options=[])
@opts = options
@opts.each do |pair|
instance_variable_set("@#{pair[0].to_sym}", pair[1])
end
end
def build_where_clause
q = []
ary = []
@opts.each do |pair|
iv = instance_variable_get("@#{pair[0]}")
unless iv.nil? || iv.to_s == ''''
q << "#{pair[0]} = ?"
ary << iv
end
end
return [q.join(" and ")].concat(ary)
end
end # End Where
# Some examples:
a = Where.new([[:project, 3], [:month, 7], [:user, 0]])
p a.build_where_clause
# => ["project = ? and month = ? and user = ?", 3, 7, 0]
b = Where.new([[:post, 6], [:user, "admin"], [:comment, 12]])
p b.build_where_clause
# => ["post = ? and user = ? and comment = ?", 6,
"admin", 12]
# built from params. You can see that the params[:person][:state] is
empty.
# this class will take that into consideration and leave that part
out of the where clause
params = {:id => 17, :person => {:city => "Yakima", :name
=>
"dave", :state => ""}}
c = Where.new([[:user, params[:person][:name]], [:city, params
[:person][:city]], [:state, params[:person][:state]]])
p c.build_where_clause
# => ["user = ? and city = ?", "dave",
"Yakima"]
Cheers-
-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
ezra-gdxLOakOTQ9oetBuM9ipNAC/G2K4zDHf@public.gmane.org
In the same WHERE clause it should be possible to mix the operators: WHERE name LIKE ''chr%'' AND city LIKE ''%FURT'' AND skills LIKE ''%plumbing%'' AND date <= ''2006-12-01'' AND age >= 25 AND age <= 50 AND sex = ''female'' And remember, all 2^7 = 128 combinations should be possible! If age and sex is uninteresting, collapse to: WHERE name LIKE ''chr%'' AND city LIKE ''%FURT'' AND skills LIKE ''%plumbing%'' AND date <= ''2006-12-01'' How can this be specified in a readable form? My long term goal is to NEVER see SQL. This is one of the problems on the journey. Christer -- Posted via http://www.ruby-forum.com/.
I downloaded the gems to both of these. But, I''m not sure how to get them working in my App. Has anyone used either of these? __________________________________ Yahoo! Music Unlimited Access over 1 million songs. Try it free. http://music.yahoo.com/unlimited/
I find the apparently common dislike of SQL surprising. To me, SQL is a language much like css. Very compact. Very logical (therefore easy to retain) and very powerful. On 1-Dec-05, at 11:05 AM, Christer Nilsson wrote:> In the same WHERE clause it should be possible to mix the operators: > > WHERE name LIKE ''chr%'' > AND city LIKE ''%FURT'' > AND skills LIKE ''%plumbing%'' > AND date <= ''2006-12-01'' > AND age >= 25 > AND age <= 50 > AND sex = ''female'' > > And remember, all 2^7 = 128 combinations should be possible! > > If age and sex is uninteresting, collapse to: > > WHERE name LIKE ''chr%'' > AND city LIKE ''%FURT'' > AND skills LIKE ''%plumbing%'' > AND date <= ''2006-12-01'' > > How can this be specified in a readable form? > > My long term goal is to NEVER see SQL. This is one of the problems on > the journey. > > Christer > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Am Donnerstag, den 01.12.2005, 19:05 +0100 schrieb Christer Nilsson:> In the same WHERE clause it should be possible to mix the operators: > > WHERE name LIKE ''chr%'' > AND city LIKE ''%FURT'' > AND skills LIKE ''%plumbing%'' > AND date <= ''2006-12-01'' > AND age >= 25 > AND age <= 50 > AND sex = ''female'' > > And remember, all 2^7 = 128 combinations should be possible! > > If age and sex is uninteresting, collapse to: > > WHERE name LIKE ''chr%'' > AND city LIKE ''%FURT'' > AND skills LIKE ''%plumbing%'' > AND date <= ''2006-12-01'' > > How can this be specified in a readable form? > > My long term goal is to NEVER see SQL. This is one of the problems on > the journey. > > Christer >Maybe you want to write a little plugin and share it with us? This would be a nice contribute to the community ;)
Agreed. -----Original Message----- From: rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Bruce Balmer Sent: Thursday, December 01, 2005 1:31 PM To: rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: Re: [Rails] Re: Newbie: Building conditions from form I find the apparently common dislike of SQL surprising. To me, SQL is a language much like css. Very compact. Very logical (therefore easy to retain) and very powerful. On 1-Dec-05, at 11:05 AM, Christer Nilsson wrote:> In the same WHERE clause it should be possible to mix the operators: > > WHERE name LIKE ''chr%'' > AND city LIKE ''%FURT'' > AND skills LIKE ''%plumbing%'' > AND date <= ''2006-12-01'' > AND age >= 25 > AND age <= 50 > AND sex = ''female'' > > And remember, all 2^7 = 128 combinations should be possible! > > If age and sex is uninteresting, collapse to: > > WHERE name LIKE ''chr%'' > AND city LIKE ''%FURT'' > AND skills LIKE ''%plumbing%'' > AND date <= ''2006-12-01'' > > How can this be specified in a readable form? > > My long term goal is to NEVER see SQL. This is one of the problems on > the journey. > > Christer > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails_______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Hi, In your view, if you want to use textile (redcloth): <%= textilize(@page.description) %> And if you want to use markdown (bluecloth), use: <%= markdown(@page.description) %> 2005/12/1, jonathan Mcintire:> > I downloaded the gems to both of these. But, I''m not > sure how to get them working in my App. Has anyone > used either of these?
Yeah, I would like to, but I''m an Ruby nuby. Ezra is looking at this. Christer -- Posted via http://www.ruby-forum.com/.
OK, here''s my attempt to support more operators. What do you think?
class Where
def initialize(options=[])
@opts = options
@opts.each do |triplet|
instance_variable_set("@#{triplet[0].to_sym}", triplet[2])
end
end
def build_where_clause
q = []
ary = []
@opts.each do |triplet|
iv = instance_variable_get("@#{triplet[0]}")
unless iv.nil? || iv.to_s == ''''
q << "#{triplet[0]} #{triplet[1]} ?"
ary << iv
end
end
return [q.join(" AND ")].concat(ary)
end
end # End Where
# USAGE
# Pass in your query params in an array containing nested arrays with
3 items in each
# nested array.
a = Where.new([[:project,"=", 3], [:month, ">=", 7],
[:comment,
"LIKE", "%ruby%"]])
p a.build_where_clause
# => ["project = ? AND month >= ? AND comment LIKE ?", 3, 7,
"%ruby%"]
# So the format of the Where class constructor needs an array with
these specs:
b = Where.new([ [:column_name1, "LIKE", "%value%"],
[:column_name2,
">=", 8], [:column_name3, "=", 12], [:date,
"<=", ''2006-12-0'' ] ])
p b.build_where_clause
# => ["column_name1 LIKE ? AND column_name2 >= ? AND column_name3 = ?
AND date <= ?", "%value%", 8, 12, "2006-12-0"]
# So you can pass as many columns as you like using whatever operator
you like =, >, <, >=, <=, LIKE
# and whatever esle it doesn''t really care as long as its valid SQL.
I still haven''t figured out how to use
# OR instead of AND intermixed in the same query but I will keep
working on it. Once I get it to be much
# more robust I will make it a small plug in.
Its a fun little class but is it really any shorter than writing
the :conditions yourself? ;-)
Thoughts?
Cheers-
-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
ezra-gdxLOakOTQ9oetBuM9ipNAC/G2K4zDHf@public.gmane.org
Hi Norman,
Thank you very much. I have actually been working on understanding
the code (newbie moment) you used. Below is what I finally got to
work for me.
Not very pretty, considering just learning ruby/rails. Let me know if
there is a better way to do this.
Again, thank you it really helped ;-)
Dave
def view
myconditions = []
params[:person].each do |key_value|
key, value = key_value
unless value.nil? || value.blank?
myconditions << "#{key} =
''#{value}''"
end
end
conditions = myconditions.join('' AND '')
puts myconditions.size
puts conditions
@person = conditions.size >= 1 ? Person.find
(:first, :conditions => conditions) : nil
if @person == nil
flash[:notice] = ''No records found.''
redirect_to :action => ''index''
end
end
On Dec 1, 2005, at 1:42 AM, Norman Timmler wrote:
> Am Mittwoch, den 30.11.2005, 16:08 -0800 schrieb David Watts:
>> Thanks,
>>
>> The list has been very kind and patient with my questions.
>>
>> Now for the but....
>>
>> I was able to get the search to work for one value (params[:person]
>> [:name]).
>> As soon as I added a second one it blows up doooh....
>>
>> What is needed to remove the blank conditions?
>
> I refere you to my post from yesterday to this subject. Following
> method
> handles your problem. By the way, this is a little bit more generic
> than
> your approach.
>
> def view
> conditions = [[]]
> params[:person].each do |key_value|
> key, value = key_value
> unless value.blank?
> conditions.first << "#{key} = ?"
> conditions << value
> end
> end
> conditions.first.join('' AND '')
> @person = conditions.size > 1 ? Person.find(:first, :conditions =>
> conditions) : nil
> end
>
> Try to analyse and understand it. You will see.
>
>> What I have now is:
>>
>> def view
>> #initialize the conditions array: [''1=1''].
>> conditions = [''1=1'']
>> values = Hash.new
>>
>> if params[:person][:name] then
>> conditions << ''name = :name''
>> values[:name] = params[:person][:name]
>> end
>> if params[:person][:city] then
>> conditions << ''city = :city''
>> values[:city] = params[:person][:city]
>> end
>>
>> puts conditions
>> @person = Person.find(:first, :conditions =>
[conditions.join(''
>> AND ''), values])
>> end
>>
>> Giving me:
>> Which makes sense it should not find anything
>>
>> Parameters: {"commit"=>"Search",
"action"=>"view",
>> "controller"=>"friends",
"person"=>{"city"=>"",
"name"=>"dave",
>> "state"=>""}}
>> Person Load (0.001174) SELECT * FROM people WHERE (1=1 AND name
>> = ''dave'' AND city = '''') LIMIT 1
>> Rendering friends/view
>>
>>
>> ActionView::TemplateError (You have a nil object when you
didn''t
>> expect it!
>> The error occured while evaluating nil.name) on line #4 of app/views/
>> friends/view.rhtml:
>> 1: <h1>Listing Found</h1>
>> 2:
>> 3: <p>
>> 4: <%= @person.name %><br />
>> 5: <%= @person.street1 %><br />
>> 6: <%= @person.street2 %><br />
>> 7: <%= @person.city %><br />
>>
>> Thanks Again for your patience
>>
>>> This is your error:
>>> @person = Person.find(:first, :conditions =>
[conditions.join('' AND
>>> ''), params])
>>>
>>> You need to do this:
>>> @person = Person.find(:first, :conditions =>
[conditions.join('' AND
>>> ''), params[:person]])
>>>
>>> Notice I used params[:person], and not plain params. Rails is
>>> attempting to search for a key by name :state, but there are none
in
>>> params. It is stored as params[:person][:state].
>>>
>>> Also, you might get an error because you have too many parameters
in
>>> the params Hash vs what you are using in the conditions.
You''ll
>>> have
>>> to initialize a new Hash with just the values you need:
>>>
>>> def view
>>> conditions = [''1=1'']
>>> values = Hash.new
>>>
>>> if params[:person][:city] then
>>> conditions << ''city = :city''
>>> values[:city] = params[:person][:city]
>>> end
>>>
>>> @people = Person.find(:all, :conditions =>
[conditions.join('' AND
>>> ''), values])
>>> end
>>>
>>> BTW, that blog you refer to is mine :) Happy to see it is of some
>>> help to someone.
>>>
>>> Bye !
>>> --
>>> François Beausoleil
>>> http://blog.teksol.info/
>>> _______________________________________________
>>> Rails mailing list
>>> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org
>>> http://lists.rubyonrails.org/mailman/listinfo/rails
>>
>> _______________________________________________
>> Rails mailing list
>> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org
>> http://lists.rubyonrails.org/mailman/listinfo/rails
>>
>
> _______________________________________________
> Rails mailing list
> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
Ezra, I think you are on the right track. Thus will save me a lot of lines. Some thoughts about the and/or problem. I''m not sure about the Ruby syntax, but consider this example Where.new ( [:or, [:and, [x=1], [y=2], [z=3]], [w=4]] ) ( x=1 translates to your format [:x, "=", 1] ) which will evaluate to (x=1 and y=2 and z=3) or w=4. If one or more of the values is nil (not given), there will be a simplification. 1 is nil: (y=2 and z=3) or w=4 2 is nil: (x=1 and z=3) or w=4 3 is nil: (x=1 and y=2) or w=4 4 is nil: x=1 and y=2 and y=3 etc. Another way of doing this would be to introduce 1=1 or 1=0 1 is nil: (1=1 and y=2 and z=3) or w=4 2 is nil: (x=1 and 1=1 and z=3) or w=4 3 is nil: (x=1 and y=2 and 1=1) or w=4 4 is nil: (x=1 and y=2 and y=3) or 1=0 Alternative syntax: or(and(x=1,y=2,z=3),w=4) There will be some recursion necessary to produce the statement. Is there a better way of expressing this in Ruby ? Maybe "=", ">=", "LIKE", etc should be functions. Example like(:comment,"%ruby%") I see no problem with the implementation, my question is, how to express the condition clause in a human readable way, using Ruby. -- Posted via http://www.ruby-forum.com/.
On Dec 1, 2005, at 3:29 PM, Christer Nilsson wrote:> Ezra, I think you are on the right track. Thus will save me a lot of > lines. > > Some thoughts about the and/or problem. > > I''m not sure about the Ruby syntax, but consider this example > > Where.new ( [:or, [:and, [x=1], [y=2], [z=3]], [w=4]] ) > ( x=1 translates to your format [:x, "=", 1] )What about something like this: Where.new( {:and = > [ [x=1], [y=2], [z=3] ], :or => [ [w=4], [a=9] ] } ) I don''t think I am going to try to support every combination possible. By the time it would work with all kinds of grouped and''s and or''s you might as well write a custom query yourself. But lets try to support the most common needs and make those easy.> > which will evaluate to > (x=1 and y=2 and z=3) or w=4. > > If one or more of the values is nil (not given), there will be a > simplification. > 1 is nil: (y=2 and z=3) or w=4 > 2 is nil: (x=1 and z=3) or w=4 > 3 is nil: (x=1 and y=2) or w=4 > 4 is nil: x=1 and y=2 and y=3 > etc.This already works. If the value of one of the columns is nil or empty string after a to_s method then it will be left out of the statement all together.> > Another way of doing this would be to introduce 1=1 or 1=0 > 1 is nil: (1=1 and y=2 and z=3) or w=4 > 2 is nil: (x=1 and 1=1 and z=3) or w=4 > 3 is nil: (x=1 and y=2 and 1=1) or w=4 > 4 is nil: (x=1 and y=2 and y=3) or 1=0 > > Alternative syntax: > or(and(x=1,y=2,z=3),w=4) > > There will be some recursion necessary to produce the statement. > > Is there a better way of expressing this in Ruby ? > > Maybe "=", ">=", "LIKE", etc should be functions. > Example > like(:comment,"%ruby%") > > I see no problem with the implementation, my question is, how to > express > the condition clause in a human readable way, using Ruby. > >Alright, I''m with you. Let me try to think of a small DSL to describe the where clause in a more human readable way -Ezra Zygmuntowicz Yakima Herald-Republic WebMaster http://yakimaherald.com 509-577-7732 ezra-gdxLOakOTQ9oetBuM9ipNAC/G2K4zDHf@public.gmane.org
Ezra, this is just a first approximation. No handling of numbers. No
handling of sql inject. Could you please give me a hint?
def zand(*arg)
arg.delete(nil)
arg.join(" and ")
end
def zor(*arg)
arg.delete(nil)
arg.nil? ? nil : "(#{arg.join(" or ")})"
end
def eq(a,b)
b.nil? ? nil : "#{a}=''#{b}''"
end
def lt(a,b)
b.nil? ? nil : "#{a}<=''#{b}''"
end
def gt(a,b)
b.nil? ? nil : "#{a}>=''#{b}''"
end
def zin(a,b)
b.empty? ? nil : "#{a} in (#{b.join(",")})"
end
def between(a,b,c)
zand(gt(a,b),lt(a,c))
end
def like(a,b)
case b
when b.nil?, "%", "%%"
nil
else
"#{a} like ''#{b}''"
end
end
def assert(a,b)
a==b ? print(".") : print("\nexpected: #{a}\nactual:
#{b}\n")
end
assert "price>=''500'' and
price<=''1000''",
between("price","500","1000")
assert "price>=''100'' and
price<=''500''",
zand(gt("price","100"),
lt("price","500"))
assert "rooms in (1,2,3)", zin("rooms",[1,2,3])
assert nil, zin("rooms",[])
assert "size>=''100''",
gt("size","100")
assert "size<=''500''",
lt("size","500")
assert "price<=''500''",
zand(gt("price",nil), lt("price","500"))
assert "", zand(gt("price",nil), lt("price",nil))
size = zand(gt("size","100"),
lt("size","150"))
price = zand(gt("price",nil), lt("price","500"))
city = eq("city","Berlin")
assert "size>=''100'' and
size<=''150'' and (price<=''500'' or
city=''Berlin'')",zand(size,zor(price,city))
assert "city like
''%furt''",like("city","%furt")
assert "city like
''%furt%''",like("city","%furt%")
assert "city like
''furt%''",like("city","furt%")
assert nil,like("city","%")
assert nil,like("city","%%")
print("\nReady!")
--
Posted via http://www.ruby-forum.com/.
Cool stuff! On Dec 2, 2005, at 12:29 AM, Christer Nilsson wrote:> Ezra, this is just a first approximation. No handling of numbers. No > handling of sql inject. Could you please give me a hint? > > def zand(*arg) > arg.delete(nil) > arg.join(" and ") > end > > def zor(*arg) > arg.delete(nil) > arg.nil? ? nil : "(#{arg.join(" or ")})" > end > > def eq(a,b) > b.nil? ? nil : "#{a}=''#{b}''" > end > > def lt(a,b) > b.nil? ? nil : "#{a}<=''#{b}''" > enddef <(a,b) b.nil? ? nil : "#{a}<=''#{b}''" end> > def gt(a,b) > b.nil? ? nil : "#{a}>=''#{b}''" > enddef >(a,b) b.nil? ? nil : "#{a}>=''#{b}'' end I have some other code I wrote last night as well. Let me clean it up and I''ll show it to you. -Ezra> def zin(a,b) > b.empty? ? nil : "#{a} in (#{b.join(",")})" > end > > def between(a,b,c) > zand(gt(a,b),lt(a,c)) > end > > def like(a,b) > case b > when b.nil?, "%", "%%" > nil > else > "#{a} like ''#{b}''" > end > end > > def assert(a,b) > a==b ? print(".") : print("\nexpected: #{a}\nactual: #{b}\n") > end > > assert "price>=''500'' and price<=''1000''", between("price","500","1000") > assert "price>=''100'' and price<=''500''", zand(gt("price","100"), > lt("price","500")) > assert "rooms in (1,2,3)", zin("rooms",[1,2,3]) > assert nil, zin("rooms",[]) > assert "size>=''100''", gt("size","100") > assert "size<=''500''", lt("size","500") > assert "price<=''500''", zand(gt("price",nil), lt("price","500")) > assert "", zand(gt("price",nil), lt("price",nil)) > > size = zand(gt("size","100"), lt("size","150")) > price = zand(gt("price",nil), lt("price","500")) > city = eq("city","Berlin") > assert "size>=''100'' and size<=''150'' and (price<=''500'' or > city=''Berlin'')",zand(size,zor(price,city)) > > assert "city like ''%furt''",like("city","%furt") > assert "city like ''%furt%''",like("city","%furt%") > assert "city like ''furt%''",like("city","furt%") > assert nil,like("city","%") > assert nil,like("city","%%") > > print("\nReady!") > > -- > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-Ezra Zygmuntowicz Yakima Herald-Republic WebMaster http://yakimaherald.com 509-577-7732 ezra-gdxLOakOTQ9oetBuM9ipNAC/G2K4zDHf@public.gmane.org
Julian ''Julik'' Tarkhanov
2005-Dec-04 23:29 UTC
Re: Re: Newbie: Building conditions from form
On 1-dec-2005, at 21:28, Hogan, Brian P. wrote:> Agreed. > > -----Original Message----- > From: rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > [mailto:rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Bruce Balmer > Sent: Thursday, December 01, 2005 1:31 PM > To: rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > Subject: Re: [Rails] Re: Newbie: Building conditions from form > > > I find the apparently common dislike of SQL surprising. To me, SQL is > a language much like css. Very compact. Very logical (therefore easy > to retain) and very powerful.It''s not about readability, SQL is very elegant and readable. it''s about composing the needed query _programmatically_ with minimum fuss, adding conditions and operators as they are needed, conditionally or in batches. Whuc, in current Rails, IS clunky. I think I''ve seen a Query plugin somewhere on the web but I just can''t trace it. Maybe it was announced on the list as well. -- Julian ''Julik'' Tarkhanov me at julik.nl